How to bind 'touchstart' and 'click' events but not respond to both?

前端 未结 30 3064
抹茶落季
抹茶落季 2020-11-22 14:08

I\'m working on a mobile web site that has to work on a variety of devices. The one\'s giving me a headache at the moment are BlackBerry.

We need to support both key

相关标签:
30条回答
  • 2020-11-22 14:32

    For simple features, just recognize touch or click I use the following code:

    var element = $("#element");
    
    element.click(function(e)
    {
      if(e.target.ontouchstart !== undefined)
      {
        console.log( "touch" );
        return;
      }
      console.log( "no touch" );
    });
    

    This will return "touch" if the touchstart event is defined and "no touch" if not. Like I said this is a simple approach for click/tap events just that.

    0 讨论(0)
  • 2020-11-22 14:33

    EDIT: My former answer (based on answers in this thread) was not the way to go for me. I wanted a sub-menu to expand on mouse enter or touch click and to collapse on mouse leave or another touch click. Since mouse events normally are being fired after touch events, it was kind of tricky to write event listeners that support both touchscreen and mouse input at the same time.

    jQuery plugin: Touch Or Mouse

    I ended up writing a jQuery plugin called "Touch Or Mouse" (897 bytes minified) that can detect whether an event was invoked by a touchscreen or mouse (without testing for touch support!). This enables the support of both touchscreen and mouse at the same time and completely separate their events.

    This way the OP can use touchstart or touchend for quickly responding to touch clicks and click for clicks invoked only by a mouse.

    Demonstration

    First one has to make ie. the body element track touch events:

    $(document.body).touchOrMouse('init');
    

    Mouse events our bound to elements in the default way and by calling $body.touchOrMouse('get', e) we can find out whether the event was invoked by a touchscreen or mouse.

    $('.link').click(function(e) {
      var touchOrMouse = $(document.body).touchOrMouse('get', e);
    
      if (touchOrMouse === 'touch') {
        // Handle touch click.
      }
      else if (touchOrMouse === 'mouse') {
        // Handle mouse click.
      }
    }
    

    See the plugin at work at http://jsfiddle.net/lmeurs/uo4069nh.

    Explanation

    1. This plugin needs to be called on ie. the body element to track touchstart and touchend events, this way the touchend event does not have to be fired on the trigger element (ie. a link or button). Between these two touch events this plugin considers any mouse event to be invoked by touch.
    2. Mouse events are fired only after touchend, when a mouse event is being fired within the ghostEventDelay (option, 1000ms by default) after touchend, this plugin considers the mouse event to be invoked by touch.
    3. When clicking on an element using a touchscreen, the element gains the :active state. The mouseleave event is only fired after the element loses this state by ie. clicking on another element. Since this could be seconds (or minutes!) after the mouseenter event has been fired, this plugin keeps track of an element's last mouseenter event: if the last mouseenter event was invoked by touch, the following mouseleave event is also considered to be invoked by touch.
    0 讨论(0)
  • 2020-11-22 14:35

    This is the fix that I "create" and it take out the GhostClick and implements the FastClick. Try on your own and let us know if it worked for you.

    $(document).on('touchstart click', '.myBtn', function(event){
            if(event.handled === false) return
            event.stopPropagation();
            event.preventDefault();
            event.handled = true;
    
            // Do your magic here
    
    });
    
    0 讨论(0)
  • 2020-11-22 14:37

    Just adding return false; at the end of the on("click touchstart") event function can solve this problem.

    $(this).on("click touchstart", function() {
      // Do things
      return false;
    });
    

    From the jQuery documentation on .on()

    Returning false from an event handler will automatically call event.stopPropagation() and event.preventDefault(). A false value can also be passed for the handler as a shorthand for function(){ return false; }.

    0 讨论(0)
  • 2020-11-22 14:37

    This worked for me, mobile listens to both, so prevent the one, which is the touch event. desktop only listen to mouse.

     $btnUp.bind('touchstart mousedown',function(e){
         e.preventDefault();
    
         if (e.type === 'touchstart') {
             return;
         }
    
         var val = _step( _options.arrowStep );
                   _evt('Button', [val, true]);
      });
    
    0 讨论(0)
  • 2020-11-22 14:37

    I am also working on an Android/iPad web app, and it seems that if only using "touchmove" is enough to "move components" ( no need touchstart ). By disabling touchstart, you can use .click(); from jQuery. It's actually working because it hasn't be overloaded by touchstart.

    Finally, you can binb .live("touchstart", function(e) { e.stopPropagation(); }); to ask the touchstart event to stop propagating, living room to click() to get triggered.

    It worked for me.

    0 讨论(0)
提交回复
热议问题