/** * @file * A Backbone View that provides the visual view of a contextual link. */ (function (Drupal, Backbone) { /** * @deprecated in drupal:9.4.0 and is removed from drupal:11.0.0. There is no * replacement. */ 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() { // Prevents delay and simulated mouse events. const touchEndToClick = function (event) { event.preventDefault(); event.target.click(); }; // Used for tracking the presence of touch events. When true, the // mousemove and mouseenter event handlers are effectively disabled. // This is used instead of preventDefault() on touchstart as some // touchstart events are not cancelable. let touchStart = false; return { touchstart() { // Set to true so the mouseenter events that follows knows to not // execute any hover related logic. touchStart = true; }, mouseenter() { // We only want mouse hover events on non-touch. if (!touchStart) { this.model.focus(); } }, mousemove() { // Because there are scenarios where there are both touchscreens // and pointer devices, the touchStart flag should be set back to // false after mouseenter and mouseleave complete. It will be set to // true if another touchstart event occurs. touchStart = false; }, 'click .trigger': function () { this.model.toggleOpen(); }, 'touchend .trigger': touchEndToClick, 'click .contextual-links a': function () { this.model.close().blur(); }, 'touchend .contextual-links a': touchEndToClick, }; }, /** * Renders the visual view of a contextual link. Listens to mouse & touch. * * @constructs * * @augments Backbone.View */ initialize() { this.listenTo(this.model, 'change', this.render); }, /** * {@inheritdoc} * * @return {Drupal.contextual.VisualView} * The current contextual visual view. */ render() { const 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. const 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);