Pregunta Evitar el evento de clic con jQuery arrastrar y soltar


Tengo elementos en la página que son draggabe con jQuery. Estos elementos tienen un clic evento que navega a otra página (enlaces ordinarios, por ejemplo).

¿Cuál es la mejor manera de evitar que el clic se dispare al soltar dicho elemento, al tiempo que permite hacer clic en él sin arrastrar y soltar?

Tengo este problema con los elementos ordenables, pero creo que es bueno tener una solución para arrastrar y soltar en general.

He resuelto el problema por mí mismo. Después de eso encontró esa misma solución existe para Scriptaculous, pero tal vez alguien tenga una mejor manera de lograr eso.


76
2017-11-20 16:25


origen


Respuestas:


Una solución que funcionó bien para mí y que no requiere un tiempo de espera: (sí, soy un poco pedante ;-)

Agrego una clase de marcador al elemento cuando se inicia el arrastre, p. 'noclick'. Cuando se suelta el elemento, se activa el evento click, más precisamente si el arrastre finaliza, en realidad no tiene que soltarse en un objetivo válido. En el controlador de clics, elimino la clase de marcador si está presente; de ​​lo contrario, el clic se maneja normalmente.

$('your selector').draggable({
    start: function(event, ui) {
        $(this).addClass('noclick');
    }
});

$('your selector').click(function(event) {
    if ($(this).hasClass('noclick')) {
        $(this).removeClass('noclick');
    }
    else {
        // actual click event code
    }
});

83
2018-03-26 19:16



La solución es agregar un controlador de clics que evitará que el clic se propague al inicio del arrastre. Y luego elimine ese controlador después de realizar una caída. La última acción debe retrasarse un poco para que la prevención de clics funcione.

Solución para ordenar:

...
.sortable({
...
        start: function(event, ui) {
            ui.item.bind("click.prevent",
                function(event) { event.preventDefault(); });
        },
        stop: function(event, ui) {
            setTimeout(function(){ui.item.unbind("click.prevent");}, 300);
        }
...
})

Solución para arrastrar:

...
.draggable({
...
        start: function(event, ui) {
            ui.helper.bind("click.prevent",
                function(event) { event.preventDefault(); });
        },
        stop: function(event, ui) {
            setTimeout(function(){ui.helper.unbind("click.prevent");}, 300);
        }
...
})

38
2017-11-20 16:26



Me gustaría agregar a esto que parece que prevenir el evento click solo funciona si el evento click se define DESPUÉS del evento arrastrable o ordenable. Si el clic se agrega primero, se activa al arrastrar.


11
2018-03-15 13:34



Tuve el mismo problema e intenté varios enfoques y ninguno funcionó para mí.

Solución 1

$('.item').click(function(e)
{            
    if ( $(this).is('.ui-draggable-dragging') ) return false;
});  

no hace nada por mí Se hace clic en el elemento después de que se realiza el arrastre.

Solución 2 (por Tom de Boer)

$('.item').draggable(
{   
    stop: function(event, ui) 
    {
         $( event.originalEvent.target).one('click', function(e){ e.stopImmediatePropagation(); } );
    }
});

Esto funciona bien pero falla en un caso: cuando iba a pantalla completa en clic:

var body = $('body')[0];     
req = body.requestFullScreen || body.webkitRequestFullScreen || body.mozRequestFullScreen;
req.call(body); 

Solución 3 (por Sasha Yanovets)

 $('.item').draggable({
        start: function(event, ui) {
            ui.helper.bind("click.prevent",
                function(event) { event.preventDefault(); });
        },
        stop: function(event, ui) {
            setTimeout(function(){ui.helper.unbind("click.prevent");}, 300);
        }
})

Esto no funciona para mi.

Solución 4- el único que funcionó bien

$('.item').draggable(
{   
});
$('.item').click(function(e)
{  
});

Sí, eso es todo, el orden correcto es el truco: primero debes vincular el evento arrastrable () y luego el clic (). Incluso cuando puse el código de alternancia de pantalla completa en el evento click (), todavía no fue a pantalla completa al arrastrar. ¡Perfecto para mi!


10
2018-03-28 12:44



Realmente no me gusta usar temporizadores o prevenir, así que lo que hice es esto:

var el, dragged

el = $( '#some_element' );

el.on( 'mousedown', onMouseDown );
el.on( 'mouseup', onMouseUp );
el.draggable( { start: onStartDrag } );

onMouseDown = function( ) {
  dragged = false;
}

onMouseUp = function( ) {
  if( !dragged ) {
    console.log('no drag, normal click')
  }
}

onStartDrag = function( ) {
  dragged = true;
}

Roca sólida..


9
2017-11-15 08:48



Encontré que usando la función de clic jQuery estándar:

$("#element").click(function(mouseEvent){ // click event }); 

funciona bien en jQuery UI. El evento click no se ejecutará al arrastrar y soltar. :)


9
2018-01-01 00:44



versión de lex82 pero para .sortable ()

 start: function(event, ui){
 ui.item.find('.ui-widget-header').addClass('noclick');
 },

y es posible que solo necesites:

 start: function(event, ui){
 ui.item.addClass('noclick');
 },

y esto es lo que estoy usando para alternar:

$("#datasign-widgets .ui-widget-header").click(function(){
if ($(this).hasClass('noclick')) {
$(this).removeClass('noclick');

}
else {
$(this).next().slideToggle();
$(this).find('.ui-icon').toggleClass("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
}
});

3
2018-01-10 20:24



Una posible alternativa para la respuesta de Sasha sin impedir el incumplimiento:

var tmp_handler;
.sortable({
        start : function(event,ui){
            tmp_handler = ui.item.data("events").click[0].handler;
            ui.item.off();
        },
        stop : function(event,ui){
            setTimeout(function(){ui.item.on("click", tmp_handler)}, 300);
        },

3
2017-11-09 19:10



En jQuery UI, los elementos que se arrastran reciben la clase "ui-draggable-dragging".
Por lo tanto, podemos utilizar esta clase para determinar si hacer clic o no, simplemente retrasar el evento.
No necesita usar las funciones de devolución de llamada "inicio" o "detención", simplemente haga lo siguiente:

$('#foo').on('mouseup', function () {
    if (! $(this).hasClass('ui-draggable-dragging')) {
        // your click function
    }
});

Esto se desencadena desde "mouseup", en lugar de "mousedown" o "click", por lo que hay un ligero retraso, puede que no sea perfecto, pero es más fácil que otras soluciones sugeridas aquí.


3
2018-03-04 18:32



Después de leer esto y algunos hilos, esta fue la solución con la que fui.

var dragging = false;
$("#sortable").mouseover(function() {
    $(this).parent().sortable({
        start: function(event, ui) {
            dragging = true;
        },
        stop: function(event, ui) {
            // Update Code here
        }
    })
});
$("#sortable").click(function(mouseEvent){
    if (!dragging) {
        alert($(this).attr("id"));
    } else {
        dragging = false;
    }
});

1
2017-09-09 17:11



¿Has intentado desactivar el enlace utilizando event.preventDefault (); en el evento de inicio y volver a habilitarlo en el evento de arrastrar detenido o evento de soltar mediante desvinculación?


0
2017-11-20 16:29