@atlassian/aui
Version:
Atlassian User Interface Framework
175 lines (141 loc) • 6.15 kB
JavaScript
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define(['module', 'exports', './jquery', './internal/globalize'], factory);
} else if (typeof exports !== "undefined") {
factory(module, exports, require('./jquery'), require('./internal/globalize'));
} else {
var mod = {
exports: {}
};
factory(mod, mod.exports, global.jquery, global.globalize);
global.focusManager = mod.exports;
}
})(this, function (module, exports, _jquery, _globalize) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _jquery2 = _interopRequireDefault(_jquery);
var _globalize2 = _interopRequireDefault(_globalize);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
(function initSelectors() {
/*
:tabbable and :focusable functions from jQuery UI v 1.10.4
renamed to :aui-tabbable and :aui-focusable to not clash with jquery-ui if it's included.
Code modified slightly to be compatible with jQuery < 1.8
.addBack() replaced with .andSelf()
$.curCSS() replaced with $.css()
*/
function visible(element) {
return _jquery2.default.css(element, 'visibility') === 'visible';
}
function focusable(element, isTabIndexNotNaN) {
var nodeName = element.nodeName.toLowerCase();
if (nodeName === 'aui-select') {
return true;
}
if (nodeName === 'area') {
var map = element.parentNode;
var mapName = map.name;
var imageMap = (0, _jquery2.default)('img[usemap=#' + mapName + ']').get();
if (!element.href || !mapName || map.nodeName.toLowerCase() !== 'map') {
return false;
}
return imageMap && visible(imageMap);
}
var isFormElement = /input|select|textarea|button|object/.test(nodeName);
var isAnchor = nodeName === 'a';
var isAnchorTabbable = element.href || isTabIndexNotNaN;
return (isFormElement ? !element.disabled : isAnchor ? isAnchorTabbable : isTabIndexNotNaN) && visible(element);
}
function tabbable(element) {
var tabIndex = _jquery2.default.attr(element, 'tabindex');
var isTabIndexNaN = isNaN(tabIndex);
var hasTabIndex = isTabIndexNaN || tabIndex >= 0;
return hasTabIndex && focusable(element, !isTabIndexNaN);
}
_jquery2.default.extend(_jquery2.default.expr[':'], {
'aui-focusable': function auiFocusable(element) {
return focusable(element, !isNaN(_jquery2.default.attr(element, 'tabindex')));
},
'aui-tabbable': tabbable
});
})();
var RESTORE_FOCUS_DATA_KEY = '_aui-focus-restore';
function FocusManager() {
this._focusTrapStack = [];
(0, _jquery2.default)(document).on('focusout', { focusTrapStack: this._focusTrapStack }, focusTrapHandler);
}
FocusManager.defaultFocusSelector = ':aui-tabbable';
FocusManager.prototype.enter = function ($el) {
// remember focus on old element
$el.data(RESTORE_FOCUS_DATA_KEY, (0, _jquery2.default)(document.activeElement));
// focus on new selector
if ($el.attr('data-aui-focus') !== 'false') {
var focusSelector = $el.attr('data-aui-focus-selector') || FocusManager.defaultFocusSelector;
var $focusEl = $el.is(focusSelector) ? $el : $el.find(focusSelector);
$focusEl.first().focus();
}
if (elementTrapsFocus($el)) {
trapFocus($el, this._focusTrapStack);
}
};
function trapFocus($el, focusTrapStack) {
focusTrapStack.push($el);
}
function untrapFocus(focusTrapStack) {
focusTrapStack.pop();
}
function elementTrapsFocus($el) {
return $el.is('.aui-dialog2');
}
FocusManager.prototype.exit = function ($el) {
if (elementTrapsFocus($el)) {
untrapFocus(this._focusTrapStack);
}
// AUI-1059: remove focus from the active element when dialog is hidden
var activeElement = document.activeElement;
if ($el[0] === activeElement || $el.has(activeElement).length) {
(0, _jquery2.default)(activeElement).blur();
}
var $restoreFocus = $el.data(RESTORE_FOCUS_DATA_KEY);
if ($restoreFocus && $restoreFocus.length) {
$el.removeData(RESTORE_FOCUS_DATA_KEY);
$restoreFocus.focus();
}
};
function focusTrapHandler(event) {
var focusTrapStack = event.data.focusTrapStack;
if (!event.relatedTarget) {
//Does not work in firefox, see https://bugzilla.mozilla.org/show_bug.cgi?id=687787
return;
}
if (focusTrapStack.length === 0) {
return;
}
var $focusTrapElement = focusTrapStack[focusTrapStack.length - 1];
var focusOrigin = event.target;
var focusTo = event.relatedTarget;
var $tabbableElements = $focusTrapElement.find(':aui-tabbable');
var $firstTabbableElement = (0, _jquery2.default)($tabbableElements.first());
var $lastTabbableElement = (0, _jquery2.default)($tabbableElements.last());
var elementContainsOrigin = $focusTrapElement.has(focusTo).length === 0;
var focusLeavingElement = elementContainsOrigin && focusTo;
if (focusLeavingElement) {
if ($firstTabbableElement.is(focusOrigin)) {
$lastTabbableElement.focus();
} else if ($lastTabbableElement.is(focusOrigin)) {
$firstTabbableElement.focus();
}
}
}
FocusManager.global = new FocusManager();
(0, _globalize2.default)('FocusManager', FocusManager);
exports.default = FocusManager;
module.exports = exports['default'];
});
//# sourceMappingURL=focus-manager.js.map