Prévenir l'événement de clic avec jQuery drag and drop
j'ai un élément sur la page qui est draggabe avec jQuery. Ces éléments ont un clic événement qui navigue vers une autre page (liens ordinaires par exemple).
Quelle est la meilleure façon d'empêcher le clic de tirer sur la chute d'un tel élément, tout en permettant de le cliquer dans l'état de non glisser-déposer?
j'ai ce problème avec sortable éléments, mais pense qu'il est bon d'avoir la solution générale de glisser-déposer.
j'ai résolu le problème pour moi. Après cela trouvé que la même solution existe pour Scriptaculous , mais peut-être quelqu'un a une meilleure façon d'atteindre cela.
14 réponses
une solution qui a bien fonctionné pour moi et qui ne nécessite pas de temps mort: (oui je suis un peu pédant ; -)
j'ajoute une classe marqueur à l'élément lorsque le déplacement commence, par exemple 'noclick'. Lorsque l'élément est supprimé, l'événement de clic est déclenché -- plus précisément si le déplacement se termine, en fait il n'a pas besoin d'être abandonné sur une cible valide. Dans le gestionnaire de clic, je supprime la classe de marqueur si elle est présente, sinon le clic est manipulé normalement.
$('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
}
});
Solution est d'ajouter le gestionnaire de clic qui empêchera le clic de se propager au début de la traînée. Puis retirez du gestionnaire après la chute est effectuée. La dernière action devrait être retardée un peu pour que la prévention de clic fonctionne.
Solution pour sortable:
...
.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);
}
...
})
Solution pour égouttage:
...
.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);
}
...
})
j'aimerais ajouter à cela qu'il semble empêcher l'événement de clic ne fonctionne que si l'événement de clic est défini après l'événement draggable ou sortable. Si le clic est ajouté en premier, il est activé sur la traînée.
j'ai eu le même problème et j'ai essayé plusieurs approches et aucune n'a fonctionné pour moi.
Solution 1
$('.item').click(function(e)
{
if ( $(this).is('.ui-draggable-dragging') ) return false;
});
ne fait rien pour moi. L'élément est cliqué après ce déplacement est effectué.
Solution 2 (par Tom De Boer)
$('.item').draggable(
{
stop: function(event, ui)
{
$( event.originalEvent.target).one('click', function(e){ e.stopImmediatePropagation(); } );
}
});
cela fonctionne très bien mais échoue dans un cas - quand j'allais plein écran onclick:
var body = $('body')[0];
req = body.requestFullScreen || body.webkitRequestFullScreen || body.mozRequestFullScreen;
req.call(body);
Solution 3 (par 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);
}
})
ça ne marche pas pour moi.
Solution 4 - le seul qui a fonctionné très bien
$('.item').draggable(
{
});
$('.item').click(function(e)
{
});
ouais, c'est ça - le bon de commande fait l'affaire - vous avez d'abord besoin de se lier draggable (), puis cliquez sur() de l'événement. Même quand j'ai mis le code de basculement du plein écran dans click (), il n'est pas allé sur le plein écran quand glisser. Parfait pour moi!
Je n'aime pas vraiment utiliser de minuteries ou de prévention, donc ce que j'ai fait est ceci:
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;
}
Rocksolid..
j'ai trouvé que l'utilisation de la fonction de clic jQuery standard:
$("#element").click(function(mouseEvent){ // click event });
fonctionne très bien dans jQuery UI. L'événement de clic ne sera pas exécuté lorsque le glisser-déposer. :)
la version de lex82 mais pour .sortable ()
start: function(event, ui){
ui.item.find('.ui-widget-header').addClass('noclick');
},
et que vous avez besoin est:
start: function(event, ui){
ui.item.addClass('noclick');
},
et voici ce que j'utilise pour la bascule:
$("#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");
}
});
une alternative possible pour la réponse de Sasha sans prévenir la défaillance:
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);
},
dans jQuery UI, les éléments traînés sont classés dans la classe"ui-draggable-dragging".
Nous pouvons donc utiliser cette classe pour déterminer s'il faut cliquer ou non, il suffit de retarder l'événement.
Vous n'avez pas besoin d'utiliser les fonctions de rappel "start" Ou "stop", faites simplement:
$('#foo').on('mouseup', function () {
if (! $(this).hasClass('ui-draggable-dragging')) {
// your click function
}
});
ceci est déclenché à partir de "mouseup", plutôt que "mousedown" ou "click" - donc il ya un léger retard, pourrait ne pas être parfait - mais il est plus facile que d'autres solutions sont suggérées ici.
après avoir lu ceci et quelques fils c'était la solution avec laquelle je suis allé.
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;
}
});
avez-vous essayé de désactiver le lien En utilisant event.preventDefault(); dans le début de l'événement et de le réactiver dans les glisser arrêté de l'événement ou de la baisse de l'événement à l'aide de délier?
juste une petite ride à ajouter aux réponses données ci-dessus. J'ai dû faire un div qui contient un élément SalesForce modulable, mais L'élément SalesForce a une action onclick définie dans le html à travers un certain VisualForce gobbledigook.
évidemment, cela viole la règle "définir l'action click après l'action drag", alors comme solution de contournement, j'ai redéfini L'action de L'élément SalesForce pour qu'elle soit déclenchée "onDblClick", et j'ai utilisé ce code pour le conteneur 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');
}
});
l'événement de clic du parent cache essentiellement le besoin de double-cliquer l'élément enfant, laissant l'expérience utilisateur intacte.
j'ai essayé comme ceci:
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);
}
});
dans mon cas, il a fonctionné comme ceci:
$('#draggable').draggable({
start: function(event, ui) {
$(event.toElement).one('click', function(e) { e.stopPropagation(); });
}
});