X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=web%2Fcore%2Fmisc%2Ftabbingmanager.js;fp=web%2Fcore%2Fmisc%2Ftabbingmanager.js;h=2d0b92716d96656617b6bffe15a0ca70d6a78b48;hp=134523f5bf97b320a421dc670a99d2f336650308;hb=9917807b03b64faf00f6a1f29dcb6eafc454efa5;hpb=aea91e65e895364e460983b890e295aa5d5540a5 diff --git a/web/core/misc/tabbingmanager.js b/web/core/misc/tabbingmanager.js index 134523f5b..2d0b92716 100644 --- a/web/core/misc/tabbingmanager.js +++ b/web/core/misc/tabbingmanager.js @@ -1,184 +1,72 @@ /** - * @file - * Manages page tabbing modifications made by modules. - */ - -/** - * Allow modules to respond to the constrain event. - * - * @event drupalTabbingConstrained - */ - -/** - * Allow modules to respond to the tabbingContext release event. - * - * @event drupalTabbingContextReleased - */ - -/** - * Allow modules to respond to the constrain event. - * - * @event drupalTabbingContextActivated - */ - -/** - * Allow modules to respond to the constrain event. - * - * @event drupalTabbingContextDeactivated - */ +* DO NOT EDIT THIS FILE. +* See the following change record for more information, +* https://www.drupal.org/node/2815083 +* @preserve +**/ (function ($, Drupal) { - - 'use strict'; - - /** - * Provides an API for managing page tabbing order modifications. - * - * @constructor Drupal~TabbingManager - */ function TabbingManager() { - - /** - * Tabbing sets are stored as a stack. The active set is at the top of the - * stack. We use a JavaScript array as if it were a stack; we consider the - * first element to be the bottom and the last element to be the top. This - * allows us to use JavaScript's built-in Array.push() and Array.pop() - * methods. - * - * @type {Array.} - */ this.stack = []; } - /** - * Add public methods to the TabbingManager class. - */ - $.extend(TabbingManager.prototype, /** @lends Drupal~TabbingManager# */{ - - /** - * Constrain tabbing to the specified set of elements only. - * - * Makes elements outside of the specified set of elements unreachable via - * the tab key. - * - * @param {jQuery} elements - * The set of elements to which tabbing should be constrained. Can also - * be a jQuery-compatible selector string. - * - * @return {Drupal~TabbingContext} - * The TabbingContext instance. - * - * @fires event:drupalTabbingConstrained - */ - constrain: function (elements) { - // Deactivate all tabbingContexts to prepare for the new constraint. A - // tabbingContext instance will only be reactivated if the stack is - // unwound to it in the _unwindStack() method. + $.extend(TabbingManager.prototype, { + constrain: function constrain(elements) { var il = this.stack.length; for (var i = 0; i < il; i++) { this.stack[i].deactivate(); } - // The "active tabbing set" are the elements tabbing should be constrained - // to. var $elements = $(elements).find(':tabbable').addBack(':tabbable'); var tabbingContext = new TabbingContext({ - // The level is the current height of the stack before this new - // tabbingContext is pushed on top of the stack. level: this.stack.length, $tabbableElements: $elements }); this.stack.push(tabbingContext); - // Activates the tabbingContext; this will manipulate the DOM to constrain - // tabbing. tabbingContext.activate(); - // Allow modules to respond to the constrain event. $(document).trigger('drupalTabbingConstrained', tabbingContext); return tabbingContext; }, - - /** - * Restores a former tabbingContext when an active one is released. - * - * The TabbingManager stack of tabbingContext instances will be unwound - * from the top-most released tabbingContext down to the first non-released - * tabbingContext instance. This non-released instance is then activated. - */ - release: function () { - // Unwind as far as possible: find the topmost non-released - // tabbingContext. + release: function release() { var toActivate = this.stack.length - 1; while (toActivate >= 0 && this.stack[toActivate].released) { toActivate--; } - // Delete all tabbingContexts after the to be activated one. They have - // already been deactivated, so their effect on the DOM has been reversed. this.stack.splice(toActivate + 1); - // Get topmost tabbingContext, if one exists, and activate it. if (toActivate >= 0) { this.stack[toActivate].activate(); } }, - - /** - * Makes all elements outside of the tabbingContext's set untabbable. - * - * Elements made untabbable have their original tabindex and autofocus - * values stored so that they might be restored later when this - * tabbingContext is deactivated. - * - * @param {Drupal~TabbingContext} tabbingContext - * The TabbingContext instance that has been activated. - */ - activate: function (tabbingContext) { + activate: function activate(tabbingContext) { var $set = tabbingContext.$tabbableElements; var level = tabbingContext.level; - // Determine which elements are reachable via tabbing by default. - var $disabledSet = $(':tabbable') - // Exclude elements of the active tabbing set. - .not($set); - // Set the disabled set on the tabbingContext. + + var $disabledSet = $(':tabbable').not($set); + tabbingContext.$disabledElements = $disabledSet; - // Record the tabindex for each element, so we can restore it later. + var il = $disabledSet.length; for (var i = 0; i < il; i++) { this.recordTabindex($disabledSet.eq(i), level); } - // Make all tabbable elements outside of the active tabbing set - // unreachable. - $disabledSet - .prop('tabindex', -1) - .prop('autofocus', false); - // Set focus on an element in the tabbingContext's set of tabbable - // elements. First, check if there is an element with an autofocus - // attribute. Select the last one from the DOM order. + $disabledSet.prop('tabindex', -1).prop('autofocus', false); + var $hasFocus = $set.filter('[autofocus]').eq(-1); - // If no element in the tabbable set has an autofocus attribute, select - // the first element in the set. + if ($hasFocus.length === 0) { $hasFocus = $set.eq(0); } $hasFocus.trigger('focus'); }, - - /** - * Restores that tabbable state of a tabbingContext's disabled elements. - * - * Elements that were made untabbable have their original tabindex and - * autofocus values restored. - * - * @param {Drupal~TabbingContext} tabbingContext - * The TabbingContext instance that has been deactivated. - */ - deactivate: function (tabbingContext) { + deactivate: function deactivate(tabbingContext) { var $set = tabbingContext.$disabledElements; var level = tabbingContext.level; var il = $set.length; @@ -186,16 +74,7 @@ this.restoreTabindex($set.eq(i), level); } }, - - /** - * Records the tabindex and autofocus values of an untabbable element. - * - * @param {jQuery} $el - * The set of elements that have been disabled. - * @param {number} level - * The stack level for which the tabindex attribute should be recorded. - */ - recordTabindex: function ($el, level) { + recordTabindex: function recordTabindex($el, level) { var tabInfo = $el.data('drupalOriginalTabIndices') || {}; tabInfo[level] = { tabindex: $el[0].getAttribute('tabindex'), @@ -203,38 +82,22 @@ }; $el.data('drupalOriginalTabIndices', tabInfo); }, - - /** - * Restores the tabindex and autofocus values of a reactivated element. - * - * @param {jQuery} $el - * The element that is being reactivated. - * @param {number} level - * The stack level for which the tabindex attribute should be restored. - */ - restoreTabindex: function ($el, level) { + restoreTabindex: function restoreTabindex($el, level) { var tabInfo = $el.data('drupalOriginalTabIndices'); if (tabInfo && tabInfo[level]) { var data = tabInfo[level]; if (data.tabindex) { $el[0].setAttribute('tabindex', data.tabindex); - } - // If the element did not have a tabindex at this stack level then - // remove it. - else { - $el[0].removeAttribute('tabindex'); - } + } else { + $el[0].removeAttribute('tabindex'); + } if (data.autofocus) { $el[0].setAttribute('autofocus', 'autofocus'); } - // Clean up $.data. if (level === 0) { - // Remove all data. $el.removeData('drupalOriginalTabIndices'); - } - else { - // Remove the data for this stack level and higher. + } else { var levelToDelete = level; while (tabInfo.hasOwnProperty(levelToDelete)) { delete tabInfo[levelToDelete]; @@ -246,124 +109,51 @@ } }); - /** - * Stores a set of tabbable elements. - * - * This constraint can be removed with the release() method. - * - * @constructor Drupal~TabbingContext - * - * @param {object} options - * A set of initiating values - * @param {number} options.level - * The level in the TabbingManager's stack of this tabbingContext. - * @param {jQuery} options.$tabbableElements - * The DOM elements that should be reachable via the tab key when this - * tabbingContext is active. - * @param {jQuery} options.$disabledElements - * The DOM elements that should not be reachable via the tab key when this - * tabbingContext is active. - * @param {bool} options.released - * A released tabbingContext can never be activated again. It will be - * cleaned up when the TabbingManager unwinds its stack. - * @param {bool} options.active - * When true, the tabbable elements of this tabbingContext will be reachable - * via the tab key and the disabled elements will not. Only one - * tabbingContext can be active at a time. - */ function TabbingContext(options) { - - $.extend(this, /** @lends Drupal~TabbingContext# */{ - - /** - * @type {?number} - */ + $.extend(this, { level: null, - /** - * @type {jQuery} - */ $tabbableElements: $(), - /** - * @type {jQuery} - */ $disabledElements: $(), - /** - * @type {bool} - */ released: false, - /** - * @type {bool} - */ active: false }, options); } - /** - * Add public methods to the TabbingContext class. - */ - $.extend(TabbingContext.prototype, /** @lends Drupal~TabbingContext# */{ - - /** - * Releases this TabbingContext. - * - * Once a TabbingContext object is released, it can never be activated - * again. - * - * @fires event:drupalTabbingContextReleased - */ - release: function () { + $.extend(TabbingContext.prototype, { + release: function release() { if (!this.released) { this.deactivate(); this.released = true; Drupal.tabbingManager.release(this); - // Allow modules to respond to the tabbingContext release event. + $(document).trigger('drupalTabbingContextReleased', this); } }, - - /** - * Activates this TabbingContext. - * - * @fires event:drupalTabbingContextActivated - */ - activate: function () { - // A released TabbingContext object can never be activated again. + activate: function activate() { if (!this.active && !this.released) { this.active = true; Drupal.tabbingManager.activate(this); - // Allow modules to respond to the constrain event. + $(document).trigger('drupalTabbingContextActivated', this); } }, - - /** - * Deactivates this TabbingContext. - * - * @fires event:drupalTabbingContextDeactivated - */ - deactivate: function () { + deactivate: function deactivate() { if (this.active) { this.active = false; Drupal.tabbingManager.deactivate(this); - // Allow modules to respond to the constrain event. + $(document).trigger('drupalTabbingContextDeactivated', this); } } }); - // Mark this behavior as processed on the first pass and return if it is - // already processed. if (Drupal.tabbingManager) { return; } - /** - * @type {Drupal~TabbingManager} - */ Drupal.tabbingManager = new TabbingManager(); - -}(jQuery, Drupal)); +})(jQuery, Drupal); \ No newline at end of file