Js / jQuery Drag'n'Drop, recount drop targets

I have the following problem: I have a large tree that has sub-nodes that can be folded and expanded on demand (data in nodes is obtained using AJAX). However, I use jquery.event.drop / drag to create my drag / drop goals.

However, when I add / unfold the goal of changing the purpose of the drop, I need to recount. Here is how I wanted to do this:

function create_drop_targets() { $('li a') .bind('dropstart', function(event) { }) .bind('drop', function(event) { }) .bind('dropend', function(event) { }); } 

create_drop_targets () is called by drop / expand.

However, this does not work. I found the following in jquery.event.drop:

 var drop = $.event.special.drop = { setup: function(){ drop.$elements = drop.$elements.add( this ); drop.data[ drop.data.length ] = drop.locate( this ); }, locate: function( elem ){ // return { L:left, R:right, T:top, B:bottom, H:height, W:width } var $el = $(elem), pos = $el.offset(), h = $el.outerHeight(), w = $el.outerWidth(); return { elem: elem, L: pos.left, R: pos.left+w, T: pos.top, B: pos.top+h, W: w, H: h }; } 

Now I need to know how I can call the setup () method again so that it refills $ elements with new positions for droppables.

+4
source share
4 answers

Just the same problem. I wandered around jQuery source code and found this (in ui.droppable.js ):

 drag: function(draggable, event) { //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); ... 

So you just need to use

 $(".cocktails").draggable({ refreshPositions: true, }); 

It doesn't seem to be very well documented ... but that fixed my problem. Everything is a bit slower, I would recommend some usage-specific settings (turn it on before the changes happen, and turn it off as soon as the user moves his mouse and the changes happen).

+3
source

Maybe itโ€™s better to add live events introduced in jQuery 1.3?

$("li a").live("dropstart", function(){...});

+1
source

I ran into the same problem when I tried to combine scrolling with draggable rows in liteGrid, but I found a workaround. Your mileage may vary, but what I did was add logic to the drag event handler, which will check if the grid scrolls (which was when I needed to force updates of the positions to be reset), and if so, I set refreshPositions to true to draggable. This does not immediately update the positions, but it will force them to be updated the next time the drag handle is moved. Since refreshPositions slows down, I will turn it off again the next time the drag event handler starts. The end result is that refreshPositions is only allowed when the grid scrolls in the liteGrid and it turns off from time to time. Here is some code to illustrate:

 //This will be called every time the user moves the draggable helper. function onDrag(event, ui) { //We need to re-aquire the drag handle; we don't //hardcode it to a selector, so this event can be //used by multiple draggables. var dragHandle = $(event.target); //If refreshOptions *was* true, jQueryUI has already refreshed the droppables, //so we can now switch this option back off. if (dragHandle.draggable('option', 'refreshPositions')) { dragHandle.draggable('option', 'refreshPositions', false) } //Your other drag handling code if (/* logic to determine if your droppables need to be refreshed */) { dragHandle.draggable('option', 'refreshPositions', true); } } $("#mydraggable").draggable({ //Your options here, note that refreshPositions is off. drag: onDrag }); 

I hope this saves you from stuffing your head on the keyboard as many times as I did ...

0
source

I understand that the original question is now quite old, but one little trick that I came up with to update the position of dragged items without much overhead (AFAICT) is to disable and immediately re-enable them where necessary.

For example, I noticed that resizing my browser window would not update the position of my draggable table rows, so I did the following:

 $(window).resize(function () { $(".draggable").draggable("option", "disabled", true); $(".draggable").draggable("option", "disabled", false); }); 

I hope this helps someone out there!

0
source

All Articles