JS / JQuery Drag'n'Drop, пересчитать цели падения - PullRequest
4 голосов
/ 07 апреля 2009

У меня есть следующая проблема, у меня есть большое дерево, у которого есть подузлы, которые можно сложить и развернуть по требованию (данные в узлах извлекаются с помощью AJAX). Однако я использую jquery.event.drop / drag для создания моих целей перетаскивания.

Однако, когда я складываю / раскладываю, цели падения меняют положение, и мне нужно пересчитать. Вот как я хотел это сделать:

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

create_drop_targets () вызывается при сворачивании / разворачивании.

Однако это не работает. Я нашел следующее в 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 };
        }

Теперь мне нужно знать, как я могу снова вызвать метод setup (), чтобы он снова заполнял элементы $ новыми позициями для droppables.

Ответы [ 4 ]

3 голосов
/ 25 апреля 2009

Просто была такая же проблема. Я бродил по исходному коду jQuery и нашел это (в 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);
  ...

Итак, вам просто нужно использовать

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

Кажется, не очень хорошо документировано ... но это решило мою проблему. Делает все немного медленнее, конечно, я бы посоветовал некоторую настройку, зависящую от использования (включите ее до того, как произойдут изменения, и отключите ее, как только пользователь переместил свою мышь и изменения произошли).

1 голос
/ 07 апреля 2009

Может быть, будет лучше добавить живые события, представленные в jQuery 1.3?

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

0 голосов
/ 24 ноября 2010

Я понимаю, что исходный вопрос сейчас довольно старый, но одна маленькая хитрость, которую я придумал, чтобы обновить положение перетаскиваемых элементов без особых накладных расходов (AFAICT), - это отключить и немедленно включить их снова, где это необходимо.

Например, я заметил, что изменение размера окна моего браузера не обновит положение строк моей перетаскиваемой таблицы, поэтому я сделал это:

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

Надеюсь, это кому-нибудь поможет!

0 голосов
/ 16 января 2010

Я столкнулся с той же проблемой, когда пытался объединить прокрутку с перетаскиваемыми строками в liteGrid, но нашел способ обхода. Ваш пробег может варьироваться, но я добавил логику в свой обработчик событий перетаскивания, который проверял бы, прокручивается ли сетка (именно тогда мне нужно было обновить обновляемые позиции), и если да, я установил refreshPositions в true на перетаскиваемом. Это не немедленно обновляет позиции, но заставит их обновляться при следующем перемещении ручки перетаскивания. Поскольку refreshPositions замедляет работу, я снова отключаю его при следующем запуске обработчика событий перетаскивания. Конечным результатом является то, что refreshPositions включается только тогда, когда сетка прокручивается в liteGrid, и она отключена в остальное время. Вот некоторый код для иллюстрации:

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

Надеюсь, это избавит вас от удара головой о клавиатуру столько раз, сколько я ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...