summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/focus.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/focus.js')
-rw-r--r--devtools/client/shared/focus.js73
1 files changed, 73 insertions, 0 deletions
diff --git a/devtools/client/shared/focus.js b/devtools/client/shared/focus.js
new file mode 100644
index 0000000000..68bcc8e7be
--- /dev/null
+++ b/devtools/client/shared/focus.js
@@ -0,0 +1,73 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+/*
+ * Simplied selector targetting elements that can receive the focus, full
+ * version at http://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus
+ */
+const focusableSelector = [
+ "a[href]:not([tabindex='-1'])",
+ "button:not([disabled], [tabindex='-1'])",
+ "iframe:not([tabindex='-1'])",
+ "input:not([disabled], [tabindex='-1'])",
+ "select:not([disabled], [tabindex='-1'])",
+ "textarea:not([disabled], [tabindex='-1'])",
+ "[tabindex]:not([tabindex='-1'])",
+].join(", ");
+
+/**
+ * Wrap and move keyboard focus to first/last focusable element inside a container
+ * element to prevent the focus from escaping the container.
+ *
+ * @param {Array} elms
+ * focusable elements inside a container
+ * @param {DOMNode} current
+ * currently focused element inside containter
+ * @param {Boolean} back
+ * direction
+ * @return {DOMNode}
+ * newly focused element
+ */
+function wrapMoveFocus(elms, current, back) {
+ let next;
+
+ if (elms.length === 0) {
+ return false;
+ }
+
+ if (back) {
+ if (elms.indexOf(current) === 0) {
+ next = elms[elms.length - 1];
+ next.focus();
+ }
+ } else if (elms.indexOf(current) === elms.length - 1) {
+ next = elms[0];
+ next.focus();
+ }
+
+ return next;
+}
+
+/**
+ * Get a list of all elements that are focusable with a keyboard inside the parent element
+ *
+ * @param {DOMNode} parentEl
+ * parent DOM element to be queried
+ * @return {Array}
+ * array of focusable children elements inside the parent
+ */
+function getFocusableElements(parentEl) {
+ return parentEl
+ ? Array.from(parentEl.querySelectorAll(focusableSelector))
+ : [];
+}
+
+// Make this available to both AMD and CJS environments
+define(function(require, exports, module) {
+ module.exports.focusableSelector = focusableSelector;
+ exports.wrapMoveFocus = wrapMoveFocus;
+ exports.getFocusableElements = getFocusableElements;
+});