Unverified Commit e894995a authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #2168711 by yogeshmpawar, droplet, mariancalinro, bnjmnm, peterpoe,...

Issue #2168711 by yogeshmpawar, droplet, mariancalinro, bnjmnm, peterpoe, lauriii, Kgaut, nod_, benjifisher:  Modernizr.touchevents use can lead to scenarios that break contextual links
parent 33527a5f
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ drupal.contextual-links:
    - core/drupalSettings
    # @todo Remove this in https://www.drupal.org/project/drupal/issues/3203920
    - core/internal.backbone
    - core/modernizr
    - core/once
    - core/jquery.once.bc

+26 −10
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
 * A Backbone View that renders the visual view of a contextual region element.
 */

(function (Drupal, Backbone, Modernizr) {
(function (Drupal, Backbone) {
  Drupal.contextual.RegionView = Backbone.View.extend(
    /** @lends Drupal.contextual.RegionView# */ {
      /**
@@ -13,19 +13,35 @@
       *   A mapping of events to be used in the view.
       */
      events() {
        let mapping = {
        // 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 and mouseleave events that follow
            // know to not execute any hover related logic.
            touchStart = true;
          },
          mouseenter() {
            if (!touchStart) {
              this.model.set('regionIsHovered', true);
            }
          },
          mouseleave() {
            if (!touchStart) {
              this.model.close().blur().set('regionIsHovered', false);
            }
          },
          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;
          },
        };
        // We don't want mouse hover events on touch.
        if (Modernizr.touchevents) {
          mapping = {};
        }
        return mapping;
      },

      /**
@@ -52,4 +68,4 @@
      },
    },
  );
})(Drupal, Backbone, Modernizr);
})(Drupal, Backbone);
+16 −11
Original line number Diff line number Diff line
@@ -5,23 +5,28 @@
* @preserve
**/

(function (Drupal, Backbone, Modernizr) {
(function (Drupal, Backbone) {
  Drupal.contextual.RegionView = Backbone.View.extend({
    events: function events() {
      var mapping = {
      var touchStart = false;
      return {
        touchstart: function touchstart() {
          touchStart = true;
        },
        mouseenter: function mouseenter() {
          if (!touchStart) {
            this.model.set('regionIsHovered', true);
          }
        },
        mouseleave: function mouseleave() {
          if (!touchStart) {
            this.model.close().blur().set('regionIsHovered', false);
          }
      };

      if (Modernizr.touchevents) {
        mapping = {};
        },
        mousemove: function mousemove() {
          touchStart = false;
        }

      return mapping;
      };
    },
    initialize: function initialize() {
      this.listenTo(this.model, 'change:hasFocus', this.render);
@@ -31,4 +36,4 @@
      return this;
    }
  });
})(Drupal, Backbone, Modernizr);
 No newline at end of file
})(Drupal, Backbone);
 No newline at end of file
+28 −10
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
 * A Backbone View that provides the visual view of a contextual link.
 */

(function (Drupal, Backbone, Modernizr) {
(function (Drupal, Backbone) {
  Drupal.contextual.VisualView = Backbone.View.extend(
    /** @lends Drupal.contextual.VisualView# */ {
      /**
@@ -18,7 +18,32 @@
          event.preventDefault();
          event.target.click();
        };
        const mapping = {

        // 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();
          },
@@ -28,13 +53,6 @@
          },
          '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;
      },

      /**
@@ -84,4 +102,4 @@
      },
    },
  );
})(Drupal, Backbone, Modernizr);
})(Drupal, Backbone);
+15 −11
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
* @preserve
**/

(function (Drupal, Backbone, Modernizr) {
(function (Drupal, Backbone) {
  Drupal.contextual.VisualView = Backbone.View.extend({
    events: function events() {
      var touchEndToClick = function touchEndToClick(event) {
@@ -13,7 +13,19 @@
        event.target.click();
      };

      var mapping = {
      var touchStart = false;
      return {
        touchstart: function touchstart() {
          touchStart = true;
        },
        mouseenter: function mouseenter() {
          if (!touchStart) {
            this.model.focus();
          }
        },
        mousemove: function mousemove() {
          touchStart = false;
        },
        'click .trigger': function clickTrigger() {
          this.model.toggleOpen();
        },
@@ -23,14 +35,6 @@
        },
        'touchend .contextual-links a': touchEndToClick
      };

      if (!Modernizr.touchevents) {
        mapping.mouseenter = function () {
          this.model.focus();
        };
      }

      return mapping;
    },
    initialize: function initialize() {
      this.listenTo(this.model, 'change', this.render);
@@ -47,4 +51,4 @@
      return this;
    }
  });
})(Drupal, Backbone, Modernizr);
 No newline at end of file
})(Drupal, Backbone);
 No newline at end of file