web-dev-qa-db-fra.com

Empêcher le clic de fantôme en reliant 'touchstart' et 'click'

Je développe une application et la teste sur mon ordinateur de bureau et mon mobile. J'essaie de réparer ces lentes pressions sur le mobile et viens d'apprendre la différence entre touchstart et click.

J'ai donc lié mes boutons avec jQuery pour effectuer les deux touchstart et cliquer comme suit:

$('.button').on('touchstart click', function(){
});

Maintenant, l'application fonctionne légèrement mieux au téléphone. Cependant, il effectue un clic tactile, puis un clic régulier, c'est-à-dire potentiellement un double clic, ou lorsque la diapositive suivante arrive, il clique sur quelque chose. Dans mon cas, un formulaire apparaît et le champ de saisie qui apparaît dans l'espace où le bouton sur lequel vous avez cliqué était sélectionné est sélectionné. Clic de fantôme. 

Comment puis-je dire à ma fonction que s'il y a un contact, ignorez le clic? 

Ou mieux encore, y a-t-il un moyen de dire à jQuery de simplement reconnaître tous les «clics» comme une touche?

Je voudrais supprimer la liaison 'clic', mais je ne peux pas tester si facilement dans mon environnement de bureau si facilement.

13
willdanceforfun

Si vous voulez faire des choses spécifiques pour différents types d'événements, utilisez e.type

$('.button').on('touchstart click', function(e) {    
    e.preventDefault(); //prevent default behavior
    if(e.type == "touchstart") {
        // Handle touchstart event.
    } else if(e.type == "click") {
        // Handle click event.
    }
});
22
Krishna

Touchstart doit avoir lieu avant clic, aussi je supprime le gestionnaire de clic si l'événement est de type touchstart. Cela semble bien fonctionner pour mes besoins:

$('.do-popdown').on('click touchstart', handlePopdown);
function handlePopdown(e){
    if(e.type == 'touchstart') {
        $('.do-popdown').off('click', handlePopdown).click(function(e){
            // do nothing
            e.stopPropagation();
            e.preventDefault();
            return false;
        });
    }
    // do my handling...
    // and nothing else:
    e.stopPropagation();
    e.preventDefault();
    return false;
}

La e.stopPropagation(); e.preventDefault(); return false; est peut-être excessive, mais je l'utilise pour différents éléments (<a>, <div>, <span>, <button>, etc.) et cela répond à mes besoins habituels.

EDIT: Une approche plus générale (meilleure?) Consiste à créer quelque chose de similaire au classeur d'événements .click() bien connu:

jQuery.fn.extend({
    clickOrTouch: function(handler) {
        return this.each(function() {
            var event = ('ontouchstart' in document) ? 'touchstart' : 'click';
            $(this).on(event, handler);
        });
    }
});

De cette façon, seul l'événement approprié est associé aux éléments sélectionnés.

Je suppose qu'un nom plus "approprié" serait .touchstartOrClick() mais comme il remplace plus ou moins .click(), j'ai décidé de commencer le nom par click.

Ceci peut être utilisé comme .click(). Par exemple, placez une button à l'intérieur d'une div et exécutez:

$('button').clickOrTouch(doSomething);
$('div').clickOrTouch(doSomething);
function doSomething(e) {
    $('body').append(this.tagName + ' ' + e.type + '<br>');
    e.stopPropagation();
}

Cela affichera "DIV click" ou "BUTTON touchstart" en fonction de la façon dont il est déclenché. Si cela est utilisé sur un lien, ajoutez e.preventDefault() si nécessaire dans votre gestionnaire.

12
Slashback

Ce code de @Krishna ne fonctionne pas pour moi:

$('.button').on('touchstart click', function(e) {    
    e.stopPropagation(); //stops propagation
    if(e.type == "touchstart") {
        // Handle touchstart event.
    } else if(e.type == "click") {
        // Handle click event.
    }
});

Mais celui-ci devrait fonctionner, comme @Slashback l’avait initialement suggéré.

$('.button').on('touchstart click', function(e) {    
    e.preventDefault();

    if(e.type == "touchstart") {
        // Handle touchstart event.
    } else if(e.type == "click") {
        // Handle click event.
    }
});

.preventDefault () seul a fonctionné pour moi au lieu de .stopPropagation (). Je ne suis pas obligé de faire trop.

3
reigngel

J'utilise PhoneGap. Cela peut être utile:

function longTapEvent(id, longTapFun) {
    $(id).click(function() {
        longTapFun();
        return;
    })

    $(id).unbind("touchstart");
    $(id).bind("touchstart", function() {
        //do sth...
    });
    $(id).unbind("touchend");
    $(id).bind("touchend", function() {
        //do sth...
    });
}
1
sunflower zhang

Vous pouvez détecter un clic et échapper à l'activation actuelle de la fonction si l'incendie précédent n'était pas un clic (c'est-à-dire un toucher ou autre chose) - dans Vanilla js:

buttonx.addEventListener('touchend',clicktap);
buttonx.addEventListener('click',clicktap);

function clicktap(e) {
var c = e.type.includes("click"); // or "mouse" if using "mousedown"
if (c && (this.wastouched)) return this.wastouched = 0;
this.wastouched = !c;

// ..run things..

}
0
CheeseFrog

J'utilise les éléments suivants dans mes projets: 

$('.button').on('touchstart', function() {

   var thisButton = $(this); 
   if(!thisButton.hasClass('disabled')) {
     thisButton.addClass('disabled'); //add class disabled to prevent double execution

     ............rest of code

     window.setTimeout(function () {
        thisButton.removeClass('disabled'); //remove class disalbed after 300ms
     }, 300);

});

J'espère que cela aidera quelqu'un.

0
Roumelis George

L'utilisation de data-tap-disabled = "true" sur l'élément résout mon problème.

http://ionicframework.com/docs/api/page/tap/

0
Ananda Naphade