jQuery Sortable -- remove a default behavior while dragging, restore after a drop
I've got a grid of pictures that I want to be able to drag/drop to sort. sortable() works great. The caveat is that I've also got the jQuery Fancybox plugin http://fancybox.net running which will open up a larger view of an image when clicked.
So you can click to start dragging, but as soon as you drop fancybox is triggered and the image enlarges.
I've tried s开发者_开发百科omething like this, but things get REALLY messed up (drag doesn't work at all anymore, my list gets rearranged all over the page, it's nasty):
$('#list').sortable({
start:function(e,ui) {
e.preventDefault();
}
});
Tried with both start
and stop
but no luck. I've also tried unbinding the click
handler for the items, but that didn't help either. Ideally I could sort of "hide" the fancybox handlers while dragging and then reinstate them after I drop. There may be a way to un-fancybox the whole list while dragging and then call $.fancybox()
again to start it up, but there's gotta be an easier way...
Thanks for any help!
All right, I got it working! I was sure that kwicher's below would work but I had to tweak it a bit. I ended up having to swap back and forth between the fancybox callbacks and the sortable callbacks:
$('#list').sortable({
start:function(e,ui) {
ui.item.addClass('drag_sort');
}
});
$('#list').fancybox({
onStart:function(items,index,opts) {
var obj = $(items[index]).parent()
if (obj.hasClass('drag_sort')) {
obj.removeClass('drag_sort');
return false;
}
}
});
Putting the removeClass()
in the stop
callback of sortable wasn't working: apparently the sortable stop
fires before the fancybox onStart
and so the class was gone by the time fancybox went to look.
Note that the sortable targets the <li>
in the list directly, but fancybox targets the <a>
inside the list item. That's why I have to get the parent()
in fancybox's onStart
. Oh, and simply going return false
in the onStart
is enough to get fancybox to ignore that click!
I solved this problem with a fairly low tech approach for a project. Inside of start I would mark something saying that the current click is related to a drag and should be ignored.
Then in the code that gets triggered for a normal click event I would check to see if the current click was marked as for dragging. Super low tech example:
var clickIsForDragging = false;
$('#list li').click(function() {
// Ignore dragging clicks
if (clickIsForDragging) {
clickIsForDragging = false;
return;
}
// Perform whatever normal click action
});
$('#list').sortable({
start:function(e,ui) {
e.preventDefault();
clickIsForDragging = true;
}
});
Obviously, using globals is not ideal, but at this this demonstrates the concept. I am wondering if some property of the click event can be marked to say that its a dragging click. Maybe I will do some fiddling later and see.
I also saw another post on Stack Overflow that dealt with a similar issue and used unbinding and rebinding: jQuery UI Sortable -- How can I cancel the click event on an item that's dragged/sorted?
I have not tested it yet but in principle that should work:
$('#list').sortable({
start:function(e,ui) {
//e.preventDefault(); - I am not sure that would be necessary
$('#list li').addClass('drag_sort');
}
stop:function(){
$('#list li').removeClass('drag_sort');
}
});
$('#list li').fancybox({
onStart:function(){
if($(this).hasClass('drag_sort')){
$.fancybox.cancel();
}
}
});
You could give it a try.
K
精彩评论