Evento de clic de jQuery llamando después del evento taphold

Estoy desarrollando una aplicación PhoneGap para Android usando Jquery y Jquery Mobile.

Tengo una lista de elementos que necesitan dos eventos vinculados a cada elemento de la lista. Necesito un evento “taphold” y un evento “click”. El problema que tengo es que cuando hago un “taphold”, se desencadena el evento “taphold” correcto. Sin embargo, tan pronto como lo publico, el evento de clic también se activa. ¿Cómo puedo evitar que el evento de clic se active después de un taphold?

Código:

function LoadMyItems(items) { for(var idx in items) { var itemLine = '
' + '' + items[idx].item.name+ '
'; $('#my_list').append('
  • '+itemLine+'
  • '); $('#my_item_'+items[idx].user_item_id).bind('taphold', {userItem:items[idx]},ShowMyItemInfo); $('#my_item_'+items[idx].user_item_id).bind('click tap', {userItem:items[idx]},FitMyUpgradeItem); console.log('UserItem '+items[idx].user_item_id+' loaded and events bound'); } $('#my_items_loader').hide(); myScroll.refresh(); }

    Después de los consejos a continuación, esto es lo que terminé con. Esto funciona dentro del objeto iScroll.

     function LoadMyItems(items) { for(var idx in items) { var itemLine = '
    ' + '' + items[idx].item.name+ '
    '; $('#my_list').append('
  • '+itemLine+'
  • '); (function(index) { var tapTime = 0; var xPos = 0; var yPos = 0; $('#my_item_'+items[index].user_item_id).bind('vmousedown vmouseup', function (event) { if (event.type == 'vmousedown') { tapTime = new Date().getTime(); xPos = event.pageX; yPos = event.pageY; var timer = setTimeout(function() { var duration = (new Date().getTime() - tapTime); var xDiff = Math.abs(mouseXPos - xPos); var yDiff = Math.abs(mouseYPos - yPos); if(duration >= 700 && (yDiff <= 40 || mouseXPos == 0)) ShowItemInfo(items[index].item); },750); } else { //event.type == 'vmouseup' var duration = (new Date().getTime() - tapTime); var xDiff = Math.abs(event.pageX - xPos); var yDiff = Math.abs(event.pageY - yPos); tapTime = new Date().getTime(); if (duration < 699 && yDiff <= 40) { //this is a tap FitMyUpgradeItem(items[index]); } } }); $('#my_item_'+items[index].user_item_id).bind('touchmove',function(event) { event.preventDefault(); }); })(idx); console.log('UserItem '+items[idx].user_item_id+' loaded and events bound'); } $('#my_items_loader').hide(); myScroll.refresh(); }

    En lugar de usar tap y taphold (que he tratado de usar pero encontré los mismos problemas, parece ser un problema inherente al evento taphold ) puedes usar vmousedown y establecer un flag, luego vincular a vmouseup para determinar si era un tap o un taphold :

     var tapTime = 0; $('#my_item_'+items[idx].user_item_id).bind('vmousedown vmouseup', function (event) { if (event.type == 'vmousedown') { tapTime = new Date().getTime(); } else { //event.type == 'vmouseup' //here you can check how long the `tap` was to determine what do do var duration = (new Date().getTime() - tapTime); if (duration > 3000) { //this is a tap-hold ShowMyItemInfo(items[idx]); } else { //this is a tap FitMyUpgradeItem(items[idx]); } } }); 

    Para que esto funcione correctamente, deberá agregar un IIFE alrededor del código de bucle o cambiar ShowMyItemInfo(items[idx]); para trabajar sin hacer referencia a la variable que cambia cada iteración del ciclo. Un fácil de crear un IIFE es simplemente usar $.each() . De lo contrario, su ciclo se vería así:

     for(var idx in items) { (function (idx) { ... })(idx); } 

    IIFE = Expresión de función invocada inmediatamente. Nos permite tomar una “instantánea” del estado actual de las variables que pasamos al IIFE. Entonces, al pasar en idx (técnicamente la segunda instancia es la variable que se está transfiriendo, y la primera instancia es la variable disponible dentro de IIFE, que podría cambiarse a algo así como ids_new por simplicidad), se guarda el valor pasado. para cuando se dispare el controlador de eventos tap .

    Actualizar

    También puede establecer un tiempo de espera para determinar taphold lugar de usar el evento vmouseup :

     //setup a timer and a flag variable var tapTimer, isTapHold = false; $('#my_item_'+items[idx].user_item_id).bind('vmousedown vmouseup', function (event) { if (event.type == 'vmousedown') { //set the timer to run the `taphold` function in three seconds // tapTimer = setTimeout(function () { isTapHold = true; ShowMyItemInfo(items[idx]); }, 3000); } else { //event.type == 'vmouseup' //clear the timeout if it hasn't yet occured clearTimeout(tapTimer); //if the flag is set to false then this is a `tap` event if (!isTapHold) { //this is a tap, not a tap-hold FitMyUpgradeItem(items[idx]); } //reset flag isTapHold = false; } }); 

    De esta forma, el evento se disparará después de que el usuario mantenga presionado el dedo durante tres segundos. Luego, el controlador de eventos tap solo se activará si esos tres segundos no ocurrieron.

    Simplemente configure esto en la parte superior de su documento o en cualquier otro lugar antes de definir su par:

     $.event.special.tap.emitTapOnTaphold = false; 

    Entonces puedes usarlo así:

     $('#button').on('tap',function(){ console.log('tap!'); }).on('taphold',function(){ console.log('taphold!'); }); 

    Personalmente, creo que las respuestas aquí complicaron mucho el problema. Si solo quieres una manera simple de poder continuar usando el evento taphold e ignorar el evento click que se activa cuando lanzas un taphold, así es como resolví este mismo problema en mi propio proyecto:

     // We will use this flag to ignore click events we don't want var skipNextClick = false; //Set up your event handler. You could do these using two handlers or one. I chose one. $('div.element').on('click taphold', function (e) { //set up a quick bool flag that is true if click var isClick = (e.type == 'click'); if (isClick && !skipNextClick) { //run your code for normal click events here... } else if (isClick && skipNextClick) { //this is where skipped click events will end up... //we need to reset our skipNextClick flag here, //this way, our next click will not be ignored skipNextClick = false; } else { //taphold event //to ignore the click event that fires when you release your taphold, //we set the skipNextClick flag to true here. skipNextClick = true; //run your code for taphold events here... } }); 

    Use tap \ vclick y taphold en su lugar: el evento Tap se activa dos veces después de un taphold.

     $('#my_item_'+items[idx].user_item_id).bind('vclick', ... $('#my_item_'+items[idx].user_item_id).bind('taphold', ... 

    En este ejemplo, el clic no se llama en realidad después del taphold. Verifíquelo aquí: http://jsfiddle.net/YL8hj/43/

    Editar:

    jQuery Mobile vincula automáticamente el evento táctil a algunos elementos. Al combinar iScroll con jQuery Mobile, podría ser una buena idea vincular una función separada al evento ‘touchmove’ y evitar que el evento burbujee (event.preventDefault ()). Al hacer esto, jQuery Mobile no podrá manejar el evento táctil mientras los usuarios interactúan con el elemento iScroll.

    también http://appcropolis.com/blog/jquery-wrapper-for-iscroll/ credit https://stackoverflow.com/a/9408567/643500