web-dev-qa-db-de.com

Klickereignis mit jQuery per Drag & Drop verhindern

Ich habe ein Element auf der Seite, das mit jQuery draggabe ist. Diese Elemente verfügen über ein Klickereignis, das zu einer anderen Seite navigiert (z. B. normale Links).

Was ist der beste Weg, um zu verhindern, dass beim Ablegen eines solchen Elements ein Klick ausgelöst wird, während das Klicken im Drag-and-Drop-Zustand erfolgt?

Ich habe dieses Problem mit sortierbaren Elementen, denke aber, dass es gut ist, eine Lösung für allgemeines Ziehen und Ablegen zu haben.

Ich habe das Problem für mich gelöst. Nachdem diese gefunden wurde, gibt es dieselbe Lösung existiert für Scriptaculous , aber vielleicht hat jemand einen besseren Weg, dies zu erreichen.

78

Die Lösung besteht darin, einen Click-Handler hinzuzufügen, der verhindert, dass das Klicken beim Starten des Ziehens propagiert wird. Entfernen Sie dann diesen Handler, nachdem der Drop ausgeführt wurde. Die letzte Aktion sollte etwas verzögert werden, damit die Klickverhinderung funktioniert.

Lösung für sortierbar:

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

Lösung für schleppbare:

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

Eine Lösung, die für mich gut funktioniert hat und keine Auszeit erfordert: (Ja, ich bin ein bisschen pedantisch ;-)

Ich füge dem Element eine Markierungsklasse hinzu, wenn das Ziehen beginnt, z. 'noclick'. Wenn das Element gelöscht wird, wird das Klickereignis ausgelöst. Genauer gesagt, wenn das Ziehen beendet ist, muss es nicht auf ein gültiges Ziel fallen gelassen werden. Im Click-Handler entferne ich die Markierungsklasse, falls vorhanden, andernfalls wird der Klick normal behandelt.

$('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
    }
});
85
lex82

Ich möchte hinzufügen, dass das Click-Ereignis scheinbar nur dann zu funktionieren scheint, wenn das Click-Ereignis NACH dem Draggable- oder Sortier-Event definiert ist. Wenn der Klick zuerst hinzugefügt wird, wird er beim Ziehen aktiviert.

11
kasakka

Ich hatte das gleiche Problem und versuchte mehrere Ansätze und keiner hat für mich funktioniert.

Lösung 1

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

tut nichts für mich Das Element wird nach dem Ziehen angeklickt.

Lösung 2 (von Tom de Boer)

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

Das funktioniert gut, schlägt aber in einem Fall fehl, als ich den Vollbild-Onclick-Modus besuchte:

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

Lösung 3 (von 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);
        }
})

Das funktioniert bei mir nicht.

Lösung 4 - die einzige, die gut funktioniert hat

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

Ja, das ist es - die richtige Reihenfolge macht den Trick - zuerst müssen Sie draggable () binden, dann click (). Selbst wenn ich den Vollbild-Umschaltcode in das click () -Ereignis setze, wurde beim Ziehen immer noch nicht der Vollbildmodus angezeigt. Perfekt für mich!

11
Tom

Ich fand das unter Verwendung der Standard-jQuery-Klickfunktion:

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

funktioniert gut in jQuery UI. Das Klickereignis wird beim Ziehen und Ablegen nicht ausgeführt. :)

9
Norm

Ich mag es nicht wirklich, Timer zu verwenden oder zu verhindern, also habe ich Folgendes getan:

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

8
Tim Baas

In der jQuery-Benutzeroberfläche erhalten Elemente, die gezogen werden, die Klasse "Ziehen von Ui-Ziehen".
Wir können diese Klasse daher verwenden, um zu bestimmen, ob Sie klicken oder nicht, um das Ereignis zu verzögern.
Sie brauchen nicht die Callback-Funktionen "start" oder "stop" zu verwenden.

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

Dies wird durch "Mouseup" ausgelöst und nicht durch "Mausedown" oder "Klick" - daher gibt es eine leichte Verzögerung, die möglicherweise nicht perfekt ist - aber es ist einfacher als andere hier vorgeschlagene Lösungen.

3
lukesrw

Eine mögliche Alternative für Sashas Antwort, ohne die Standardeinstellung zu verhindern:

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
Matt Styles

Lex82-Version, jedoch für .sortable ()

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

und du brauchst vielleicht nur:

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

und hier ist was ich für den Toggle verwende:

$("#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
orolo

Nachdem ich dies und ein paar Threads durchgelesen hatte, war dies die Lösung, mit der ich gegangen bin.

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
jwdreger

Ich habe es so versucht:

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

});
0
sun

In meinem Fall hat es so funktioniert:

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

Haben Sie versucht, die Verknüpfung mit event.preventDefault () zu deaktivieren? im Startereignis und erneutes Aktivieren im Ziehen angehaltenen Ereignis oder im Dropereignis mit Unbind?

0
alienonland

Nur ein wenig Falten, um die Antworten oben zu ergänzen. Ich musste ein div erstellen, das ein SalesForce-Element enthält, das sich ziehen lässt, aber für das SalesForce-Element ist eine Onclick-Aktion definiert, die in html durch einige VisualForce-Befehle definiert wird.

Offensichtlich verstößt dies gegen die Regel "Klickaktion nach der Drag-Aktion definieren". Daher habe ich als Workaround die Aktion des SalesForce-Elements neu definiert, die "onDblClick" ausgelöst werden soll, und diesen Code für den Container div verwendet:

$(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');
    }
});

Das Click-Ereignis des übergeordneten Elements verbirgt im Wesentlichen die Notwendigkeit, auf das untergeordnete Element zu doppelklicken, sodass die Benutzererfahrung erhalten bleibt.

0
geekbrit