Chris@0: /** Chris@0: * @file Chris@0: * A Backbone Model for the state of a contextual link's trigger, list & region. Chris@0: */ Chris@0: Chris@17: (function(Drupal, Backbone) { Chris@0: /** Chris@0: * Models the state of a contextual link's trigger, list & region. Chris@0: * Chris@0: * @constructor Chris@0: * Chris@0: * @augments Backbone.Model Chris@0: */ Chris@17: Drupal.contextual.StateModel = Backbone.Model.extend( Chris@17: /** @lends Drupal.contextual.StateModel# */ { Chris@17: /** Chris@17: * @type {object} Chris@17: * Chris@17: * @prop {string} title Chris@17: * @prop {bool} regionIsHovered Chris@17: * @prop {bool} hasFocus Chris@17: * @prop {bool} isOpen Chris@17: * @prop {bool} isLocked Chris@17: */ Chris@17: defaults: /** @lends Drupal.contextual.StateModel# */ { Chris@17: /** Chris@17: * The title of the entity to which these contextual links apply. Chris@17: * Chris@17: * @type {string} Chris@17: */ Chris@17: title: '', Chris@0: Chris@17: /** Chris@17: * Represents if the contextual region is being hovered. Chris@17: * Chris@17: * @type {bool} Chris@17: */ Chris@17: regionIsHovered: false, Chris@17: Chris@17: /** Chris@17: * Represents if the contextual trigger or options have focus. Chris@17: * Chris@17: * @type {bool} Chris@17: */ Chris@17: hasFocus: false, Chris@17: Chris@17: /** Chris@17: * Represents if the contextual options for an entity are available to Chris@17: * be selected (i.e. whether the list of options is visible). Chris@17: * Chris@17: * @type {bool} Chris@17: */ Chris@17: isOpen: false, Chris@17: Chris@17: /** Chris@17: * When the model is locked, the trigger remains active. Chris@17: * Chris@17: * @type {bool} Chris@17: */ Chris@17: isLocked: false, Chris@17: }, Chris@0: Chris@0: /** Chris@17: * Opens or closes the contextual link. Chris@0: * Chris@17: * If it is opened, then also give focus. Chris@17: * Chris@17: * @return {Drupal.contextual.StateModel} Chris@17: * The current contextual state model. Chris@0: */ Chris@17: toggleOpen() { Chris@17: const newIsOpen = !this.get('isOpen'); Chris@17: this.set('isOpen', newIsOpen); Chris@17: if (newIsOpen) { Chris@17: this.focus(); Chris@17: } Chris@17: return this; Chris@17: }, Chris@0: Chris@0: /** Chris@17: * Closes this contextual link. Chris@0: * Chris@17: * Does not call blur() because we want to allow a contextual link to have Chris@17: * focus, yet be closed for example when hovering. Chris@17: * Chris@17: * @return {Drupal.contextual.StateModel} Chris@17: * The current contextual state model. Chris@0: */ Chris@17: close() { Chris@17: this.set('isOpen', false); Chris@17: return this; Chris@17: }, Chris@0: Chris@0: /** Chris@17: * Gives focus to this contextual link. Chris@0: * Chris@17: * Also closes + removes focus from every other contextual link. Chris@17: * Chris@17: * @return {Drupal.contextual.StateModel} Chris@17: * The current contextual state model. Chris@0: */ Chris@17: focus() { Chris@17: this.set('hasFocus', true); Chris@17: const cid = this.cid; Chris@17: this.collection.each(model => { Chris@17: if (model.cid !== cid) { Chris@17: model.close().blur(); Chris@17: } Chris@17: }); Chris@17: return this; Chris@17: }, Chris@0: Chris@0: /** Chris@17: * Removes focus from this contextual link, unless it is open. Chris@0: * Chris@17: * @return {Drupal.contextual.StateModel} Chris@17: * The current contextual state model. Chris@0: */ Chris@17: blur() { Chris@17: if (!this.get('isOpen')) { Chris@17: this.set('hasFocus', false); Chris@17: } Chris@17: return this; Chris@17: }, Chris@0: }, Chris@17: ); Chris@17: })(Drupal, Backbone);