Пользовательский интерфейс jQuery добавляет отбрасываемый прослушиватель событий при наведении

Я хочу добавить отбрасываемый прослушиватель событий при перетаскивании одного объекта и наведении на отбрасываемый объект.

Вот мой код:

$('.will-be-drag').draggable({
    helper: 'clone',
    drag: function (event, ui) {
        $('.will-be-drop').hover(function () {
            $(this).droppable({
                drop: function (event, ui) {
                    let item = ui.draggable;
                    console.log(item[0])
                    item.detach().appendTo($(this));
                }
            });
        }, function () {
            $(this).droppable('disable');
        });

    }
});

И мой HTML такой:

<div class="will-be-drag"></div>
<div class="will-be-drag"></div>
<div class="will-be-drag"></div>

<?php
for($i = 0; $i <= 3000; $i++){
?>
    <div class="will-be-drop"></div>
<?php
}
?>

Я делаю это из-за проблем с производительностью. У меня есть сбрасываемый объект размером 3k, и он зависает при перетаскивании. Он должен добавить droppable прослушиватель событий, перетаскивая только $('.will-be-drag') объект и зависая $('.will-be-drop').

С этим кодом он добавляет только при наведении, а не при перетаскивании.

Как мне это сделать?

Я хочу, чтобы javascript дышал, он опаздывает при установке 3k droppable объектов. Всего 30-40 перетаскиваемых элементов. Это стол.


person sundowatch    schedule 19.02.2020    source источник
comment
Нет, я хочу добавить выпадающие только парящие элементы   -  person sundowatch    schedule 19.02.2020
comment
можно еще html код поставить?   -  person Arvind Maurya    schedule 19.02.2020
comment
Хорошо, позвольте мне поставить PHP-код   -  person sundowatch    schedule 19.02.2020
comment
Это не лучший способ заставить функцию работать. Я бы назначил droppable при инициализации страницы, а затем вы можете настроить параметр accept или оставить их отключенными до наведения.   -  person Twisty    schedule 19.02.2020
comment
Я думаю, что jQuery ui добавляет все прослушиватели событий, и он пытается обработать все эти прослушиватели событий.   -  person sundowatch    schedule 20.02.2020
comment
@sundowatch да, к каждому объекту будет добавлен список событий. Если вы используете disable, он отключен до тех пор, пока вы не enabled. Я все еще думаю, что вы должны инициализировать их все, отключить их, а затем включить видимые.   -  person Twisty    schedule 20.02.2020


Ответы (1)


Вот пример наведения:

$(function() {
  $("#draggable").draggable();
  $("#droppable").droppable({
    drop: function(event, ui) {
      $(this)
        .find("p")
        .html("Dropped!");
    }
  }).hover(function(e) {
    // IN
    $(this)
      .addClass("ui-state-highlight");
  }, function(e) {
    // OUT
    $(this)
      .removeClass("ui-state-highlight");
  });
});
#draggable {
  width: 100px;
  height: 100px;
  padding: 0.5em;
  float: left;
  margin: 10px 10px 10px 0;
}

#droppable {
  width: 150px;
  height: 150px;
  padding: 0.5em;
  float: left;
  margin: 10px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="draggable" class="ui-widget-content">
  <p>Drag me to my target</p>
</div>

<div id="droppable" class="ui-widget-header">
  <p>Drop here</p>
</div>

Вы можете видеть, что когда вы наводите курсор мыши на выпадающий элемент, он выделяется. Когда перетаскиваешь - нет. Я подозреваю, что событие hover не может всплывать над постоянным событием mousedown.

Предложил бы это:

$(function() {
  function makeDrops(n) {
    var t = $(".ui-widget").eq(1);
    for (var i = 1; i <= n; i++) {
      $("<div>", {
        id: "drop-" + i,
        class: "will-be-drop ui-widget-content"
      }).appendTo(t);
    }
  }

  function inViewport(element, detectPartial) {
    element = $(element);
    detectPartial = (!!detectPartial); // if null or undefined, default to false

    var viewport = $(window),
      vpWidth = viewport.width(),
      vpHeight = viewport.height(),
      vpTop = viewport.scrollTop(),
      vpBottom = vpTop + vpHeight,
      vpLeft = viewport.scrollLeft(),
      vpRight = vpLeft + vpWidth,

      elementOffset = element.offset(),
      elementTopArea = elementOffset.top + ((detectPartial) ? element.height() : 0),
      elementBottomArea = elementOffset.top + ((detectPartial) ? 0 : element.height()),
      elementLeftArea = elementOffset.left + ((detectPartial) ? element.width() : 0),
      elementRightArea = elementOffset.left + ((detectPartial) ? 0 : element.width());

    return ((elementBottomArea <= vpBottom) && (elementTopArea >= vpTop)) && ((elementRightArea <= vpRight) && (elementLeftArea >= vpLeft));
  }

  function markVisible(c) {
    c.each(function(i, el) {
      if (inViewport(el, true)) {
        $(el).addClass("visible");
      }
    });
  }

  makeDrops(3000);

  $(".will-be-drop").droppable({
    drop: function(event, ui) {
      let item = ui.draggable;
      console.log("Drag Item " + item.text().trim() + " dropped to " + $(this).attr("id"));
      item.detach().appendTo($(this));
    },
    over: function() {
      $(this).addClass("ui-state-highlight");
    },
    out: function() {
      $(this).removeClass("ui-state-highlight");
    }
  }).droppable("disable");

  $('.will-be-drag').draggable({
    helper: 'clone',
    start: function(e, ui) {
      markVisible($(".will-be-drop"));
      $(".will-be-drop.visible").droppable("enable");
    },
    drag: function(e, ui) {
      $(".will-be-drop.visible").droppable("disable").removeClass("visible");
      markVisible($(".will-be-drop"));
      $(".will-be-drop.visible").droppable("enable");
    },
    stop: function(e, ui) {
      $(".will-be-drop").droppable("disable");
      $(".will-be-drop.ui-state-highlight").removeClass("ui-state-highlight");
    }
  });
});
.will-be-drag {
  width: 50px;
  height: 50px;
  padding: 0.25em;
  float: left;
  margin: 10px 10px 10px 0;
}

.will-be-drop {
  width: 100px;
  height: 100px;
  padding: 0.25em;
  float: left;
  margin: 10px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="ui-widget">
  <div class="will-be-drag ui-widget-content">A</div>
  <div class="will-be-drag ui-widget-content">B</div>
  <div class="will-be-drag ui-widget-content">C</div>
</div>
<div class="ui-widget">
</div>

Вы также можете инициализировать некоторые как dropppable с :visible или другим условием, чтобы уменьшить нагрузку на память. Просто не забудьте также уничтожить их, иначе вы просто усугубите проблему с памятью, когда пользователь перемещается по странице во время перетаскивания.

person Twisty    schedule 19.02.2020
comment
Спасибо и извините, но по производительности разницы нет, реально зависает - person sundowatch; 19.02.2020
comment
@sundowatch нет, я не тестировал его с 3000 элементами. Я обновил свой ответ, и да, он немного медленнее, но скрипт не остановился. Если на странице и в других скриптах больше элементов, ресурс памяти может упасть в некоторых браузерах до состояния, когда скрипт больше не отвечает. Если это так, вы можете подумать об инициализации и уничтожении droppable на основе значения прокрутки и включить группу из них. Возможно, используйте селектор :visible. - person Twisty; 20.02.2020
comment
Да, это было бы решением, но если мне удастся получить ячейку (будет-выпадать) при перетаскивании, все будет в порядке. - person sundowatch; 20.02.2020
comment
@sundowatch из-за действия «нажми и удерживай», созданного перетаскиванием, некоторые события, такие как наведение, не всегда запускаются должным образом. Таким образом, положение мыши или положение прокрутки лучше учитывать во время перетаскивания. - person Twisty; 20.02.2020
comment
@sundowatch обновлен расширенным примером, касающимся наведения. - person Twisty; 20.02.2020
comment
@sundowatch еще одно гораздо более крупное обновление, которое включает только выпадающие элементы в окне просмотра. - person Twisty; 20.02.2020