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

后端 未结 2 338
逝去的感伤
逝去的感伤 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;
    }
    <link href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" rel="stylesheet" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
    <div id="container">
      <div id="boxA" class="box">
        <h4>box A</h4>
    
        <div id="A1" class="slot">
          <div id="a1" class="item"></div>
        </div>
        <div id="A2" class="slot">
          <div id="a2" class="item"></div>
        </div>
        <div id="A3" class="slot">
          <div id="a3" class="item"></div>
        </div>
        <div id="A4" class="slot"></div>
        <div id="A5" class="slot"></div>
      </div>
      <div id="boxB" class="box">
        <h4>box B</h4>
    
        <div id="B1" class="slot"></div>
        <div id="B2" class="slot">
          <div id="b2" class="item"></div>
        </div>
        <div id="B3" class="slot"></div>
        <div id="B4" class="slot"></div>
        <div id="B5" class="slot">
          <div id="b5" class="item"></div>
        </div>
      </div>
    </div>


    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)

    0 讨论(0)
  • 2020-12-06 04:05

    If you mean, you want to drag and drop something and you want to revert if the data is dropped in the wrong area, then you can you use following code as a sample to achive your target

    $(function() {
      $(".connectedSortable").sortable({
        connectWith: ".connectedSortable",
        placeholder: "ui-state-highlight",
        //containment: "parent",
        revert: true
      });
      $("#sortable2").sortable({
        connectWith: ".connectedSortable",
        receive: function(event, ui) {
          if (ui.item.attr('cust-attr') != 'm') {
            console.log('wrong element');
            $("#" + ui.sender.attr('id')).sortable('cancel');
          }
        }
      });
      $("#sortable2x").sortable({
        connectWith: ".connectedSortable",
        receive: function(event, ui) {
          if (ui.item.attr('cust-attr') == 'm') {
            console.log('wrong element');
            $("#" + ui.sender.attr('id')).sortable('cancel');
          }
        }
      });
    });
    #sortable1,
    #sortable1x,
    #sortable2,
    #sortable2x {
      list-style-type: none;
      margin: 0;
      padding: 0 0 2.5em;
      float: left;
      margin-right: 10px;
    }
    #sortable1 li,
    #sortable1x li,
    #sortable2 li,
    #sortable2x li {
      box-shadow: 2px 2px 0 #6D6D6D;
      cursor: pointer;
      margin: 0 5px 5px 5px;
      padding: 5px;
      font-size: 1.2em;
      width: 150px;
    }
    #sortable2 .ui-selecting,
    #sortable2x .ui-selecting {
      background: #FECA40;
    }
    #sortable2 .ui-selected,
    #sortable2x .ui-selected {
      background: #F39814;
      color: white;
    }
    #sortable1x,
    #sortable2x {
      list-style-type: none;
      margin: 0;
      width: 60%;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="http://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
    <link href="http://code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css" rel="stylesheet">
    <div style="width:600px;height:360px;">
      <div style="float:left;">
        Set 1 : &nbsp;
      </div>
      <div>
        <ul id="sortable1" class="connectedSortable" style="border: 1px solid #000000;width:220px;height:300px;padding:4px;">
          <li class="ui-state-default" cust-attr="m">Item 1 Set 1 X</li>
          <li class="ui-state-default" cust-attr="m">Item 2 Set 1 X</li>
          <li class="ui-state-default">Item 3 Set 1 X</li>
          <li class="ui-state-default">Item 4 Set 1 X</li>
          <li class="ui-state-default">Item 5 Set 1 X</li>
        </ul>
        <ul id="sortable1x" class="connectedSortable" style="border: 1px solid #000000;width:220px;height:300px;padding:4px;">
          <li class="ui-state-default" cust-attr="m">Item 1 Set 1 Y</li>
          <li class="ui-state-default" cust-attr="m">Item 2 Set 1 Y</li>
          <li class="ui-state-default">Item 3 Set 1 Y</li>
          <li class="ui-state-default">Item 4 Set 1 Y</li>
          <li class="ui-state-default">Item 5 Set 1 Y</li>
        </ul>
      </div>
    </div>
    <div style="width:600px;height:360px;">
      <div style="float:left;">
        Set 2 : &nbsp;
      </div>
      <div>
        <ul id="sortable2" class="connectedSortable connectedSortablex" style="border: 1px solid #000000;width:220px;height:300px;padding:4px;">
    
        </ul>
        <ul id="sortable2x" class="connectedSortable connectedSortablex" style="border: 1px solid #000000;width:220px;height:300px;padding:4px;">
    
        </ul>
      </div>
    </div>

    Click the below link to see demo http://jsfiddle.net/g90rau5p/3/

    If you want multiple items drop, use multisort jquery library which can be used along with jqueryUI. For more details about it go to https://github.com/shvetsgroup/jquery.multisortable

    0 讨论(0)
提交回复
热议问题