summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/contextual/js
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/contextual/js')
-rw-r--r--core/modules/contextual/js/contextual.es6.js256
-rw-r--r--core/modules/contextual/js/contextual.js153
-rw-r--r--core/modules/contextual/js/contextual.toolbar.es6.js77
-rw-r--r--core/modules/contextual/js/contextual.toolbar.js42
-rw-r--r--core/modules/contextual/js/models/StateModel.es6.js132
-rw-r--r--core/modules/contextual/js/models/StateModel.js99
-rw-r--r--core/modules/contextual/js/toolbar/models/StateModel.es6.js119
-rw-r--r--core/modules/contextual/js/toolbar/models/StateModel.js93
-rw-r--r--core/modules/contextual/js/toolbar/views/AuralView.es6.js104
-rw-r--r--core/modules/contextual/js/toolbar/views/AuralView.js70
-rw-r--r--core/modules/contextual/js/toolbar/views/VisualView.es6.js84
-rw-r--r--core/modules/contextual/js/toolbar/views/VisualView.js66
-rw-r--r--core/modules/contextual/js/views/AuralView.es6.js55
-rw-r--r--core/modules/contextual/js/views/AuralView.js51
-rw-r--r--core/modules/contextual/js/views/KeyboardView.es6.js61
-rw-r--r--core/modules/contextual/js/views/KeyboardView.js51
-rw-r--r--core/modules/contextual/js/views/RegionView.es6.js57
-rw-r--r--core/modules/contextual/js/views/RegionView.js48
-rw-r--r--core/modules/contextual/js/views/VisualView.es6.js80
-rw-r--r--core/modules/contextual/js/views/VisualView.js73
20 files changed, 1187 insertions, 584 deletions
diff --git a/core/modules/contextual/js/contextual.es6.js b/core/modules/contextual/js/contextual.es6.js
new file mode 100644
index 000000000000..558ea105cc2f
--- /dev/null
+++ b/core/modules/contextual/js/contextual.es6.js
@@ -0,0 +1,256 @@
+/**
+ * @file
+ * Attaches behaviors for the Contextual module.
+ */
+
+(function ($, Drupal, drupalSettings, _, Backbone, JSON, storage) {
+
+ 'use strict';
+
+ var options = $.extend(drupalSettings.contextual,
+ // Merge strings on top of drupalSettings so that they are not mutable.
+ {
+ strings: {
+ open: Drupal.t('Open'),
+ close: Drupal.t('Close')
+ }
+ }
+ );
+
+ // Clear the cached contextual links whenever the current user's set of
+ // permissions changes.
+ var cachedPermissionsHash = storage.getItem('Drupal.contextual.permissionsHash');
+ var permissionsHash = drupalSettings.user.permissionsHash;
+ if (cachedPermissionsHash !== permissionsHash) {
+ if (typeof permissionsHash === 'string') {
+ _.chain(storage).keys().each(function (key) {
+ if (key.substring(0, 18) === 'Drupal.contextual.') {
+ storage.removeItem(key);
+ }
+ });
+ }
+ storage.setItem('Drupal.contextual.permissionsHash', permissionsHash);
+ }
+
+ /**
+ * Initializes a contextual link: updates its DOM, sets up model and views.
+ *
+ * @param {jQuery} $contextual
+ * A contextual links placeholder DOM element, containing the actual
+ * contextual links as rendered by the server.
+ * @param {string} html
+ * The server-side rendered HTML for this contextual link.
+ */
+ function initContextual($contextual, html) {
+ var $region = $contextual.closest('.contextual-region');
+ var contextual = Drupal.contextual;
+
+ $contextual
+ // Update the placeholder to contain its rendered contextual links.
+ .html(html)
+ // Use the placeholder as a wrapper with a specific class to provide
+ // positioning and behavior attachment context.
+ .addClass('contextual')
+ // Ensure a trigger element exists before the actual contextual links.
+ .prepend(Drupal.theme('contextualTrigger'));
+
+ // Set the destination parameter on each of the contextual links.
+ var destination = 'destination=' + Drupal.encodePath(drupalSettings.path.currentPath);
+ $contextual.find('.contextual-links a').each(function () {
+ var url = this.getAttribute('href');
+ var glue = (url.indexOf('?') === -1) ? '?' : '&';
+ this.setAttribute('href', url + glue + destination);
+ });
+
+ // Create a model and the appropriate views.
+ var model = new contextual.StateModel({
+ title: $region.find('h2').eq(0).text().trim()
+ });
+ var viewOptions = $.extend({el: $contextual, model: model}, options);
+ contextual.views.push({
+ visual: new contextual.VisualView(viewOptions),
+ aural: new contextual.AuralView(viewOptions),
+ keyboard: new contextual.KeyboardView(viewOptions)
+ });
+ contextual.regionViews.push(new contextual.RegionView(
+ $.extend({el: $region, model: model}, options))
+ );
+
+ // Add the model to the collection. This must happen after the views have
+ // been associated with it, otherwise collection change event handlers can't
+ // trigger the model change event handler in its views.
+ contextual.collection.add(model);
+
+ // Let other JavaScript react to the adding of a new contextual link.
+ $(document).trigger('drupalContextualLinkAdded', {
+ $el: $contextual,
+ $region: $region,
+ model: model
+ });
+
+ // Fix visual collisions between contextual link triggers.
+ adjustIfNestedAndOverlapping($contextual);
+ }
+
+ /**
+ * Determines if a contextual link is nested & overlapping, if so: adjusts it.
+ *
+ * This only deals with two levels of nesting; deeper levels are not touched.
+ *
+ * @param {jQuery} $contextual
+ * A contextual links placeholder DOM element, containing the actual
+ * contextual links as rendered by the server.
+ */
+ function adjustIfNestedAndOverlapping($contextual) {
+ var $contextuals = $contextual
+ // @todo confirm that .closest() is not sufficient
+ .parents('.contextual-region').eq(-1)
+ .find('.contextual');
+
+ // Early-return when there's no nesting.
+ if ($contextuals.length === 1) {
+ return;
+ }
+
+ // If the two contextual links overlap, then we move the second one.
+ var firstTop = $contextuals.eq(0).offset().top;
+ var secondTop = $contextuals.eq(1).offset().top;
+ if (firstTop === secondTop) {
+ var $nestedContextual = $contextuals.eq(1);
+
+ // Retrieve height of nested contextual link.
+ var height = 0;
+ var $trigger = $nestedContextual.find('.trigger');
+ // Elements with the .visually-hidden class have no dimensions, so this
+ // class must be temporarily removed to the calculate the height.
+ $trigger.removeClass('visually-hidden');
+ height = $nestedContextual.height();
+ $trigger.addClass('visually-hidden');
+
+ // Adjust nested contextual link's position.
+ $nestedContextual.css({top: $nestedContextual.position().top + height});
+ }
+ }
+
+ /**
+ * Attaches outline behavior for regions associated with contextual links.
+ *
+ * Events
+ * Contextual triggers an event that can be used by other scripts.
+ * - drupalContextualLinkAdded: Triggered when a contextual link is added.
+ *
+ * @type {Drupal~behavior}
+ *
+ * @prop {Drupal~behaviorAttach} attach
+ * Attaches the outline behavior to the right context.
+ */
+ Drupal.behaviors.contextual = {
+ attach: function (context) {
+ var $context = $(context);
+
+ // Find all contextual links placeholders, if any.
+ var $placeholders = $context.find('[data-contextual-id]').once('contextual-render');
+ if ($placeholders.length === 0) {
+ return;
+ }
+
+ // Collect the IDs for all contextual links placeholders.
+ var ids = [];
+ $placeholders.each(function () {
+ ids.push($(this).attr('data-contextual-id'));
+ });
+
+ // Update all contextual links placeholders whose HTML is cached.
+ var uncachedIDs = _.filter(ids, function initIfCached(contextualID) {
+ var html = storage.getItem('Drupal.contextual.' + contextualID);
+ if (html && html.length) {
+ // Initialize after the current execution cycle, to make the AJAX
+ // request for retrieving the uncached contextual links as soon as
+ // possible, but also to ensure that other Drupal behaviors have had
+ // the chance to set up an event listener on the Backbone collection
+ // Drupal.contextual.collection.
+ window.setTimeout(function () {
+ initContextual($context.find('[data-contextual-id="' + contextualID + '"]'), html);
+ });
+ return false;
+ }
+ return true;
+ });
+
+ // Perform an AJAX request to let the server render the contextual links
+ // for each of the placeholders.
+ if (uncachedIDs.length > 0) {
+ $.ajax({
+ url: Drupal.url('contextual/render'),
+ type: 'POST',
+ data: {'ids[]': uncachedIDs},
+ dataType: 'json',
+ success: function (results) {
+ _.each(results, function (html, contextualID) {
+ // Store the metadata.
+ storage.setItem('Drupal.contextual.' + contextualID, html);
+ // If the rendered contextual links are empty, then the current
+ // user does not have permission to access the associated links:
+ // don't render anything.
+ if (html.length > 0) {
+ // Update the placeholders to contain its rendered contextual
+ // links. Usually there will only be one placeholder, but it's
+ // possible for multiple identical placeholders exist on the
+ // page (probably because the same content appears more than
+ // once).
+ $placeholders = $context.find('[data-contextual-id="' + contextualID + '"]');
+
+ // Initialize the contextual links.
+ for (var i = 0; i < $placeholders.length; i++) {
+ initContextual($placeholders.eq(i), html);
+ }
+ }
+ });
+ }
+ });
+ }
+ }
+ };
+
+ /**
+ * Namespace for contextual related functionality.
+ *
+ * @namespace
+ */
+ Drupal.contextual = {
+
+ /**
+ * The {@link Drupal.contextual.View} instances associated with each list
+ * element of contextual links.
+ *
+ * @type {Array}
+ */
+ views: [],
+
+ /**
+ * The {@link Drupal.contextual.RegionView} instances associated with each
+ * contextual region element.
+ *
+ * @type {Array}
+ */
+ regionViews: []
+ };
+
+ /**
+ * A Backbone.Collection of {@link Drupal.contextual.StateModel} instances.
+ *
+ * @type {Backbone.Collection}
+ */
+ Drupal.contextual.collection = new Backbone.Collection([], {model: Drupal.contextual.StateModel});
+
+ /**
+ * A trigger is an interactive element often bound to a click handler.
+ *
+ * @return {string}
+ * A string representing a DOM fragment.
+ */
+ Drupal.theme.contextualTrigger = function () {
+ return '<button class="trigger visually-hidden focusable" type="button"></button>';
+ };
+
+})(jQuery, Drupal, drupalSettings, _, Backbone, window.JSON, window.sessionStorage);
diff --git a/core/modules/contextual/js/contextual.js b/core/modules/contextual/js/contextual.js
index 558ea105cc2f..7eb42ec3de0d 100644
--- a/core/modules/contextual/js/contextual.js
+++ b/core/modules/contextual/js/contextual.js
@@ -1,24 +1,22 @@
/**
- * @file
- * Attaches behaviors for the Contextual module.
- */
+* DO NOT EDIT THIS FILE.
+* All changes should be applied to ./modules/contextual/js/contextual.es6.js
+* See the following change record for more information,
+* https://www.drupal.org/node/2873849
+* @preserve
+**/
(function ($, Drupal, drupalSettings, _, Backbone, JSON, storage) {
'use strict';
- var options = $.extend(drupalSettings.contextual,
- // Merge strings on top of drupalSettings so that they are not mutable.
- {
- strings: {
- open: Drupal.t('Open'),
- close: Drupal.t('Close')
- }
+ var options = $.extend(drupalSettings.contextual, {
+ strings: {
+ open: Drupal.t('Open'),
+ close: Drupal.t('Close')
}
- );
+ });
- // Clear the cached contextual links whenever the current user's set of
- // permissions changes.
var cachedPermissionsHash = storage.getItem('Drupal.contextual.permissionsHash');
var permissionsHash = drupalSettings.user.permissionsHash;
if (cachedPermissionsHash !== permissionsHash) {
@@ -32,143 +30,81 @@
storage.setItem('Drupal.contextual.permissionsHash', permissionsHash);
}
- /**
- * Initializes a contextual link: updates its DOM, sets up model and views.
- *
- * @param {jQuery} $contextual
- * A contextual links placeholder DOM element, containing the actual
- * contextual links as rendered by the server.
- * @param {string} html
- * The server-side rendered HTML for this contextual link.
- */
function initContextual($contextual, html) {
var $region = $contextual.closest('.contextual-region');
var contextual = Drupal.contextual;
- $contextual
- // Update the placeholder to contain its rendered contextual links.
- .html(html)
- // Use the placeholder as a wrapper with a specific class to provide
- // positioning and behavior attachment context.
- .addClass('contextual')
- // Ensure a trigger element exists before the actual contextual links.
- .prepend(Drupal.theme('contextualTrigger'));
+ $contextual.html(html).addClass('contextual').prepend(Drupal.theme('contextualTrigger'));
- // Set the destination parameter on each of the contextual links.
var destination = 'destination=' + Drupal.encodePath(drupalSettings.path.currentPath);
$contextual.find('.contextual-links a').each(function () {
var url = this.getAttribute('href');
- var glue = (url.indexOf('?') === -1) ? '?' : '&';
+ var glue = url.indexOf('?') === -1 ? '?' : '&';
this.setAttribute('href', url + glue + destination);
});
- // Create a model and the appropriate views.
var model = new contextual.StateModel({
title: $region.find('h2').eq(0).text().trim()
});
- var viewOptions = $.extend({el: $contextual, model: model}, options);
+ var viewOptions = $.extend({ el: $contextual, model: model }, options);
contextual.views.push({
visual: new contextual.VisualView(viewOptions),
aural: new contextual.AuralView(viewOptions),
keyboard: new contextual.KeyboardView(viewOptions)
});
- contextual.regionViews.push(new contextual.RegionView(
- $.extend({el: $region, model: model}, options))
- );
+ contextual.regionViews.push(new contextual.RegionView($.extend({ el: $region, model: model }, options)));
- // Add the model to the collection. This must happen after the views have
- // been associated with it, otherwise collection change event handlers can't
- // trigger the model change event handler in its views.
contextual.collection.add(model);
- // Let other JavaScript react to the adding of a new contextual link.
$(document).trigger('drupalContextualLinkAdded', {
$el: $contextual,
$region: $region,
model: model
});
- // Fix visual collisions between contextual link triggers.
adjustIfNestedAndOverlapping($contextual);
}
- /**
- * Determines if a contextual link is nested & overlapping, if so: adjusts it.
- *
- * This only deals with two levels of nesting; deeper levels are not touched.
- *
- * @param {jQuery} $contextual
- * A contextual links placeholder DOM element, containing the actual
- * contextual links as rendered by the server.
- */
function adjustIfNestedAndOverlapping($contextual) {
- var $contextuals = $contextual
- // @todo confirm that .closest() is not sufficient
- .parents('.contextual-region').eq(-1)
- .find('.contextual');
+ var $contextuals = $contextual.parents('.contextual-region').eq(-1).find('.contextual');
- // Early-return when there's no nesting.
if ($contextuals.length === 1) {
return;
}
- // If the two contextual links overlap, then we move the second one.
var firstTop = $contextuals.eq(0).offset().top;
var secondTop = $contextuals.eq(1).offset().top;
if (firstTop === secondTop) {
var $nestedContextual = $contextuals.eq(1);
- // Retrieve height of nested contextual link.
var height = 0;
var $trigger = $nestedContextual.find('.trigger');
- // Elements with the .visually-hidden class have no dimensions, so this
- // class must be temporarily removed to the calculate the height.
+
$trigger.removeClass('visually-hidden');
height = $nestedContextual.height();
$trigger.addClass('visually-hidden');
- // Adjust nested contextual link's position.
- $nestedContextual.css({top: $nestedContextual.position().top + height});
+ $nestedContextual.css({ top: $nestedContextual.position().top + height });
}
}
- /**
- * Attaches outline behavior for regions associated with contextual links.
- *
- * Events
- * Contextual triggers an event that can be used by other scripts.
- * - drupalContextualLinkAdded: Triggered when a contextual link is added.
- *
- * @type {Drupal~behavior}
- *
- * @prop {Drupal~behaviorAttach} attach
- * Attaches the outline behavior to the right context.
- */
Drupal.behaviors.contextual = {
- attach: function (context) {
+ attach: function attach(context) {
var $context = $(context);
- // Find all contextual links placeholders, if any.
var $placeholders = $context.find('[data-contextual-id]').once('contextual-render');
if ($placeholders.length === 0) {
return;
}
- // Collect the IDs for all contextual links placeholders.
var ids = [];
$placeholders.each(function () {
ids.push($(this).attr('data-contextual-id'));
});
- // Update all contextual links placeholders whose HTML is cached.
var uncachedIDs = _.filter(ids, function initIfCached(contextualID) {
var html = storage.getItem('Drupal.contextual.' + contextualID);
if (html && html.length) {
- // Initialize after the current execution cycle, to make the AJAX
- // request for retrieving the uncached contextual links as soon as
- // possible, but also to ensure that other Drupal behaviors have had
- // the chance to set up an event listener on the Backbone collection
- // Drupal.contextual.collection.
window.setTimeout(function () {
initContextual($context.find('[data-contextual-id="' + contextualID + '"]'), html);
});
@@ -177,30 +113,19 @@
return true;
});
- // Perform an AJAX request to let the server render the contextual links
- // for each of the placeholders.
if (uncachedIDs.length > 0) {
$.ajax({
url: Drupal.url('contextual/render'),
type: 'POST',
- data: {'ids[]': uncachedIDs},
+ data: { 'ids[]': uncachedIDs },
dataType: 'json',
- success: function (results) {
+ success: function success(results) {
_.each(results, function (html, contextualID) {
- // Store the metadata.
storage.setItem('Drupal.contextual.' + contextualID, html);
- // If the rendered contextual links are empty, then the current
- // user does not have permission to access the associated links:
- // don't render anything.
+
if (html.length > 0) {
- // Update the placeholders to contain its rendered contextual
- // links. Usually there will only be one placeholder, but it's
- // possible for multiple identical placeholders exist on the
- // page (probably because the same content appears more than
- // once).
$placeholders = $context.find('[data-contextual-id="' + contextualID + '"]');
- // Initialize the contextual links.
for (var i = 0; i < $placeholders.length; i++) {
initContextual($placeholders.eq(i), html);
}
@@ -212,45 +137,15 @@
}
};
- /**
- * Namespace for contextual related functionality.
- *
- * @namespace
- */
Drupal.contextual = {
-
- /**
- * The {@link Drupal.contextual.View} instances associated with each list
- * element of contextual links.
- *
- * @type {Array}
- */
views: [],
- /**
- * The {@link Drupal.contextual.RegionView} instances associated with each
- * contextual region element.
- *
- * @type {Array}
- */
regionViews: []
};
- /**
- * A Backbone.Collection of {@link Drupal.contextual.StateModel} instances.
- *
- * @type {Backbone.Collection}
- */
- Drupal.contextual.collection = new Backbone.Collection([], {model: Drupal.contextual.StateModel});
+ Drupal.contextual.collection = new Backbone.Collection([], { model: Drupal.contextual.StateModel });
- /**
- * A trigger is an interactive element often bound to a click handler.
- *
- * @return {string}
- * A string representing a DOM fragment.
- */
Drupal.theme.contextualTrigger = function () {
return '<button class="trigger visually-hidden focusable" type="button"></button>';
};
-
-})(jQuery, Drupal, drupalSettings, _, Backbone, window.JSON, window.sessionStorage);
+})(jQuery, Drupal, drupalSettings, _, Backbone, window.JSON, window.sessionStorage); \ No newline at end of file
diff --git a/core/modules/contextual/js/contextual.toolbar.es6.js b/core/modules/contextual/js/contextual.toolbar.es6.js
new file mode 100644
index 000000000000..b5a9053490c0
--- /dev/null
+++ b/core/modules/contextual/js/contextual.toolbar.es6.js
@@ -0,0 +1,77 @@
+/**
+ * @file
+ * Attaches behaviors for the Contextual module's edit toolbar tab.
+ */
+
+(function ($, Drupal, Backbone) {
+
+ 'use strict';
+
+ var strings = {
+ tabbingReleased: Drupal.t('Tabbing is no longer constrained by the Contextual module.'),
+ tabbingConstrained: Drupal.t('Tabbing is constrained to a set of @contextualsCount and the edit mode toggle.'),
+ pressEsc: Drupal.t('Press the esc key to exit.')
+ };
+
+ /**
+ * Initializes a contextual link: updates its DOM, sets up model and views.
+ *
+ * @param {HTMLElement} context
+ * A contextual links DOM element as rendered by the server.
+ */
+ function initContextualToolbar(context) {
+ if (!Drupal.contextual || !Drupal.contextual.collection) {
+ return;
+ }
+
+ var contextualToolbar = Drupal.contextualToolbar;
+ var model = contextualToolbar.model = new contextualToolbar.StateModel({
+ // Checks whether localStorage indicates we should start in edit mode
+ // rather than view mode.
+ // @see Drupal.contextualToolbar.VisualView.persist
+ isViewing: localStorage.getItem('Drupal.contextualToolbar.isViewing') !== 'false'
+ }, {
+ contextualCollection: Drupal.contextual.collection
+ });
+
+ var viewOptions = {
+ el: $('.toolbar .toolbar-bar .contextual-toolbar-tab'),
+ model: model,
+ strings: strings
+ };
+ new contextualToolbar.VisualView(viewOptions);
+ new contextualToolbar.AuralView(viewOptions);
+ }
+
+ /**
+ * Attaches contextual's edit toolbar tab behavior.
+ *
+ * @type {Drupal~behavior}
+ *
+ * @prop {Drupal~behaviorAttach} attach
+ * Attaches contextual toolbar behavior on a contextualToolbar-init event.
+ */
+ Drupal.behaviors.contextualToolbar = {
+ attach: function (context) {
+ if ($('body').once('contextualToolbar-init').length) {
+ initContextualToolbar(context);
+ }
+ }
+ };
+
+ /**
+ * Namespace for the contextual toolbar.
+ *
+ * @namespace
+ */
+ Drupal.contextualToolbar = {
+
+ /**
+ * The {@link Drupal.contextualToolbar.StateModel} instance.
+ *
+ * @type {?Drupal.contextualToolbar.StateModel}
+ */
+ model: null
+ };
+
+})(jQuery, Drupal, Backbone);
diff --git a/core/modules/contextual/js/contextual.toolbar.js b/core/modules/contextual/js/contextual.toolbar.js
index b5a9053490c0..291a5a68c300 100644
--- a/core/modules/contextual/js/contextual.toolbar.js
+++ b/core/modules/contextual/js/contextual.toolbar.js
@@ -1,7 +1,10 @@
/**
- * @file
- * Attaches behaviors for the Contextual module's edit toolbar tab.
- */
+* DO NOT EDIT THIS FILE.
+* All changes should be applied to ./modules/contextual/js/contextual.toolbar.es6.js
+* See the following change record for more information,
+* https://www.drupal.org/node/2873849
+* @preserve
+**/
(function ($, Drupal, Backbone) {
@@ -13,12 +16,6 @@
pressEsc: Drupal.t('Press the esc key to exit.')
};
- /**
- * Initializes a contextual link: updates its DOM, sets up model and views.
- *
- * @param {HTMLElement} context
- * A contextual links DOM element as rendered by the server.
- */
function initContextualToolbar(context) {
if (!Drupal.contextual || !Drupal.contextual.collection) {
return;
@@ -26,9 +23,6 @@
var contextualToolbar = Drupal.contextualToolbar;
var model = contextualToolbar.model = new contextualToolbar.StateModel({
- // Checks whether localStorage indicates we should start in edit mode
- // rather than view mode.
- // @see Drupal.contextualToolbar.VisualView.persist
isViewing: localStorage.getItem('Drupal.contextualToolbar.isViewing') !== 'false'
}, {
contextualCollection: Drupal.contextual.collection
@@ -43,35 +37,15 @@
new contextualToolbar.AuralView(viewOptions);
}
- /**
- * Attaches contextual's edit toolbar tab behavior.
- *
- * @type {Drupal~behavior}
- *
- * @prop {Drupal~behaviorAttach} attach
- * Attaches contextual toolbar behavior on a contextualToolbar-init event.
- */
Drupal.behaviors.contextualToolbar = {
- attach: function (context) {
+ attach: function attach(context) {
if ($('body').once('contextualToolbar-init').length) {
initContextualToolbar(context);
}
}
};
- /**
- * Namespace for the contextual toolbar.
- *
- * @namespace
- */
Drupal.contextualToolbar = {
-
- /**
- * The {@link Drupal.contextualToolbar.StateModel} instance.
- *
- * @type {?Drupal.contextualToolbar.StateModel}
- */
model: null
};
-
-})(jQuery, Drupal, Backbone);
+})(jQuery, Drupal, Backbone); \ No newline at end of file
diff --git a/core/modules/contextual/js/models/StateModel.es6.js b/core/modules/contextual/js/models/StateModel.es6.js
new file mode 100644
index 000000000000..465d717d5636
--- /dev/null
+++ b/core/modules/contextual/js/models/StateModel.es6.js
@@ -0,0 +1,132 @@
+/**
+ * @file
+ * A Backbone Model for the state of a contextual link's trigger, list & region.
+ */
+
+(function (Drupal, Backbone) {
+
+ 'use strict';
+
+ /**
+ * Models the state of a contextual link's trigger, list & region.
+ *
+ * @constructor
+ *
+ * @augments Backbone.Model
+ */
+ Drupal.contextual.StateModel = Backbone.Model.extend(/** @lends Drupal.contextual.StateModel# */{
+
+ /**
+ * @type {object}
+ *
+ * @prop {string} title
+ * @prop {bool} regionIsHovered
+ * @prop {bool} hasFocus
+ * @prop {bool} isOpen
+ * @prop {bool} isLocked
+ */
+ defaults: /** @lends Drupal.contextual.StateModel# */{
+
+ /**
+ * The title of the entity to which these contextual links apply.
+ *
+ * @type {string}
+ */
+ title: '',
+
+ /**
+ * Represents if the contextual region is being hovered.
+ *
+ * @type {bool}
+ */
+ regionIsHovered: false,
+
+ /**
+ * Represents if the contextual trigger or options have focus.
+ *
+ * @type {bool}
+ */
+ hasFocus: false,
+
+ /**
+ * Represents if the contextual options for an entity are available to
+ * be selected (i.e. whether the list of options is visible).
+ *
+ * @type {bool}
+ */
+ isOpen: false,
+
+ /**
+ * When the model is locked, the trigger remains active.
+ *
+ * @type {bool}
+ */
+ isLocked: false
+ },
+
+ /**
+ * Opens or closes the contextual link.
+ *
+ * If it is opened, then also give focus.
+ *
+ * @return {Drupal.contextual.StateModel}
+ * The current contextual state model.
+ */
+ toggleOpen: function () {
+ var newIsOpen = !this.get('isOpen');
+ this.set('isOpen', newIsOpen);
+ if (newIsOpen) {
+ this.focus();
+ }
+ return this;
+ },
+
+ /**
+ * Closes this contextual link.
+ *
+ * Does not call blur() because we want to allow a contextual link to have
+ * focus, yet be closed for example when hovering.
+ *
+ * @return {Drupal.contextual.StateModel}
+ * The current contextual state model.
+ */
+ close: function () {
+ this.set('isOpen', false);
+ return this;
+ },
+
+ /**
+ * Gives focus to this contextual link.
+ *
+ * Also closes + removes focus from every other contextual link.
+ *
+ * @return {Drupal.contextual.StateModel}
+ * The current contextual state model.
+ */
+ focus: function () {
+ this.set('hasFocus', true);
+ var cid = this.cid;
+ this.collection.each(function (model) {
+ if (model.cid !== cid) {
+ model.close().blur();
+ }
+ });
+ return this;
+ },
+
+ /**
+ * Removes focus from this contextual link, unless it is open.
+ *
+ * @return {Drupal.contextual.StateModel}
+ * The current contextual state model.
+ */
+ blur: function () {
+ if (!this.get('isOpen')) {
+ this.set('hasFocus', false);
+ }
+ return this;
+ }
+
+ });
+
+})(Drupal, Backbone);
diff --git a/core/modules/contextual/js/models/StateModel.js b/core/modules/contextual/js/models/StateModel.js
index 465d717d5636..ac9a89582486 100644
--- a/core/modules/contextual/js/models/StateModel.js
+++ b/core/modules/contextual/js/models/StateModel.js
@@ -1,78 +1,29 @@
/**
- * @file
- * A Backbone Model for the state of a contextual link's trigger, list & region.
- */
+* DO NOT EDIT THIS FILE.
+* All changes should be applied to ./modules/contextual/js/models/StateModel.es6.js
+* See the following change record for more information,
+* https://www.drupal.org/node/2873849
+* @preserve
+**/
(function (Drupal, Backbone) {
'use strict';
- /**
- * Models the state of a contextual link's trigger, list & region.
- *
- * @constructor
- *
- * @augments Backbone.Model
- */
- Drupal.contextual.StateModel = Backbone.Model.extend(/** @lends Drupal.contextual.StateModel# */{
-
- /**
- * @type {object}
- *
- * @prop {string} title
- * @prop {bool} regionIsHovered
- * @prop {bool} hasFocus
- * @prop {bool} isOpen
- * @prop {bool} isLocked
- */
- defaults: /** @lends Drupal.contextual.StateModel# */{
-
- /**
- * The title of the entity to which these contextual links apply.
- *
- * @type {string}
- */
+ Drupal.contextual.StateModel = Backbone.Model.extend({
+ defaults: {
title: '',
- /**
- * Represents if the contextual region is being hovered.
- *
- * @type {bool}
- */
regionIsHovered: false,
- /**
- * Represents if the contextual trigger or options have focus.
- *
- * @type {bool}
- */
hasFocus: false,
- /**
- * Represents if the contextual options for an entity are available to
- * be selected (i.e. whether the list of options is visible).
- *
- * @type {bool}
- */
isOpen: false,
- /**
- * When the model is locked, the trigger remains active.
- *
- * @type {bool}
- */
isLocked: false
},
- /**
- * Opens or closes the contextual link.
- *
- * If it is opened, then also give focus.
- *
- * @return {Drupal.contextual.StateModel}
- * The current contextual state model.
- */
- toggleOpen: function () {
+ toggleOpen: function toggleOpen() {
var newIsOpen = !this.get('isOpen');
this.set('isOpen', newIsOpen);
if (newIsOpen) {
@@ -81,29 +32,12 @@
return this;
},
- /**
- * Closes this contextual link.
- *
- * Does not call blur() because we want to allow a contextual link to have
- * focus, yet be closed for example when hovering.
- *
- * @return {Drupal.contextual.StateModel}
- * The current contextual state model.
- */
- close: function () {
+ close: function close() {
this.set('isOpen', false);
return this;
},
- /**
- * Gives focus to this contextual link.
- *
- * Also closes + removes focus from every other contextual link.
- *
- * @return {Drupal.contextual.StateModel}
- * The current contextual state model.
- */
- focus: function () {
+ focus: function focus() {
this.set('hasFocus', true);
var cid = this.cid;
this.collection.each(function (model) {
@@ -114,13 +48,7 @@
return this;
},
- /**
- * Removes focus from this contextual link, unless it is open.
- *
- * @return {Drupal.contextual.StateModel}
- * The current contextual state model.
- */
- blur: function () {
+ blur: function blur() {
if (!this.get('isOpen')) {
this.set('hasFocus', false);
}
@@ -128,5 +56,4 @@
}
});
-
-})(Drupal, Backbone);
+})(Drupal, Backbone); \ No newline at end of file
diff --git a/core/modules/contextual/js/toolbar/models/StateModel.es6.js b/core/modules/contextual/js/toolbar/models/StateModel.es6.js
new file mode 100644
index 000000000000..d9159e4e97f6
--- /dev/null
+++ b/core/modules/contextual/js/toolbar/models/StateModel.es6.js
@@ -0,0 +1,119 @@
+/**
+ * @file
+ * A Backbone Model for the state of Contextual module's edit toolbar tab.
+ */
+
+(function (Drupal, Backbone) {
+
+ 'use strict';
+
+ Drupal.contextualToolbar.StateModel = Backbone.Model.extend(/** @lends Drupal.contextualToolbar.StateModel# */{
+
+ /**
+ * @type {object}
+ *
+ * @prop {bool} isViewing
+ * @prop {bool} isVisible
+ * @prop {number} contextualCount
+ * @prop {Drupal~TabbingContext} tabbingContext
+ */
+ defaults: /** @lends Drupal.contextualToolbar.StateModel# */{
+
+ /**
+ * Indicates whether the toggle is currently in "view" or "edit" mode.
+ *
+ * @type {bool}
+ */
+ isViewing: true,
+
+ /**
+ * Indicates whether the toggle should be visible or hidden. Automatically
+ * calculated, depends on contextualCount.
+ *
+ * @type {bool}
+ */
+ isVisible: false,
+
+ /**
+ * Tracks how many contextual links exist on the page.
+ *
+ * @type {number}
+ */
+ contextualCount: 0,
+
+ /**
+ * A TabbingContext object as returned by {@link Drupal~TabbingManager}:
+ * the set of tabbable elements when edit mode is enabled.
+ *
+ * @type {?Drupal~TabbingContext}
+ */
+ tabbingContext: null
+ },
+
+ /**
+ * Models the state of the edit mode toggle.
+ *
+ * @constructs
+ *
+ * @augments Backbone.Model
+ *
+ * @param {object} attrs
+ * Attributes for the backbone model.
+ * @param {object} options
+ * An object with the following option:
+ * @param {Backbone.collection} options.contextualCollection
+ * The collection of {@link Drupal.contextual.StateModel} models that
+ * represent the contextual links on the page.
+ */
+ initialize: function (attrs, options) {
+ // Respond to new/removed contextual links.
+ this.listenTo(options.contextualCollection, 'reset remove add', this.countContextualLinks);
+ this.listenTo(options.contextualCollection, 'add', this.lockNewContextualLinks);
+
+ // Automatically determine visibility.
+ this.listenTo(this, 'change:contextualCount', this.updateVisibility);
+
+ // Whenever edit mode is toggled, lock all contextual links.
+ this.listenTo(this, 'change:isViewing', function (model, isViewing) {
+ options.contextualCollection.each(function (contextualModel) {
+ contextualModel.set('isLocked', !isViewing);
+ });
+ });
+ },
+
+ /**
+ * Tracks the number of contextual link models in the collection.
+ *
+ * @param {Drupal.contextual.StateModel} contextualModel
+ * The contextual links model that was added or removed.
+ * @param {Backbone.Collection} contextualCollection
+ * The collection of contextual link models.
+ */
+ countContextualLinks: function (contextualModel, contextualCollection) {
+ this.set('contextualCount', contextualCollection.length);
+ },
+
+ /**
+ * Lock newly added contextual links if edit mode is enabled.
+ *
+ * @param {Drupal.contextual.StateModel} contextualModel
+ * The contextual links model that was added.
+ * @param {Backbone.Collection} [contextualCollection]
+ * The collection of contextual link models.
+ */
+ lockNewContextualLinks: function (contextualModel, contextualCollection) {
+ if (!this.get('isViewing')) {
+ contextualModel.set('isLocked', true);
+ }
+ },
+
+ /**
+ * Automatically updates visibility of the view/edit mode toggle.
+ */
+ updateVisibility: function () {
+ this.set('isVisible', this.get('contextualCount') > 0);
+ }
+
+ });
+
+})(Drupal, Backbone);
diff --git a/core/modules/contextual/js/toolbar/models/StateModel.js b/core/modules/contextual/js/toolbar/models/StateModel.js
index d9159e4e97f6..93eed97b5b55 100644
--- a/core/modules/contextual/js/toolbar/models/StateModel.js
+++ b/core/modules/contextual/js/toolbar/models/StateModel.js
@@ -1,79 +1,32 @@
/**
- * @file
- * A Backbone Model for the state of Contextual module's edit toolbar tab.
- */
+* DO NOT EDIT THIS FILE.
+* All changes should be applied to ./modules/contextual/js/toolbar/models/StateModel.es6.js
+* See the following change record for more information,
+* https://www.drupal.org/node/2873849
+* @preserve
+**/
(function (Drupal, Backbone) {
'use strict';
- Drupal.contextualToolbar.StateModel = Backbone.Model.extend(/** @lends Drupal.contextualToolbar.StateModel# */{
-
- /**
- * @type {object}
- *
- * @prop {bool} isViewing
- * @prop {bool} isVisible
- * @prop {number} contextualCount
- * @prop {Drupal~TabbingContext} tabbingContext
- */
- defaults: /** @lends Drupal.contextualToolbar.StateModel# */{
-
- /**
- * Indicates whether the toggle is currently in "view" or "edit" mode.
- *
- * @type {bool}
- */
+ Drupal.contextualToolbar.StateModel = Backbone.Model.extend({
+ defaults: {
isViewing: true,
- /**
- * Indicates whether the toggle should be visible or hidden. Automatically
- * calculated, depends on contextualCount.
- *
- * @type {bool}
- */
isVisible: false,
- /**
- * Tracks how many contextual links exist on the page.
- *
- * @type {number}
- */
contextualCount: 0,
- /**
- * A TabbingContext object as returned by {@link Drupal~TabbingManager}:
- * the set of tabbable elements when edit mode is enabled.
- *
- * @type {?Drupal~TabbingContext}
- */
tabbingContext: null
},
- /**
- * Models the state of the edit mode toggle.
- *
- * @constructs
- *
- * @augments Backbone.Model
- *
- * @param {object} attrs
- * Attributes for the backbone model.
- * @param {object} options
- * An object with the following option:
- * @param {Backbone.collection} options.contextualCollection
- * The collection of {@link Drupal.contextual.StateModel} models that
- * represent the contextual links on the page.
- */
- initialize: function (attrs, options) {
- // Respond to new/removed contextual links.
+ initialize: function initialize(attrs, options) {
this.listenTo(options.contextualCollection, 'reset remove add', this.countContextualLinks);
this.listenTo(options.contextualCollection, 'add', this.lockNewContextualLinks);
- // Automatically determine visibility.
this.listenTo(this, 'change:contextualCount', this.updateVisibility);
- // Whenever edit mode is toggled, lock all contextual links.
this.listenTo(this, 'change:isViewing', function (model, isViewing) {
options.contextualCollection.each(function (contextualModel) {
contextualModel.set('isLocked', !isViewing);
@@ -81,39 +34,19 @@
});
},
- /**
- * Tracks the number of contextual link models in the collection.
- *
- * @param {Drupal.contextual.StateModel} contextualModel
- * The contextual links model that was added or removed.
- * @param {Backbone.Collection} contextualCollection
- * The collection of contextual link models.
- */
- countContextualLinks: function (contextualModel, contextualCollection) {
+ countContextualLinks: function countContextualLinks(contextualModel, contextualCollection) {
this.set('contextualCount', contextualCollection.length);
},
- /**
- * Lock newly added contextual links if edit mode is enabled.
- *
- * @param {Drupal.contextual.StateModel} contextualModel
- * The contextual links model that was added.
- * @param {Backbone.Collection} [contextualCollection]
- * The collection of contextual link models.
- */
- lockNewContextualLinks: function (contextualModel, contextualCollection) {
+ lockNewContextualLinks: function lockNewContextualLinks(contextualModel, contextualCollection) {
if (!this.get('isViewing')) {
contextualModel.set('isLocked', true);
}
},
- /**
- * Automatically updates visibility of the view/edit mode toggle.
- */
- updateVisibility: function () {
+ updateVisibility: function updateVisibility() {
this.set('isVisible', this.get('contextualCount') > 0);
}
});
-
-})(Drupal, Backbone);
+})(Drupal, Backbone); \ No newline at end of file
diff --git a/core/modules/contextual/js/toolbar/views/AuralView.es6.js b/core/modules/contextual/js/toolbar/views/AuralView.es6.js
new file mode 100644
index 000000000000..d684ffb9e63e
--- /dev/null
+++ b/core/modules/contextual/js/toolbar/views/AuralView.es6.js
@@ -0,0 +1,104 @@
+/**
+ * @file
+ * A Backbone View that provides the aural view of the edit mode toggle.
+ */
+
+(function ($, Drupal, Backbone, _) {
+
+ 'use strict';
+
+ Drupal.contextualToolbar.AuralView = Backbone.View.extend(/** @lends Drupal.contextualToolbar.AuralView# */{
+
+ /**
+ * Tracks whether the tabbing constraint announcement has been read once.
+ *
+ * @type {bool}
+ */
+ announcedOnce: false,
+
+ /**
+ * Renders the aural view of the edit mode toggle (screen reader support).
+ *
+ * @constructs
+ *
+ * @augments Backbone.View
+ *
+ * @param {object} options
+ * Options for the view.
+ */
+ initialize: function (options) {
+ this.options = options;
+
+ this.listenTo(this.model, 'change', this.render);
+ this.listenTo(this.model, 'change:isViewing', this.manageTabbing);
+
+ $(document).on('keyup', _.bind(this.onKeypress, this));
+ },
+
+ /**
+ * @inheritdoc
+ *
+ * @return {Drupal.contextualToolbar.AuralView}
+ * The current contextual toolbar aural view.
+ */
+ render: function () {
+ // Render the state.
+ this.$el.find('button').attr('aria-pressed', !this.model.get('isViewing'));
+
+ return this;
+ },
+
+ /**
+ * Limits tabbing to the contextual links and edit mode toolbar tab.
+ */
+ manageTabbing: function () {
+ var tabbingContext = this.model.get('tabbingContext');
+ // Always release an existing tabbing context.
+ if (tabbingContext) {
+ tabbingContext.release();
+ Drupal.announce(this.options.strings.tabbingReleased);
+ }
+ // Create a new tabbing context when edit mode is enabled.
+ if (!this.model.get('isViewing')) {
+ tabbingContext = Drupal.tabbingManager.constrain($('.contextual-toolbar-tab, .contextual'));
+ this.model.set('tabbingContext', tabbingContext);
+ this.announceTabbingConstraint();
+ this.announcedOnce = true;
+ }
+ },
+
+ /**
+ * Announces the current tabbing constraint.
+ */
+ announceTabbingConstraint: function () {
+ var strings = this.options.strings;
+ Drupal.announce(Drupal.formatString(strings.tabbingConstrained, {
+ '@contextualsCount': Drupal.formatPlural(Drupal.contextual.collection.length, '@count contextual link', '@count contextual links')
+ }));
+ Drupal.announce(strings.pressEsc);
+ },
+
+ /**
+ * Responds to esc and tab key press events.
+ *
+ * @param {jQuery.Event} event
+ * The keypress event.
+ */
+ onKeypress: function (event) {
+ // The first tab key press is tracked so that an annoucement about tabbing
+ // constraints can be raised if edit mode is enabled when the page is
+ // loaded.
+ if (!this.announcedOnce && event.keyCode === 9 && !this.model.get('isViewing')) {
+ this.announceTabbingConstraint();
+ // Set announce to true so that this conditional block won't run again.
+ this.announcedOnce = true;
+ }
+ // Respond to the ESC key. Exit out of edit mode.
+ if (event.keyCode === 27) {
+ this.model.set('isViewing', true);
+ }
+ }
+
+ });
+
+})(jQuery, Drupal, Backbone, _);
diff --git a/core/modules/contextual/js/toolbar/views/AuralView.js b/core/modules/contextual/js/toolbar/views/AuralView.js
index d684ffb9e63e..132342f5801e 100644
--- a/core/modules/contextual/js/toolbar/views/AuralView.js
+++ b/core/modules/contextual/js/toolbar/views/AuralView.js
@@ -1,32 +1,19 @@
/**
- * @file
- * A Backbone View that provides the aural view of the edit mode toggle.
- */
+* DO NOT EDIT THIS FILE.
+* All changes should be applied to ./modules/contextual/js/toolbar/views/AuralView.es6.js
+* See the following change record for more information,
+* https://www.drupal.org/node/2873849
+* @preserve
+**/
(function ($, Drupal, Backbone, _) {
'use strict';
- Drupal.contextualToolbar.AuralView = Backbone.View.extend(/** @lends Drupal.contextualToolbar.AuralView# */{
-
- /**
- * Tracks whether the tabbing constraint announcement has been read once.
- *
- * @type {bool}
- */
+ Drupal.contextualToolbar.AuralView = Backbone.View.extend({
announcedOnce: false,
- /**
- * Renders the aural view of the edit mode toggle (screen reader support).
- *
- * @constructs
- *
- * @augments Backbone.View
- *
- * @param {object} options
- * Options for the view.
- */
- initialize: function (options) {
+ initialize: function initialize(options) {
this.options = options;
this.listenTo(this.model, 'change', this.render);
@@ -35,30 +22,20 @@
$(document).on('keyup', _.bind(this.onKeypress, this));
},
- /**
- * @inheritdoc
- *
- * @return {Drupal.contextualToolbar.AuralView}
- * The current contextual toolbar aural view.
- */
- render: function () {
- // Render the state.
+ render: function render() {
this.$el.find('button').attr('aria-pressed', !this.model.get('isViewing'));
return this;
},
- /**
- * Limits tabbing to the contextual links and edit mode toolbar tab.
- */
- manageTabbing: function () {
+ manageTabbing: function manageTabbing() {
var tabbingContext = this.model.get('tabbingContext');
- // Always release an existing tabbing context.
+
if (tabbingContext) {
tabbingContext.release();
Drupal.announce(this.options.strings.tabbingReleased);
}
- // Create a new tabbing context when edit mode is enabled.
+
if (!this.model.get('isViewing')) {
tabbingContext = Drupal.tabbingManager.constrain($('.contextual-toolbar-tab, .contextual'));
this.model.set('tabbingContext', tabbingContext);
@@ -67,10 +44,7 @@
}
},
- /**
- * Announces the current tabbing constraint.
- */
- announceTabbingConstraint: function () {
+ announceTabbingConstraint: function announceTabbingConstraint() {
var strings = this.options.strings;
Drupal.announce(Drupal.formatString(strings.tabbingConstrained, {
'@contextualsCount': Drupal.formatPlural(Drupal.contextual.collection.length, '@count contextual link', '@count contextual links')
@@ -78,27 +52,17 @@
Drupal.announce(strings.pressEsc);
},
- /**
- * Responds to esc and tab key press events.
- *
- * @param {jQuery.Event} event
- * The keypress event.
- */
- onKeypress: function (event) {
- // The first tab key press is tracked so that an annoucement about tabbing
- // constraints can be raised if edit mode is enabled when the page is
- // loaded.
+ onKeypress: function onKeypress(event) {
if (!this.announcedOnce && event.keyCode === 9 && !this.model.get('isViewing')) {
this.announceTabbingConstraint();
- // Set announce to true so that this conditional block won't run again.
+
this.announcedOnce = true;
}
- // Respond to the ESC key. Exit out of edit mode.
+
if (event.keyCode === 27) {
this.model.set('isViewing', true);
}
}
});
-
-})(jQuery, Drupal, Backbone, _);
+})(jQuery, Drupal, Backbone, _); \ No newline at end of file
diff --git a/core/modules/contextual/js/toolbar/views/VisualView.es6.js b/core/modules/contextual/js/toolbar/views/VisualView.es6.js
new file mode 100644
index 000000000000..d1d413502d32
--- /dev/null
+++ b/core/modules/contextual/js/toolbar/views/VisualView.es6.js
@@ -0,0 +1,84 @@
+/**
+ * @file
+ * A Backbone View that provides the visual view of the edit mode toggle.
+ */
+
+(function (Drupal, Backbone) {
+
+ 'use strict';
+
+ Drupal.contextualToolbar.VisualView = Backbone.View.extend(/** @lends Drupal.contextualToolbar.VisualView# */{
+
+ /**
+ * Events for the Backbone view.
+ *
+ * @return {object}
+ * A mapping of events to be used in the view.
+ */
+ events: function () {
+ // Prevents delay and simulated mouse events.
+ var touchEndToClick = function (event) {
+ event.preventDefault();
+ event.target.click();
+ };
+
+ return {
+ click: function () {
+ this.model.set('isViewing', !this.model.get('isViewing'));
+ },
+ touchend: touchEndToClick
+ };
+ },
+
+ /**
+ * Renders the visual view of the edit mode toggle.
+ *
+ * Listens to mouse & touch and handles edit mode toggle interactions.
+ *
+ * @constructs
+ *
+ * @augments Backbone.View
+ */
+ initialize: function () {
+ this.listenTo(this.model, 'change', this.render);
+ this.listenTo(this.model, 'change:isViewing', this.persist);
+ },
+
+ /**
+ * @inheritdoc
+ *
+ * @return {Drupal.contextualToolbar.VisualView}
+ * The current contextual toolbar visual view.
+ */
+ render: function () {
+ // Render the visibility.
+ this.$el.toggleClass('hidden', !this.model.get('isVisible'));
+ // Render the state.
+ this.$el.find('button').toggleClass('is-active', !this.model.get('isViewing'));
+
+ return this;
+ },
+
+ /**
+ * Model change handler; persists the isViewing value to localStorage.
+ *
+ * `isViewing === true` is the default, so only stores in localStorage when
+ * it's not the default value (i.e. false).
+ *
+ * @param {Drupal.contextualToolbar.StateModel} model
+ * A {@link Drupal.contextualToolbar.StateModel} model.
+ * @param {bool} isViewing
+ * The value of the isViewing attribute in the model.
+ */
+ persist: function (model, isViewing) {
+ if (!isViewing) {
+ localStorage.setItem('Drupal.contextualToolbar.isViewing', 'false');
+ }
+ else {
+ localStorage.removeItem('Drupal.contextualToolbar.isViewing');
+ }
+ }
+
+ });
+
+})(Drupal, Backbone);
diff --git a/core/modules/contextual/js/toolbar/views/VisualView.js b/core/modules/contextual/js/toolbar/views/VisualView.js
index d1d413502d32..f666a95c2180 100644
--- a/core/modules/contextual/js/toolbar/views/VisualView.js
+++ b/core/modules/contextual/js/toolbar/views/VisualView.js
@@ -1,84 +1,50 @@
/**
- * @file
- * A Backbone View that provides the visual view of the edit mode toggle.
- */
+* DO NOT EDIT THIS FILE.
+* All changes should be applied to ./modules/contextual/js/toolbar/views/VisualView.es6.js
+* See the following change record for more information,
+* https://www.drupal.org/node/2873849
+* @preserve
+**/
(function (Drupal, Backbone) {
'use strict';
- Drupal.contextualToolbar.VisualView = Backbone.View.extend(/** @lends Drupal.contextualToolbar.VisualView# */{
-
- /**
- * Events for the Backbone view.
- *
- * @return {object}
- * A mapping of events to be used in the view.
- */
- events: function () {
- // Prevents delay and simulated mouse events.
- var touchEndToClick = function (event) {
+ Drupal.contextualToolbar.VisualView = Backbone.View.extend({
+ events: function events() {
+ var touchEndToClick = function touchEndToClick(event) {
event.preventDefault();
event.target.click();
};
return {
- click: function () {
+ click: function click() {
this.model.set('isViewing', !this.model.get('isViewing'));
},
touchend: touchEndToClick
};
},
- /**
- * Renders the visual view of the edit mode toggle.
- *
- * Listens to mouse & touch and handles edit mode toggle interactions.
- *
- * @constructs
- *
- * @augments Backbone.View
- */
- initialize: function () {
+ initialize: function initialize() {
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'change:isViewing', this.persist);
},
- /**
- * @inheritdoc
- *
- * @return {Drupal.contextualToolbar.VisualView}
- * The current contextual toolbar visual view.
- */
- render: function () {
- // Render the visibility.
+ render: function render() {
this.$el.toggleClass('hidden', !this.model.get('isVisible'));
- // Render the state.
+
this.$el.find('button').toggleClass('is-active', !this.model.get('isViewing'));
return this;
},
- /**
- * Model change handler; persists the isViewing value to localStorage.
- *
- * `isViewing === true` is the default, so only stores in localStorage when
- * it's not the default value (i.e. false).
- *
- * @param {Drupal.contextualToolbar.StateModel} model
- * A {@link Drupal.contextualToolbar.StateModel} model.
- * @param {bool} isViewing
- * The value of the isViewing attribute in the model.
- */
- persist: function (model, isViewing) {
+ persist: function persist(model, isViewing) {
if (!isViewing) {
localStorage.setItem('Drupal.contextualToolbar.isViewing', 'false');
- }
- else {
+ } else {
localStorage.removeItem('Drupal.contextualToolbar.isViewing');
}
}
});
-
-})(Drupal, Backbone);
+})(Drupal, Backbone); \ No newline at end of file
diff --git a/core/modules/contextual/js/views/AuralView.es6.js b/core/modules/contextual/js/views/AuralView.es6.js
new file mode 100644
index 000000000000..8ba2e33e347b
--- /dev/null
+++ b/core/modules/contextual/js/views/AuralView.es6.js
@@ -0,0 +1,55 @@
+/**
+ * @file
+ * A Backbone View that provides the aural view of a contextual link.
+ */
+
+(function (Drupal, Backbone) {
+
+ 'use strict';
+
+ Drupal.contextual.AuralView = Backbone.View.extend(/** @lends Drupal.contextual.AuralView# */{
+
+ /**
+ * Renders the aural view of a contextual link (i.e. screen reader support).
+ *
+ * @constructs
+ *
+ * @augments Backbone.View
+ *
+ * @param {object} options
+ * Options for the view.
+ */
+ initialize: function (options) {
+ this.options = options;
+
+ this.listenTo(this.model, 'change', this.render);
+
+ // Use aria-role form so that the number of items in the list is spoken.
+ this.$el.attr('role', 'form');
+
+ // Initial render.
+ this.render();
+ },
+
+ /**
+ * @inheritdoc
+ */
+ render: function () {
+ var isOpen = this.model.get('isOpen');
+
+ // Set the hidden property of the links.
+ this.$el.find('.contextual-links')
+ .prop('hidden', !isOpen);
+
+ // Update the view of the trigger.
+ this.$el.find('.trigger')
+ .text(Drupal.t('@action @title configuration options', {
+ '@action': (!isOpen) ? this.options.strings.open : this.options.strings.close,
+ '@title': this.model.get('title')
+ }))
+ .attr('aria-pressed', isOpen);
+ }
+
+ });
+
+})(Drupal, Backbone);
diff --git a/core/modules/contextual/js/views/AuralView.js b/core/modules/contextual/js/views/AuralView.js
index 8ba2e33e347b..5cbefcdd785d 100644
--- a/core/modules/contextual/js/views/AuralView.js
+++ b/core/modules/contextual/js/views/AuralView.js
@@ -1,55 +1,36 @@
/**
- * @file
- * A Backbone View that provides the aural view of a contextual link.
- */
+* DO NOT EDIT THIS FILE.
+* All changes should be applied to ./modules/contextual/js/views/AuralView.es6.js
+* See the following change record for more information,
+* https://www.drupal.org/node/2873849
+* @preserve
+**/
(function (Drupal, Backbone) {
'use strict';
- Drupal.contextual.AuralView = Backbone.View.extend(/** @lends Drupal.contextual.AuralView# */{
-
- /**
- * Renders the aural view of a contextual link (i.e. screen reader support).
- *
- * @constructs
- *
- * @augments Backbone.View
- *
- * @param {object} options
- * Options for the view.
- */
- initialize: function (options) {
+ Drupal.contextual.AuralView = Backbone.View.extend({
+ initialize: function initialize(options) {
this.options = options;
this.listenTo(this.model, 'change', this.render);
- // Use aria-role form so that the number of items in the list is spoken.
this.$el.attr('role', 'form');
- // Initial render.
this.render();
},
- /**
- * @inheritdoc
- */
- render: function () {
+ render: function render() {
var isOpen = this.model.get('isOpen');
- // Set the hidden property of the links.
- this.$el.find('.contextual-links')
- .prop('hidden', !isOpen);
-
- // Update the view of the trigger.
- this.$el.find('.trigger')
- .text(Drupal.t('@action @title configuration options', {
- '@action': (!isOpen) ? this.options.strings.open : this.options.strings.close,
- '@title': this.model.get('title')
- }))
- .attr('aria-pressed', isOpen);
+ this.$el.find('.contextual-links').prop('hidden', !isOpen);
+
+ this.$el.find('.trigger').text(Drupal.t('@action @title configuration options', {
+ '@action': !isOpen ? this.options.strings.open : this.options.strings.close,
+ '@title': this.model.get('title')
+ })).attr('aria-pressed', isOpen);
}
});
-
-})(Drupal, Backbone);
+})(Drupal, Backbone); \ No newline at end of file
diff --git a/core/modules/contextual/js/views/KeyboardView.es6.js b/core/modules/contextual/js/views/KeyboardView.es6.js
new file mode 100644
index 000000000000..9c247730e312
--- /dev/null
+++ b/core/modules/contextual/js/views/KeyboardView.es6.js
@@ -0,0 +1,61 @@
+/**
+ * @file
+ * A Backbone View that provides keyboard interaction for a contextual link.
+ */
+
+(function (Drupal, Backbone) {
+
+ 'use strict';
+
+ Drupal.contextual.KeyboardView = Backbone.View.extend(/** @lends Drupal.contextual.KeyboardView# */{
+
+ /**
+ * @type {object}
+ */
+ events: {
+ 'focus .trigger': 'focus',
+ 'focus .contextual-links a': 'focus',
+ 'blur .trigger': function () { this.model.blur(); },
+ 'blur .contextual-links a': function () {
+ // Set up a timeout to allow a user to tab between the trigger and the
+ // contextual links without the menu dismissing.
+ var that = this;
+ this.timer = window.setTimeout(function () {
+ that.model.close().blur();
+ }, 150);
+ }
+ },
+
+ /**
+ * Provides keyboard interaction for a contextual link.
+ *
+ * @constructs
+ *
+ * @augments Backbone.View
+ */
+ initialize: function () {
+
+ /**
+ * The timer is used to create a delay before dismissing the contextual
+ * links on blur. This is only necessary when keyboard users tab into
+ * contextual links without edit mode (i.e. without TabbingManager).
+ * That means that if we decide to disable tabbing of contextual links
+ * without edit mode, all this timer logic can go away.
+ *
+ * @type {NaN|number}
+ */
+ this.timer = NaN;
+ },
+
+ /**
+ * Sets focus on the model; Clears the timer that dismisses the links.
+ */
+ focus: function () {
+ // Clear the timeout that might have been set by blurring a link.
+ window.clearTimeout(this.timer);
+ this.model.focus();
+ }
+
+ });
+
+})(Drupal, Backbone);
diff --git a/core/modules/contextual/js/views/KeyboardView.js b/core/modules/contextual/js/views/KeyboardView.js
index 9c247730e312..1539971d6833 100644
--- a/core/modules/contextual/js/views/KeyboardView.js
+++ b/core/modules/contextual/js/views/KeyboardView.js
@@ -1,24 +1,23 @@
/**
- * @file
- * A Backbone View that provides keyboard interaction for a contextual link.
- */
+* DO NOT EDIT THIS FILE.
+* All changes should be applied to ./modules/contextual/js/views/KeyboardView.es6.js
+* See the following change record for more information,
+* https://www.drupal.org/node/2873849
+* @preserve
+**/
(function (Drupal, Backbone) {
'use strict';
- Drupal.contextual.KeyboardView = Backbone.View.extend(/** @lends Drupal.contextual.KeyboardView# */{
-
- /**
- * @type {object}
- */
+ Drupal.contextual.KeyboardView = Backbone.View.extend({
events: {
'focus .trigger': 'focus',
'focus .contextual-links a': 'focus',
- 'blur .trigger': function () { this.model.blur(); },
- 'blur .contextual-links a': function () {
- // Set up a timeout to allow a user to tab between the trigger and the
- // contextual links without the menu dismissing.
+ 'blur .trigger': function blurTrigger() {
+ this.model.blur();
+ },
+ 'blur .contextual-links a': function blurContextualLinksA() {
var that = this;
this.timer = window.setTimeout(function () {
that.model.close().blur();
@@ -26,36 +25,14 @@
}
},
- /**
- * Provides keyboard interaction for a contextual link.
- *
- * @constructs
- *
- * @augments Backbone.View
- */
- initialize: function () {
-
- /**
- * The timer is used to create a delay before dismissing the contextual
- * links on blur. This is only necessary when keyboard users tab into
- * contextual links without edit mode (i.e. without TabbingManager).
- * That means that if we decide to disable tabbing of contextual links
- * without edit mode, all this timer logic can go away.
- *
- * @type {NaN|number}
- */
+ initialize: function initialize() {
this.timer = NaN;
},
- /**
- * Sets focus on the model; Clears the timer that dismisses the links.
- */
- focus: function () {
- // Clear the timeout that might have been set by blurring a link.
+ focus: function focus() {
window.clearTimeout(this.timer);
this.model.focus();
}
});
-
-})(Drupal, Backbone);
+})(Drupal, Backbone); \ No newline at end of file
diff --git a/core/modules/contextual/js/views/RegionView.es6.js b/core/modules/contextual/js/views/RegionView.es6.js
new file mode 100644
index 000000000000..e960db36bfd6
--- /dev/null
+++ b/core/modules/contextual/js/views/RegionView.es6.js
@@ -0,0 +1,57 @@
+/**
+ * @file
+ * A Backbone View that renders the visual view of a contextual region element.
+ */
+
+(function (Drupal, Backbone, Modernizr) {
+
+ 'use strict';
+
+ Drupal.contextual.RegionView = Backbone.View.extend(/** @lends Drupal.contextual.RegionView# */{
+
+ /**
+ * Events for the Backbone view.
+ *
+ * @return {object}
+ * A mapping of events to be used in the view.
+ */
+ events: function () {
+ var mapping = {
+ mouseenter: function () { this.model.set('regionIsHovered', true); },
+ mouseleave: function () {
+ this.model.close().blur().set('regionIsHovered', false);
+ }
+ };
+ // We don't want mouse hover events on touch.
+ if (Modernizr.touchevents) {
+ mapping = {};
+ }
+ return mapping;
+ },
+
+ /**
+ * Renders the visual view of a contextual region element.
+ *
+ * @constructs
+ *
+ * @augments Backbone.View
+ */
+ initialize: function () {
+ this.listenTo(this.model, 'change:hasFocus', this.render);
+ },
+
+ /**
+ * @inheritdoc
+ *
+ * @return {Drupal.contextual.RegionView}
+ * The current contextual region view.
+ */
+ render: function () {
+ this.$el.toggleClass('focus', this.model.get('hasFocus'));
+
+ return this;
+ }
+
+ });
+
+})(Drupal, Backbone, Modernizr);
diff --git a/core/modules/contextual/js/views/RegionView.js b/core/modules/contextual/js/views/RegionView.js
index e960db36bfd6..d37e10f3c283 100644
--- a/core/modules/contextual/js/views/RegionView.js
+++ b/core/modules/contextual/js/views/RegionView.js
@@ -1,57 +1,41 @@
/**
- * @file
- * A Backbone View that renders the visual view of a contextual region element.
- */
+* DO NOT EDIT THIS FILE.
+* All changes should be applied to ./modules/contextual/js/views/RegionView.es6.js
+* See the following change record for more information,
+* https://www.drupal.org/node/2873849
+* @preserve
+**/
(function (Drupal, Backbone, Modernizr) {
'use strict';
- Drupal.contextual.RegionView = Backbone.View.extend(/** @lends Drupal.contextual.RegionView# */{
-
- /**
- * Events for the Backbone view.
- *
- * @return {object}
- * A mapping of events to be used in the view.
- */
- events: function () {
+ Drupal.contextual.RegionView = Backbone.View.extend({
+ events: function events() {
var mapping = {
- mouseenter: function () { this.model.set('regionIsHovered', true); },
- mouseleave: function () {
+ mouseenter: function mouseenter() {
+ this.model.set('regionIsHovered', true);
+ },
+ mouseleave: function mouseleave() {
this.model.close().blur().set('regionIsHovered', false);
}
};
- // We don't want mouse hover events on touch.
+
if (Modernizr.touchevents) {
mapping = {};
}
return mapping;
},
- /**
- * Renders the visual view of a contextual region element.
- *
- * @constructs
- *
- * @augments Backbone.View
- */
- initialize: function () {
+ initialize: function initialize() {
this.listenTo(this.model, 'change:hasFocus', this.render);
},
- /**
- * @inheritdoc
- *
- * @return {Drupal.contextual.RegionView}
- * The current contextual region view.
- */
- render: function () {
+ render: function render() {
this.$el.toggleClass('focus', this.model.get('hasFocus'));
return this;
}
});
-
-})(Drupal, Backbone, Modernizr);
+})(Drupal, Backbone, Modernizr); \ No newline at end of file
diff --git a/core/modules/contextual/js/views/VisualView.es6.js b/core/modules/contextual/js/views/VisualView.es6.js
new file mode 100644
index 000000000000..b22bb373dd8d
--- /dev/null
+++ b/core/modules/contextual/js/views/VisualView.es6.js
@@ -0,0 +1,80 @@
+/**
+ * @file
+ * A Backbone View that provides the visual view of a contextual link.
+ */
+
+(function (Drupal, Backbone, Modernizr) {
+
+ 'use strict';
+
+ Drupal.contextual.VisualView = Backbone.View.extend(/** @lends Drupal.contextual.VisualView# */{
+
+ /**
+ * Events for the Backbone view.
+ *
+ * @return {object}
+ * A mapping of events to be used in the view.
+ */
+ events: function () {
+ // Prevents delay and simulated mouse events.
+ var touchEndToClick = function (event) {
+ event.preventDefault();
+ event.target.click();
+ };
+ var mapping = {
+ 'click .trigger': function () { this.model.toggleOpen(); },
+ 'touchend .trigger': touchEndToClick,
+ 'click .contextual-links a': function () { this.model.close().blur(); },
+ 'touchend .contextual-links a': touchEndToClick
+ };
+ // We only want mouse hover events on non-touch.
+ if (!Modernizr.touchevents) {
+ mapping.mouseenter = function () { this.model.focus(); };
+ }
+ return mapping;
+ },
+
+ /**
+ * Renders the visual view of a contextual link. Listens to mouse & touch.
+ *
+ * @constructs
+ *
+ * @augments Backbone.View
+ */
+ initialize: function () {
+ this.listenTo(this.model, 'change', this.render);
+ },
+
+ /**
+ * @inheritdoc
+ *
+ * @return {Drupal.contextual.VisualView}
+ * The current contextual visual view.
+ */
+ render: function () {
+ var isOpen = this.model.get('isOpen');
+ // The trigger should be visible when:
+ // - the mouse hovered over the region,
+ // - the trigger is locked,
+ // - and for as long as the contextual menu is open.
+ var isVisible = this.model.get('isLocked') || this.model.get('regionIsHovered') || isOpen;
+
+ this.$el
+ // The open state determines if the links are visible.
+ .toggleClass('open', isOpen)
+ // Update the visibility of the trigger.
+ .find('.trigger').toggleClass('visually-hidden', !isVisible);
+
+ // Nested contextual region handling: hide any nested contextual triggers.
+ if ('isOpen' in this.model.changed) {
+ this.$el.closest('.contextual-region')
+ .find('.contextual .trigger:not(:first)')
+ .toggle(!isOpen);
+ }
+
+ return this;
+ }
+
+ });
+
+})(Drupal, Backbone, Modernizr);
diff --git a/core/modules/contextual/js/views/VisualView.js b/core/modules/contextual/js/views/VisualView.js
index b22bb373dd8d..c54f50f87189 100644
--- a/core/modules/contextual/js/views/VisualView.js
+++ b/core/modules/contextual/js/views/VisualView.js
@@ -1,80 +1,57 @@
/**
- * @file
- * A Backbone View that provides the visual view of a contextual link.
- */
+* DO NOT EDIT THIS FILE.
+* All changes should be applied to ./modules/contextual/js/views/VisualView.es6.js
+* See the following change record for more information,
+* https://www.drupal.org/node/2873849
+* @preserve
+**/
(function (Drupal, Backbone, Modernizr) {
'use strict';
- Drupal.contextual.VisualView = Backbone.View.extend(/** @lends Drupal.contextual.VisualView# */{
-
- /**
- * Events for the Backbone view.
- *
- * @return {object}
- * A mapping of events to be used in the view.
- */
- events: function () {
- // Prevents delay and simulated mouse events.
- var touchEndToClick = function (event) {
+ Drupal.contextual.VisualView = Backbone.View.extend({
+ events: function events() {
+ var touchEndToClick = function touchEndToClick(event) {
event.preventDefault();
event.target.click();
};
var mapping = {
- 'click .trigger': function () { this.model.toggleOpen(); },
+ 'click .trigger': function clickTrigger() {
+ this.model.toggleOpen();
+ },
'touchend .trigger': touchEndToClick,
- 'click .contextual-links a': function () { this.model.close().blur(); },
+ 'click .contextual-links a': function clickContextualLinksA() {
+ this.model.close().blur();
+ },
'touchend .contextual-links a': touchEndToClick
};
- // We only want mouse hover events on non-touch.
+
if (!Modernizr.touchevents) {
- mapping.mouseenter = function () { this.model.focus(); };
+ mapping.mouseenter = function () {
+ this.model.focus();
+ };
}
return mapping;
},
- /**
- * Renders the visual view of a contextual link. Listens to mouse & touch.
- *
- * @constructs
- *
- * @augments Backbone.View
- */
- initialize: function () {
+ initialize: function initialize() {
this.listenTo(this.model, 'change', this.render);
},
- /**
- * @inheritdoc
- *
- * @return {Drupal.contextual.VisualView}
- * The current contextual visual view.
- */
- render: function () {
+ render: function render() {
var isOpen = this.model.get('isOpen');
- // The trigger should be visible when:
- // - the mouse hovered over the region,
- // - the trigger is locked,
- // - and for as long as the contextual menu is open.
+
var isVisible = this.model.get('isLocked') || this.model.get('regionIsHovered') || isOpen;
- this.$el
- // The open state determines if the links are visible.
- .toggleClass('open', isOpen)
- // Update the visibility of the trigger.
- .find('.trigger').toggleClass('visually-hidden', !isVisible);
+ this.$el.toggleClass('open', isOpen).find('.trigger').toggleClass('visually-hidden', !isVisible);
- // Nested contextual region handling: hide any nested contextual triggers.
if ('isOpen' in this.model.changed) {
- this.$el.closest('.contextual-region')
- .find('.contextual .trigger:not(:first)')
- .toggle(!isOpen);
+ this.$el.closest('.contextual-region').find('.contextual .trigger:not(:first)').toggle(!isOpen);
}
return this;
}
});
-
-})(Drupal, Backbone, Modernizr);
+})(Drupal, Backbone, Modernizr); \ No newline at end of file