0

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 something 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!

Rob Cameron
  • 9,674
  • 7
  • 39
  • 42

3 Answers3

2

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!

Rob Cameron
  • 9,674
  • 7
  • 39
  • 42
0

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?

Community
  • 1
  • 1
Ken Colton
  • 1,046
  • 10
  • 15
0

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

kwicher
  • 2,092
  • 1
  • 19
  • 28