Skip to content

Commit c6cf28a

Browse files
committed
Prepare release v0.6.0
1 parent 627b22b commit c6cf28a

File tree

5 files changed

+258
-184
lines changed

5 files changed

+258
-184
lines changed

Diff for: dist/ctrly.esm.js

+127-90
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*!
2-
* ctrly v0.5.0
2+
* ctrly v0.6.0
33
* Copyright (c) 2018 Jan Sorgalla
44
* License: MIT
55
*/
@@ -50,14 +50,6 @@ function focus(element) {
5050
}
5151
}
5252

53-
function find(selector, element) {
54-
var context = arguments.length > 1 ? element : document;
55-
if (!context || typeof context.querySelectorAll !== 'function') {
56-
return [];
57-
}
58-
return [].slice.call(context.querySelectorAll(selector));
59-
}
60-
6153
function matches(element, selector) {
6254
if (!element) {
6355
return false;
@@ -85,6 +77,72 @@ function closest(element, selector) {
8577
return null;
8678
}
8779

80+
function find(selector, element) {
81+
var context = arguments.length > 1 ? element : document;
82+
if (!context || typeof context.querySelectorAll !== 'function') {
83+
return [];
84+
}
85+
return [].slice.call(context.querySelectorAll(selector));
86+
}
87+
88+
var selector = ['a[href]',
89+
'area[href]', 'input', 'select', 'textarea', 'button', 'iframe', 'object', 'audio[controls]', 'video[controls]', '[contenteditable]', '[tabindex]'].join(',');
90+
var inputNodeNameRegexp = /^(input|select|textarea|button|object)$/;
91+
function focusableFilter(element) {
92+
var nodeName = element.nodeName.toLowerCase();
93+
if (nodeName === 'area') {
94+
return isValidArea(element);
95+
}
96+
if (element.disabled) {
97+
return false;
98+
}
99+
if (inputNodeNameRegexp.test(nodeName)) {
100+
var fieldset = closest(element, 'fieldset');
101+
if (fieldset && fieldset.disabled) {
102+
return false;
103+
}
104+
}
105+
return visible(element);
106+
}
107+
function tabbableFilter(element) {
108+
var index = tabIndex(element);
109+
return focusableFilter(element) && index >= 0;
110+
}
111+
function compare(a, b) {
112+
var aIndex = tabIndex(a, true);
113+
var bIndex = tabIndex(b, true);
114+
if (aIndex === bIndex) {
115+
return a.compareDocumentPosition(b) & 2 ? 1 : -1;
116+
}
117+
return aIndex - bIndex;
118+
}
119+
function isValidArea(element) {
120+
var map = element.parentNode;
121+
var mapName = map.name;
122+
if (!element.href || !mapName || map.nodeName.toLowerCase() !== 'map') {
123+
return false;
124+
}
125+
var images = find("img[usemap=\"#".concat(mapName, "\"]"));
126+
return images.length > 0 && visible(images[0]);
127+
}
128+
function visible(element) {
129+
var style = getComputedStyle(element);
130+
return (
131+
style.visibility !== 'hidden' && style.visibility !== 'collapse' && style.display !== 'none' && parents(element).every(function (el) {
132+
return getComputedStyle(el).display !== 'none';
133+
})
134+
);
135+
}
136+
function tabIndex(element) {
137+
var positiveOnly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
138+
var index = parseInt(element.getAttribute('tabindex'), 10);
139+
return isNaN(index) ? 0 : positiveOnly && index < 0 ? 0 : index;
140+
}
141+
142+
function isTabbable(element) {
143+
return matches(element, selector) && tabbableFilter(element);
144+
}
145+
88146
var supportedOptions;
89147
function optionsSupport() {
90148
if (supportedOptions) {
@@ -219,60 +277,6 @@ function ready(listener) {
219277
}));
220278
}
221279

222-
var selector = ['a[href]',
223-
'area[href]', 'input', 'select', 'textarea', 'button', 'iframe', 'object', 'audio[controls]', 'video[controls]', '[contenteditable]', '[tabindex]'].join(',');
224-
var inputNodeNameRegexp = /^(input|select|textarea|button|object)$/;
225-
function focusableFilter(element) {
226-
var nodeName = element.nodeName.toLowerCase();
227-
if (nodeName === 'area') {
228-
return isValidArea(element);
229-
}
230-
if (element.disabled) {
231-
return false;
232-
}
233-
if (inputNodeNameRegexp.test(nodeName)) {
234-
var fieldset = closest(element, 'fieldset');
235-
if (fieldset && fieldset.disabled) {
236-
return false;
237-
}
238-
}
239-
return visible(element);
240-
}
241-
function tabbableFilter(element) {
242-
var index = tabIndex(element);
243-
return focusableFilter(element) && index >= 0;
244-
}
245-
function compare(a, b) {
246-
var aIndex = tabIndex(a, true);
247-
var bIndex = tabIndex(b, true);
248-
if (aIndex === bIndex) {
249-
return a.compareDocumentPosition(b) & 2 ? 1 : -1;
250-
}
251-
return aIndex - bIndex;
252-
}
253-
function isValidArea(element) {
254-
var map = element.parentNode;
255-
var mapName = map.name;
256-
if (!element.href || !mapName || map.nodeName.toLowerCase() !== 'map') {
257-
return false;
258-
}
259-
var images = find("img[usemap=\"#".concat(mapName, "\"]"));
260-
return images.length > 0 && visible(images[0]);
261-
}
262-
function visible(element) {
263-
var style = getComputedStyle(element);
264-
return (
265-
style.visibility !== 'hidden' && style.visibility !== 'collapse' && style.display !== 'none' && parents(element).every(function (el) {
266-
return getComputedStyle(el).display !== 'none';
267-
})
268-
);
269-
}
270-
function tabIndex(element) {
271-
var positiveOnly = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
272-
var index = parseInt(element.getAttribute('tabindex'), 10);
273-
return isNaN(index) ? 0 : positiveOnly && index < 0 ? 0 : index;
274-
}
275-
276280
function tabbable(element) {
277281
return find(selector, arguments.length > 0 ? element : document).filter(tabbableFilter).sort(compare);
278282
}
@@ -312,6 +316,7 @@ function findTarget(control) {
312316
return document.getElementById(control.getAttribute('aria-controls') || control.getAttribute('data-ctrly'));
313317
}
314318
function resetControl(control) {
319+
control.removeAttribute('aria-pressed');
315320
control.removeAttribute('aria-controls');
316321
control.removeAttribute('aria-expanded');
317322
}
@@ -368,6 +373,9 @@ function ctrly() {
368373
destroy();
369374
}
370375
findControls(target).forEach(function (c) {
376+
if (c.tagName.toLowerCase() !== 'button') {
377+
c.setAttribute('aria-pressed', 'false');
378+
}
371379
c.setAttribute('aria-expanded', 'false');
372380
});
373381
target.removeAttribute('data-ctrly-opened');
@@ -395,7 +403,9 @@ function ctrly() {
395403
if (options.closeOnBlur && !options.trapFocus) {
396404
removeFuncs.push(on(document, 'focusin', function (e) {
397405
if (!target.contains(e.target)) {
398-
close(target, false);
406+
setTimeout(function () {
407+
close(target, false);
408+
}, 0);
399409
}
400410
}, {
401411
capture: true,
@@ -494,6 +504,9 @@ function ctrly() {
494504
destroy: addEventListeners(control, target)
495505
};
496506
findControls(target).forEach(function (c) {
507+
if (c.tagName.toLowerCase() !== 'button') {
508+
c.setAttribute('aria-pressed', 'true');
509+
}
497510
c.setAttribute('aria-expanded', 'true');
498511
});
499512
target.setAttribute('data-ctrly-opened', '');
@@ -502,38 +515,49 @@ function ctrly() {
502515
trigger(target, 'opened');
503516
return target;
504517
}
518+
function toggle(e, control) {
519+
var target = findTarget(control);
520+
if (!target) {
521+
if (close(findParentTarget(control))) {
522+
e.preventDefault();
523+
}
524+
return;
525+
}
526+
if (control.getAttribute('aria-expanded') === 'true') {
527+
if (close(target)) {
528+
e.preventDefault();
529+
}
530+
return;
531+
}
532+
if (!options.allowMultiple) {
533+
closeOthers(target);
534+
}
535+
open(control);
536+
if (target) {
537+
e.preventDefault();
538+
if (options.focusTarget) {
539+
focus(tabbable(target)[0] || target);
540+
}
541+
target.scrollTop = 0;
542+
target.scrollLeft = 0;
543+
}
544+
}
505545
var removeControlClick;
546+
var removeControlKeypress;
506547
function init() {
507548
if (!removeControlClick) {
508549
removeControlClick = delegate(document, 'click', controlSelector, function (e, control) {
509-
if (keyCode(e) !== 1) {
510-
return;
511-
}
512-
var target = findTarget(control);
513-
if (!target) {
514-
if (close(findParentTarget(control))) {
515-
e.preventDefault();
550+
if (keyCode(e) === 1
551+
) {
552+
toggle(e, control);
516553
}
517-
return;
518-
}
519-
if (control.getAttribute('aria-expanded') === 'true') {
520-
if (close(target)) {
521-
e.preventDefault();
522-
}
523-
return;
524-
}
525-
if (!options.allowMultiple) {
526-
closeOthers(target);
527-
}
528-
open(control);
529-
if (target) {
530-
e.preventDefault();
531-
if (options.focusTarget) {
532-
focus(tabbable(target)[0] || target);
554+
});
555+
removeControlKeypress = delegate(document, 'keypress', controlSelector, function (e, control) {
556+
if (keyCode(e) === 13
557+
|| keyCode(e) === 32
558+
) {
559+
toggle(e, control);
533560
}
534-
target.scrollTop = 0;
535-
target.scrollLeft = 0;
536-
}
537561
});
538562
}
539563
find(controlSelector).forEach(function (control) {
@@ -542,6 +566,14 @@ function ctrly() {
542566
resetControl(control);
543567
return;
544568
}
569+
if (control.tagName.toLowerCase() !== 'button') {
570+
if (!control.hasAttribute('role')) {
571+
control.setAttribute('role', 'button');
572+
}
573+
if (!isTabbable(control)) {
574+
control.setAttribute('tabindex', '0');
575+
}
576+
}
545577
control.setAttribute('aria-controls', target.id);
546578
var labelledBy = findControls(target).map(function (control) {
547579
if (!control.id) {
@@ -557,6 +589,9 @@ function ctrly() {
557589
open(control);
558590
return;
559591
}
592+
if (control.tagName.toLowerCase() !== 'button') {
593+
control.setAttribute('aria-pressed', 'false');
594+
}
560595
control.setAttribute('aria-expanded', 'false');
561596
target.setAttribute('aria-hidden', 'true');
562597
target.removeAttribute('tabindex');
@@ -566,6 +601,8 @@ function ctrly() {
566601
if (fullReset && removeControlClick) {
567602
removeControlClick();
568603
removeControlClick = null;
604+
removeControlKeypress();
605+
removeControlKeypress = null;
569606
}
570607
find(controlSelector).forEach(function (control) {
571608
if (fullReset) {

0 commit comments

Comments
 (0)