focus.mjs (1930B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 * Simplied selector targetting elements that can receive the focus, full 7 * version at http://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus 8 */ 9 const focusableSelector = [ 10 "a[href]:not([tabindex='-1'])", 11 "button:not([disabled], [tabindex='-1'])", 12 "iframe:not([tabindex='-1'])", 13 "input:not([disabled], [tabindex='-1'])", 14 "select:not([disabled], [tabindex='-1'])", 15 "textarea:not([disabled], [tabindex='-1'])", 16 "[tabindex]:not([tabindex='-1'])", 17 ].join(", "); 18 19 /** 20 * Wrap and move keyboard focus to first/last focusable element inside a container 21 * element to prevent the focus from escaping the container. 22 * 23 * @param {Array} elms 24 * focusable elements inside a container 25 * @param {DOMNode} current 26 * currently focused element inside containter 27 * @param {boolean} back 28 * direction 29 * @return {DOMNode} 30 * newly focused element 31 */ 32 function wrapMoveFocus(elms, current, back) { 33 let next; 34 35 if (elms.length === 0) { 36 return false; 37 } 38 39 if (back) { 40 if (elms.indexOf(current) === 0) { 41 next = elms[elms.length - 1]; 42 next.focus(); 43 } 44 } else if (elms.indexOf(current) === elms.length - 1) { 45 next = elms[0]; 46 next.focus(); 47 } 48 49 return next; 50 } 51 52 /** 53 * Get a list of all elements that are focusable with a keyboard inside the parent element 54 * 55 * @param {DOMNode} parentEl 56 * parent DOM element to be queried 57 * @return {Array} 58 * array of focusable children elements inside the parent 59 */ 60 function getFocusableElements(parentEl) { 61 return parentEl 62 ? Array.from(parentEl.querySelectorAll(focusableSelector)) 63 : []; 64 } 65 66 export { focusableSelector, wrapMoveFocus, getFocusableElements };