Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / contextual / js / toolbar / views / AuralView.es6.js
diff --git a/web/core/modules/contextual/js/toolbar/views/AuralView.es6.js b/web/core/modules/contextual/js/toolbar/views/AuralView.es6.js
new file mode 100644 (file)
index 0000000..f243e4b
--- /dev/null
@@ -0,0 +1,103 @@
+/**
+ * @file
+ * A Backbone View that provides the aural view of the edit mode toggle.
+ */
+
+(function ($, Drupal, Backbone, _) {
+  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(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() {
+      // 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() {
+      let tabbingContext = this.model.get('tabbingContext');
+      // Always release an existing tabbing context.
+      if (tabbingContext) {
+        // Only announce release when the context was active.
+        if (tabbingContext.active) {
+          Drupal.announce(this.options.strings.tabbingReleased);
+        }
+        tabbingContext.release();
+      }
+      // 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() {
+      const 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(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, _));