2010-11-08 21 views
95

Tengo una palpitación que debe aparecer cuando un usuario hace clic en un enlace.¿Puedes detectar "arrastrar" en jQuery?

El problema es que ese mismo enlace se puede hacer clic y arrastrar para reordenar. En este caso, no necesitaría que aparezca el throbber. Solo necesita aparecer si realmente está esperando ir a alguna parte.

¿Cómo puedo, con jQuery, crear un detector de eventos que sólo permitiría una Throbber que aparezca si su un clic a través de un enlace, y no un clic y arrastre?

+0

¿Quizás OOT? He intentado varios enfoques para arrastrar y soltar con jQuery incluyendo jQuery UI, mi propio código con mousedown, mouseup, mousemove events y el que mejor funcionó es https://github.com/haberman/jdragdrop. –

+0

Aquí hay otra solución simple sin ningún framework pesado. http://blog.blakesimpson.co.uk/read/51-swipe-js-detect-touch-direction-and-distance –

Respuesta

193

En el mousedown, comience a establecer el estado, si el evento mousemove se dispara, regístrelo, finalmente en el mouseup, verifique si el mouse se movió. Si se movió, hemos estado arrastrando. Si no nos mudamos, es un clic.

var isDragging = false; 
$("a") 
.mousedown(function() { 
    isDragging = false; 
}) 
.mousemove(function() { 
    isDragging = true; 
}) 
.mouseup(function() { 
    var wasDragging = isDragging; 
    isDragging = false; 
    if (!wasDragging) { 
     $("#throbble").toggle(); 
    } 
}); 

He aquí una demostración: http://jsfiddle.net/W7tvD/1399/

+5

¡respuesta increíble! Muchas gracias! – Trip

+0

hey..pueden ayudarme con esto http://stackoverflow.com/questions/19703617/replace-mousemove-by-mousedrag/19703798?noredirect=1#19703798 –

+2

Es posible que desee agregar un umbral de arrastre para que su los clics no se interpretan como drags en el elemento "a". Solo busque una cierta cantidad de cambio en un evento de desplazamiento de mouse x e y. –

0

Tiene que configurar un temporizador. Cuando el temporizador se agota, comience la pulsación y registre el clic. Cuando se produce arrastre, borre el temporizador para que nunca se complete.

+1

.. muy inteligente, ¿cómo se detecta un arrastre? – Trip

+1

cuando configura el Arrastrable, debe haber un evento onDrag. Enganchalo allí. –

0

Si está utilizando jQueryUI, hay un evento onDrag. Si no es así, adjunte su oyente a mouseup(), no haga clic en().

+1

¿Cómo diferenciaría Mouseup entre un arrastre y un clic? – Trip

+0

Hmmm - sí, creo que no pensé lo suficiente. Quizás pueda tener un oyente conectado al mousedown que registra las coordenadas del mouse. Entonces, si las coordenadas del mouse en el mouseup son las mismas (o muy cerca), considérelo un clic. – Pickle

+0

Esto no funciona: http://stackoverflow.com/questions/12231147/jquery-mouseup-not-being-detected-correctly –

23

Por alguna razón, las soluciones anteriores no estaban trabajando para mí. Fui con lo siguiente:

$('#container').on('mousedown', function(e) { 
    $(this).data('p0', { x: e.pageX, y: e.pageY }); 
}).on('mouseup', function(e) { 
    var p0 = $(this).data('p0'), 
     p1 = { x: e.pageX, y: e.pageY }, 
     d = Math.sqrt(Math.pow(p1.x - p0.x, 2) + Math.pow(p1.y - p0.y, 2)); 

    if (d < 4) { 
     alert('clicked'); 
    } 
}) 

Se pueden ajustar el límite de distancia a lo que le plazca, o incluso llevarlo hasta el final a cero.

+0

La mejor respuesta, me ayudó mucho. Solo un pensamiento: Math.sqrt no es realmente necesario, es mejor trabajar con distancias cuadradas (sqrt es lento, podría afectar a UX). –

+0

'sqrt' no es lento y no afectará a UX, incluso si lo hizo cientos de veces. – NateS

1

Para esta forma más simple es toque inicio, toque mover y toque final. Eso está funcionando tanto para PC como para dispositivos táctiles, solo verifíquelo en la documentación de jquery y espero que esta sea la mejor solución para usted. buena suerte

3

Pruebe esto: muestra cuándo está 'arrastrado'. ;) fiddle link

$(function() { 
    var isDragging = false; 
    $("#status").html("status:"); 
    $("a") 
    .mousedown(function() { 
     $("#status").html("status: DRAGGED");   
    }) 
    .mouseup(function() { 
     $("#status").html("status: dropped"); 
    }); 

    $("ul").sortable(); 
}); 
1

plugin de jQuery basado en la respuesta de Simen Echholt. Lo llamé un solo clic.

/** 
* jQuery plugin: Configure mouse click that is triggered only when no mouse move was detected in the action. 
* 
* @param callback 
*/ 
jQuery.fn.singleclick = function(callback) { 
    return $(this).each(function() { 
     var singleClickIsDragging = false; 
     var element = $(this); 

     // Configure mouse down listener. 
     element.mousedown(function() { 
      $(window).mousemove(function() { 
       singleClickIsDragging = true; 
       $(window).unbind('mousemove'); 
      }); 
     }); 

     // Configure mouse up listener. 
     element.mouseup(function(event) { 
      var wasDragging = singleClickIsDragging; 
      singleClickIsDragging = false; 
      $(window).unbind('mousemove'); 
      if(wasDragging) { 
       return; 
      } 

      // Since no mouse move was detected then call callback function. 
      callback.call(element, event); 
     }); 
    }); 
}; 

En uso:

element.singleclick(function(event) { 
    alert('Single/simple click!'); 
}); 

^^

0
// here is how you can detect dragging in all four directions 
var isDragging = false; 
$("some DOM element").mousedown(function(e) { 
    var previous_x_position = e.pageX; 
    var previous_y_position = e.pageY; 

    $(window).mousemove(function(event) { 
     isDragging = true; 
     var x_position = event.pageX; 
     var y_position = event.pageY; 

     if (previous_x_position < x_position) { 
      alert('moving right'); 
     } else { 
      alert('moving left'); 
     } 
     if (previous_y_position < y_position) { 
      alert('moving down'); 
     } else { 
      alert('moving up'); 
     } 
     $(window).unbind("mousemove"); 
    }); 
}).mouseup(function() { 
    var wasDragging = isDragging; 
    isDragging = false; 
    $(window).unbind("mousemove"); 
}); 
1
$(".draggable") 
.mousedown(function(e){ 
    $(this).on("mousemove",function(e){ 
     var p1 = { x: e.pageX, y: e.pageY }; 
     var p0 = $(this).data("p0") || p1; 
     console.log("dragging from x:" + p0.x + " y:" + p0.y + "to x:" + p1.x + " y:" + p1.y); 
     $(this).data("p0", p1); 
    }); 
}) 
.mouseup(function(){ 
    $(this).off("mousemove"); 
}); 

Esta solución utiliza la "on" y "off" funciones para unirse a un unbind un evento mousemove (bind y desvincular están en desuso). También puede detectar el cambio en las posiciones xey del ratón entre dos eventos mousemove.

12

Con jQuery UI simplemente haz esto!

$("#draggable").draggable({ 
    start: function() { 

    }, 
    drag: function() { 

    }, 
    stop: function() { 

    } 
}); 
+2

Necesita jquery-ui, pero es la manera más fácil. –

0

no tienes que variable de configuración, puede simplemente establecer si se está moviendo en los datos de atributos

$youtubeSlider.find('a') 
    .on('mousedown', function (e) { 
     $(this).data('moving', false); 
    }) 
    .on('mousemove', function (e) { 
     $(this).data('moving', true); 
    }) 
    .on('mouseup', function (e) { 
     if (!$(this).data('moving')) { 
      // Open link 
     } 
    }); 
1

asegúrese de que establece arrastrable atributo del elemento a modo falsa no tiene efectos secundarios cuando escucha eventos de mouseup:

<div class="thing" draggable="false">text</div> 

Luego, puede usar jQue ry:

$(function() { 
    var pressed, pressX, pressY, 
     dragged, 
     offset = 3; // helps detect when the user really meant to drag 

    $(document) 
    .on('mousedown', '.thing', function(e) { 
    pressX = e.pageX; 
    pressY = e.pageY; 
    pressed = true; 
    }) 
    .on('mousemove', '.thing', function(e) { 
    if (!pressed) return; 
    dragged = Math.abs(e.pageX - pressX) > offset || 
       Math.abs(e.pageY - pressY) > offset; 
    }) 
    .on('mouseup', function() { 
    dragged && console.log('Thing dragged'); 
    pressed = dragged = false; 
    }); 
}); 
Cuestiones relacionadas