Conflicts between double tap and click. (jQuery and Hammer.js)

3

I'm trying something different, I'd like to implement something similar to an Instagram feature: two tapas to give like.

To try this, I'm using the latest versions of jQuery and Hammer.js. I'm not an advanced programmer in this area, however I've come up with the following logic to identify which event the user wants to run:

var postDoubleTapped;
postDoubleTapped = false;

Hammer($('.post').get(0)).on('doubletap', function() {
  event.preventDefault();
  postDoubleTapped = true;

  console.log('Double tap!');
  return false;
});

$(document).on('click', '.post a', function(event) {
  event.preventDefault();
  console.log(postDoubleTapped);

  setTimeout((function(_this) {
    return function() {
      if (!postDoubleTapped) {
        location.href = $(_this).attr('href');
      }
      postDoubleTapped = false;
    };
  })(this), 500);
  return false;
});

As you can see in the example ( link ), it did not work! The console returns:

Thereisanotherproblem,Icannotreproducetarget="_blank" in the a tag.

Is this the best method to do this? Am I on the right track? How can I fix this?

    
asked by anonymous 29.04.2014 / 02:35

1 answer

1

Your problem is that setTimeout is called twice: once in the first click / slap and once in the second. What is being returned in the console is natural: 1) the first is detected, prints false and creates a setTimeout ; 2) Hammer treats doubletap , printing Double tap! ; 3) the second is detected, prints true and creates a new setTimeout .

The first setTimeout executes, assigning postDoubleTapped back to false . When the second setTimeout executes, this variable already has false value, so it does the redirect.

To solve the problem, let's break it down:

  • For a quick fix, save the return value of setTimeout to a variable and - before creating another - destroy it using clearTimeout :

    var ultimoTimeout = null;
    
    ...
    
    $(document).on('click', '.post a', function(event) {
        event.preventDefault();
        console.log(postDoubleTapped);
    
        if ( ultimoTimeout !== null )
            clearTimeout(ultimoTimeout);
        ultimoTimeout = setTimeout((function(_this) {
            ...
    
  • For a "correct" solution, the interesting thing would be to prevent the event handled by Hammer from propagating. First, I noticed that you're using event global, instead of taking the function parameter, but I do not think it made any difference in practice:

    Hammer($('.post').get(0)).on('doubletap', function() {
    
    // Não deveria ser:
    //Hammer($('.post').get(0)).on('doubletap', function(event) {
    

    In addition, you call preventDefault , but not stopPropagation (this should prevent the event from propagating - getting treated by jQuery). I say "should" because - for some reason I do not know - using it does not seem to have made a difference ... I noticed that the target of the event handled by Hammer is the image, not the hyperlink, since the image is in of the link. I do not understand what's going on, so a workaround would use the solution proposed in item 1.

  • Finally, it does not matter if your link has target="_blank" or not, since you're doing - via JavaScript - a redirection of the current window to the new address (but you already knew that yourself, right?). The workaround is to use window.open instead of location.href :

    if (!postDoubleTapped) {
        window.open($(_this).attr('href'), $(_this).attr('target') || "_self");
    }
    

    This will cause the browser to try opening the URL in the window specified by the target attribute of your link (in this case, _blank ) or - if that attribute does not exist - in itself window (% with%). In my test, Chrome blocked redirection (as if it were a popup) and - according to this question in SOen - there's not much you can do about it ...

    As I read , the problem is in _self - if window opening is a direct consequence of the click (ie occurring while the click event itself was being handled) then I believe the browser would open normally. But as it occurs at an arbitrary time (when setTimeout executes) the popup blocker thinks that the site tried to open a window on its behalf, and will not. As for this, I'm afraid I have nothing to suggest for now ...

  • 29.04.2014 / 14:52