jQuery Drag and Drop с использованием живых событий

У меня есть приложение с длинным списком, который часто меняется, и мне нужно, чтобы элементы этого списка были перетаскиваемыми.

Я использовал плагин перетаскиваемого пользовательского интерфейса jQuery, но он медленно добавляется к 400+ элементам списка и должен добавляться каждый раз, когда добавляются новые элементы списка.

Кто-нибудь знает о плагине, похожем на перетаскиваемый плагин jQuery UI, который использует jQuery 1.3 .live() События? Это решило бы обе проблемы.

10 ответов

Решение

Решение Войтека отлично сработало для меня. Я немного изменил его, чтобы расширить JQuery...

(function ($) {
   $.fn.liveDraggable = function (opts) {
      this.live("mouseover", function() {
         if (!$(this).data("init")) {
            $(this).data("init", true).draggable(opts);
         }
      });
      return this;
   };
}(jQuery));

Теперь вместо того, чтобы называть это как:

$(selector).draggable({opts});

... просто используйте:

$(selector).liveDraggable({opts})

Это пример кода, который отлично работает для меня

$('.gadgets-column').live('mouseover',function(){
    $(this).draggable();
});

Вы можете сделать функцию-обёртку такой:

function liveDraggable(selector, options){
  jQuery(selector).live("mouseover",function(){
    if (!jQuery(this).data("init")) {
      jQuery(this).data("init", true);
      jQuery(this).draggable(options);
    }
  });
}

(Я использую прототип с jQuery - поэтому я поместил jQuery() вместо $())

И теперь вместо $(selector).draggable({opts}) используйте liveDraggable(selector, {opts})

Код Stldoug работал для меня, но нет необходимости постоянно проверять элемент.data("init") для каждого события наведения мыши. Кроме того, лучше использовать "mousemove", так как "mouseover" не всегда срабатывает, если ваша мышь уже находится над элементом, когда включается функция.live.

(function ($) {
    $.fn.liveDraggable = function (opts) {
        this.live("mousemove", function() {
            $(this).draggable(opts);
        });
    };
}(jQuery));

Вот как вы используете это:

$('.thing:not(.ui-draggable)').liveDraggable();

Хитрость заключается в том, чтобы добавить ":not(.ui-draggable)" в ваш селектор. Поскольку jQuery автоматически добавляет класс "ui-draggable" к вашему элементу, когда он становится перетаскиваемым, функция.live больше не будет нацеливаться на него. Другими словами, он срабатывает только один раз, в отличие от другого решения, которое срабатывает снова и снова, когда вы перемещаете вещи.

В идеале, вы могли бы просто.unbind "мышиный ход", но это не работает с.live, к сожалению.

Объединяя лучшие ответы от @john и @jasimmk:

С помощью .live :

$('li:not(.ui-draggable)').live('mouseover',function(){
    $(this).draggable(); // Only called once per li
});

.live не рекомендуется, но лучше использовать .on :

$('ul').on('mouseover', 'li:not(.ui-draggable)', function(){
    $(this).draggable();  // Only called once per li
});

Как объяснил @john, .ui-draggable автоматически добавляется в перетаскиваемые методы, поэтому, исключая этот класс с помощью селектора, вы гарантируете, что draggable() будет вызываться только один раз для каждого элемента. И используя .on уменьшит область действия селектора, улучшив производительность.

Пример:

Турецкий:

<div id="diyalogKutusu">
    <div id="diyalog-baslik">..baslik..</div>
    <div id="icerik">..icerik..</div>
</div>

$(document).on("mouseover", "#diyalogKutusu", function() {
    $(this).draggable({ handle: '#diyalog-baslik' });
});

Английский:

<div id="dialogBox">
    <div id="dialogBox-title">..title..</div>
    <div id="content">..content..</div>
</div>

$(document).on("mouseover", "#dialogBox", function() {
    $(this).draggable({ handle: '#dialogBox-title' });
});

Примечание: вы можете использовать on() вместо live() или же delegate, on() имеет хорошие показатели, чем другие

$("html divs to drag").appendTo("#layoutDiv").draggable(options);

JSFiddle

Обновленная версия, которая не использует live, поскольку она устарела:

function liveDraggable(selector, options) {
    $(document).on('mouseover', selector, function () {
        if (!$(this).data("init")) {
            $(this).data("init", true);
            $(this).draggable(options);
        }
    });
}

Другой вариант - смешать обработчик наведения мыши со съемным классом, например так:

$('.outer-container').on('mouseover', '.my-draggable.drag-unbound', function(e) {
  $(this).draggable().removeClass('drag-unbound');
});

Это довольно просто и решает некоторые проблемы, с которыми сталкиваются другие ответы при повторном связывании при наведении курсора мыши.

Старый вопрос Но у threedubmedia есть плагин drag-and-drop с поддержкой в ​​реальном времени (начиная с версии 1.7, которая называется просто "on"). http://threedubmedia.com/code/event/drop Я не слишком много использовал его, поэтому я не могу объяснить его производительность и т. д., но выглядит разумно.

Другие вопросы по тегам