/**
* @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));
this.manageTabbing();
},
/**
* {@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 announcement 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, _);