Drag and drop multiple selected draggables and revert invalid ones using Jquery UI

后端 未结 2 359
逝去的感伤
逝去的感伤 2020-12-06 03:30

Drawing a box with cursor (lasso) will select multiple .item in this JSFiddle example.

Selected .item\'s become draggable. Empty .slo

2条回答
  •  青春惊慌失措
    2020-12-06 04:03

    You can make use of document.elementFromPoint.

    Updated Fiddle

    For dropping/reverting the original draggable, we do the following once it is dropped in drop event:

    1. Check whether the droppable contains an .item or not in the dropevent. If the droppable doesn't already contain an .item, Go to step 2, else go to step3
    2. append() the element to corresponding .slot after resetting the positioning using css()
    3. Revert the element using animate() method to previous position which we cached using .data() on start event.

    For dropping/reverting the extra items being dragged:

    • We find the elements on the left and right visible area of each item being dragged (1px far from the element being dragged, Which is supposed to be the drop targets) usingdocument.elementFromPoint.

    • Since no actual drop event is triggered for these elements, we make use of the stop event of draggable to check whether either of the target's is a .slot

    • If either of them is a .slot, which means the item was dropped over a droppable, we proceed to step1 mentioned above, else we go to step3 (manually revert the item to it's original position)


    $(function() {
    
      var dragOption = {
          delay: 10,
          distance: 5,
          opacity: 0.45,
          revert: "invalid",
          revertDuration: 100,
          start: function(event, ui) {
            $(".ui-selected").each(function() {
              $(this).data("original", $(this).position());
            });
          },
          drag: function(event, ui) {
            var offset = ui.position;
            $(".ui-selected").not(this).each(function() {
              var current = $(this).offset(),
                targetLeft = document.elementFromPoint(current.left - 1, current.top),
                targetRight = document.elementFromPoint(current.left + $(this).width() + 1, current.top);
              $(this).css({
                position: "relative",
                left: offset.left,
                top: offset.top
              }).data("target", $.unique([targetLeft, targetRight]));
            });
          },
          stop: function(event, ui) {
            $(".ui-selected").not(this).each(function() {
              var $target = $($(this).data("target")).filter(function(i, elm) {
                return $(this).is(".slot") && !$(this).has(".item").length;
              });
              if ($target.length) {
                $target.append($(this).css({
                  top: 0,
                  left: 0
                }))
              } else {
                $(this).animate({
                  top: 0,
                  left: 0
                }, "slow");
              }
    
            });
            $(".ui-selected").data("original", null)
              .data("target", null)
              .removeClass("ui-selected");
          }
        },
        dropOption = {
          accept: '.item',
          activeClass: "green3",
          drop: function(event, ui) {
            if ($(this).is(".slot") && !$(this).has(".item").length) {
              $(this).append(ui.draggable.css({
                top: 0,
                left: 0
              }));
            } else {
              ui.draggable.animate({
                top: 0,
                left: 0
              }, 50);
            }
          }
        }
    
      $(".box").selectable({
        filter: ".item",
        start: function(event, ui) {
          $(".ui-draggable").draggable("destroy");
        },
        stop: function(event, ui) {
          $(".ui-selected").draggable(dragOption)
        }
      });
      $(".slot").droppable(dropOption);
    });
    .box {
      float: left;
      width: 150px;
      height: 180px;
      text-align: center;
      margin-left: 20px;
      border: 5px solid #999;
    }
    .slot {
      position: relative;
      width: 120px;
      height: 15px;
      margin-top: 2px;
      margin: 0 auto;
      border: 1px dotted;
    }
    .item {
      width: 110px;
      height: 14px;
      margin: 0 auto;
      z-index: 1;
      background-color: #CCC;
    }
    .ui-selecting {
      background: #FECA40;
    }
    .ui-selected {
      background-color: #F90;
    }
    .green3 {
      background-color: #D9FFE2;
    }
    
    
    
    

    box A

    box B


    Other references:

    • jQuery.unique()
    • is()
    • has()

    P.S: This will only work if the draggable is smaller than droppable (Which is true in this case)

提交回复
热议问题