views:

743

answers:

3

I have the following issue, I have a large tree which has subnodes which can be folded and unfolded on demand (the data within nodes gets fetched with AJAX). However, I use jquery.event.drop/drag to create my drag/drop targets.

However, when I fold/unfold the drop targets change position and I need to recalculate. This is how I wanted to do that:

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

create_drop_targets() is called upon fold/unfold.

However, this doesn't work. I have located the following within 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 it repopulates $elements with the new positions for the droppables.

+1  A: 

Maybe it will be better to add live events introduced in jQuery 1.3?

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

Thinker
I have tried this with live events on version 1.3.2, no solution.
ikanobori
+1  A: 

Just had the same issue. I wandered around within the source-code of jQuery 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'd just have to use

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

Seems not to be documented very much... but it fixed my problem. Makes everything a bit slower of course, I would advise some usage-dependent tweaking (enable it before the changes occur, and disable it once the user has moved his mouse and the changes have occured).

Marcel J.
I'm going to try this tomorrow, I'll keep you posted!
ikanobori
A: 

I ran into the same issue when I tried to combine scrolling with draggable rows in liteGrid, but I found a work-around. Your mileage may vary, but what I did was add logic to my drag event handler that would check to see if the grid was being scrolled (which is when I needed to force the droppable positions to be refreshed), and if so, I set refreshPositions to true on the draggable. This doesn't immediately refresh the positions, but it will cause them to refresh the next time the drag handle moves. Since refreshPositions slows things down, I then re-disable it the next time my drag event handler fires. The net result is that refreshPositions is enabled only when the grid is scrolling in liteGrid, and its disabled the rest of the time. Here's 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 that saves you from ramming your head into the keyboard as many times as I did...

DanMan
I should note that I tried just enabling refreshPositions, but the performance was unacceptable. With this solution, I still have slow performance when dragging rows is causing the grid to scroll, but the rest of the time it performs great (because refreshPositions is disabled).
DanMan