Перетаскивание jQuery с использованием живых событий

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

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

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


person devongovett    schedule 26.11.2009    source источник
comment
Что делает if (!jQuery(this).data("init")) { jQuery(this).data("init", true);}?   -  person    schedule 28.01.2011


Ответы (10)


Решение Wojtek отлично сработало для меня. Я немного изменил его, чтобы расширить 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})
person stldoug    schedule 28.07.2010
comment
Это сломало мой js полностью. Вам нужно разместить это где-то, в частности, для расширения функциональности JQuery? - person Andrew; 03.02.2011
comment
Вам нужно объявить его после загрузки jQuery и до того, как вы будете использовать его в своем коде. Какую ошибку вы получаете? - person stldoug; 10.04.2011
comment
Вы забыли вернуть элемент для цепочки - person Randomblue; 04.09.2011
comment
Кстати . это неверно, вы забыли удалить обработчик наведения мыши, когда устанавливаете свойство draggable. Я соответствующим образом исправлю fn.liveDraggable. - person Morg.; 13.04.2012
comment
Также только что нашел это, пытаясь решить аналогичную проблему. Отличное решение! - person Phil; 10.05.2012
comment
Лучше, чем хранить данные в элементах, почему бы не положиться на наличие CSS-класса .ui-draggable? мне кажется это легче - person mexique1; 21.10.2012
comment
В настоящее время вы должны использовать this.on('mouseover', selector, ...) вместо this.live('mouseover', ...) - person Dehalion; 23.10.2013

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

$('.gadgets-column').live('mouseover',function(){
    $(this).draggable();
});
person Jasim Muhammed    schedule 11.10.2010
comment
это простое решение, но перетаскивание выполняется для всех элементов DOM с классом столбцов гаджетов каждый раз, когда вы наводите курсор на один из них... - person Michal B.; 24.02.2012
comment
@МихалБ. Нет, это не то, как работает jQuery, $(this) относится к элементу, на который наводится указатель мыши, и это может быть даже намного легче, чем установка draggable() ранее (т.е. логика перетаскивания не будет активна до тех пор, пока вы не наведете указатель мыши). - person Morg.; 10.04.2012
comment
@Morg: Я согласен со всем, что вы сказали, вы просто не поняли, что я имел в виду. Каждый раз, когда вы наводите курсор на элемент класса gadgets-column, код будет выполняться. Код $(this).draggable();, и это не то, что вы хотели бы выполнять каждый раз, когда наводите курсор. - person Michal B.; 11.04.2012
comment
Невероятно просто, это самое простое решение. Поздравления - person Yises; 24.04.2012

Вы можете сделать функцию оболочки следующим образом:

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

person wojtekk    schedule 13.04.2010

Код 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 "mousemove", но, к сожалению, это не работает с .live.

person john    schedule 17.05.2011
comment
Да, однозначно чище. Что вы думаете о перемещении проверки ui-draggable внутрь функции плагина... что-то вроде if(!this.hasClass('ui-draggable')){...}? - person stldoug; 25.05.2011
comment
не могли бы вы использовать вместо этого делегата. там можно указать дополнительный селектор. - person Luke; 06.03.2013

Объединяем лучшие ответы от @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 уменьшит область действия селектора, повысив производительность.

person Yarin    schedule 18.07.2013

Пример:

Турецкий:

<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() имеет лучшую производительность, чем другие

person Community    schedule 08.10.2012

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

JSFiddle

person yokesh ganesan    schedule 04.12.2013

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

person Danny C    schedule 15.08.2012

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

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

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

person Micah    schedule 29.10.2014

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

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