soltar example ejemplos ejemplo drop arrastrar archivos and javascript jquery events drag-and-drop jquery-ui-sortable

javascript - example - Evitar el evento de clic con jQuery arrastrar y soltar



drag and drop jquery example (14)

¿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?

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 descubrió que existe la misma solución para Scriptaculous , pero tal vez alguien tenga una mejor manera de lograrlo.


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; } });


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í.


En mi caso, funcionó así:

$(''#draggable'').draggable({ start: function(event, ui) { $(event.toElement).one(''click'', function(e) { e.stopPropagation(); }); } });


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. :)


Intenté así:

var dragging = true; $(this).click(function(){ if(!dragging){ do str... } }); $(this).draggable({ start: function(event, ui) { dragging = true; }, stop: function(event, ui) { setTimeout(function(){dragging = false;}, 300); } });


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); } ... })


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.


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..


Solo una pequeña arruga para agregar a las respuestas dadas arriba. Tuve que hacer que un div que contiene un elemento SalesForce se pueda arrastrar, pero el elemento SalesForce tiene una acción onclick definida en el html a través de algún gobbledigook de VisualForce.

Obviamente, esto infringe la regla "definir acción de clic después de la acción de arrastre", por lo que como solución redefiní la acción del elemento SalesForce para que se active "onDblClick" y usé este código para el contenedor div:

$(this).draggable({ zIndex: 999, revert: true, revertDuration: 0, start: function(event, ui) { $(this).addClass(''noclick''); } }); $(this).click(function(){ if( $(this).hasClass(''noclick'')) { $(this).removeClass(''noclick''); } else { $(this).children(":first").trigger(''dblclick''); } });

El evento de clic de los padres básicamente oculta la necesidad de hacer doble clic en el elemento secundario, dejando intacta la experiencia del usuario.


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!


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); },


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, por ejemplo, ''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 } });


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"); } });