Home » Jquery » javascript – jQuery UI add droppable event listener while hovering

javascript – jQuery UI add droppable event listener while hovering

Posted by: admin February 22, 2020 Leave a comment

Questions:

I want to add droppable event listener while dragging one object and hovering droppable object.

Here is my code:

$('.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');
        });

    }
});

And my HTML is like that:

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

I’m doing that because of performance issues. I have 3k droppable object and it’s freezing while dragging. It must add droppable eventlistener with only dragging $('.will-be-drag') object and hovering $('.will-be-drop').

With this code It only adds while hover not while dragging.

How can I do it?

I want javascript to breathe, it’s being late when setting 3k droppable objects. There are only 30-40 draggable element. It’s a table.

How to&Answer:

Here is a Hover example:

$(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>

You can see that when you mouse over the droppable, it highlights. When you drag, it doesn’t. I suspect the hover event cannot bubble up over the persistent mousedown event.

Would suggest this:

$(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>

You can also initialize some as droppable with :visible or some other condition to reduce memory overhead. Just remember to also destroy them otherwise you will just pile on the memory issue as the user moves through the page while dragging.