使用Jquery UI拖放多个选定的可拖动并恢复无效的拖动

时间:2014-11-08 23:20:01

标签: jquery jquery-ui jquery-ui-draggable jquery-ui-droppable jquery-ui-selectable

使用光标(套索)绘制一个框将在此JSFiddle example中选择多个.item

选定的.item成为可拖动的。 .slot的空.item是有效的可放置。

当您在多个droppable上放置多个draggable时,只有当其对应的droppable无效时,只有.item哪个鼠标处于打开状态才会恢复。

如果无效可放置,那么如何每个可拖动还原?

使用Javascript:

$(function () {
  // we are going to store the selected objects in here
  var selected = $([]),
    total = [],
    offset = {
        top: 0,
        left: 0
    };

  $(document).selectable({
    filter: ".item",
    start: function (event, ui) { //remove draggable from selection, otherwise previous selection will still be draggable. 
        $(total).draggable("destroy");
    },
    selected: function (event, ui) { // push selected into total[].
        total.push(ui.selected)
    },
    unselected: function (event, ui) { //console.log('unselect ui: ',ui)
        u = ui.unselected
        //remove unselected from selection[].
        total = jQuery.grep(total, function (n) {
            return n !== u
        });
        //console.log('total array (unselected): ',total)
    },
    stop: function (vent, ui) {
        //remove duplicated element from total[].
        jQuery.unique(total)
        $(total).each(function () {
            $(this).draggable(dragOption)
        })
        //$(total).draggable(dragOption);
        //var widget = $( ".selector" ).draggable( "widget" );
        //console.log('widget: ',widget)
        console.log('break line---------------------------- ')
    }

  });

  //save drag option as an Obj.
  dragOption = {
    opacity: 0.45,
    delay: 300,
    connectToSortable: ".slot"
    //,helper: "clone"
    ,
    distance: 5,
    snap: ".slot",
    snapMode: "inner",
    revert: "invalid",
    start: function (event, ui) {
        console.log('draggable start ui: ', ui)
        selected = $(total).each(function () {
            var el = $(this);
            el.data("offset", el.offset())
        });
        offset = $(this).offset(); //get coordinates relative to document
    },
    drag: function (event, ui) { //console.log(offset.top)
        var dt = ui.position.top - offset.top,
            dl = ui.position.left - offset.left;
        selected.not(this).each(function () {
            // create the variable for we don't need to keep calling $("this")
            // el = current element we are on
            // off = what position was this element at when it was selected, before drag
            var el = $(this),
                off = el.data("offset");
            el.css({
                top: off.top + dt,
                left: off.left + dl
            });
        });
    },
    stop: function (event, ui) {
        console.log('drag stop ui : ', ui)
    }
  };

  //save drop option as an Obj.
  dropOption = {
    accept: '.item',
    drop: function (event, ui) {
        console.log('drop event : ', event);
        console.log('drop ui : ', ui)
    },
    activate: function (event, ui) { //console.log('this : ',this,'\n ui : ',ui)
    },
    out: function (event, ui) { //console.log('out',$(this))
    },
    deactivate: function (event, ui) { //console.log('deactivate')
    },
    tolerance: "intersect",
    instance: function (event, ui) { //console.log('instance ui : ',ui)
    },
    over: function (event, ui) { //console.log('this item : ',ui.draggable[0],'on this slot: ',this)
    },
    activeClass: "green3"

}
  // make empty slot droppable
  $(".slot:not(:has(>div))").droppable(dropOption)
}) <!--doc ready-->

HTML:

<body>
  <div id="container">
    <div id="header"></div>
    <div class="box" id="boxA">
      <h4>box A</h4>
      <div class="slot" id="A1">
        <div class="item" id="a1"></div>
      </div>
      <div class="slot" id="A2">
        <div class="item" id="a2"></div>
      </div>
      <div class="slot" id="A3">
        <div class="item" id="a3"></div>
      </div>
      <div class="slot" id="A4"></div>
      <div class="slot" id="A5"></div>
    </div>
    <div class ="box" id="boxB">
      <h4>box B</h4>
      <div class="slot" id="B1"></div>
      <div class="slot" id="B2">
        <div class="item" id="b2"></div>
      </div>
      <div class="slot" id="B3"></div>
      <div class="slot" id="B4"></div>
      <div class="slot" id="B5">
        <div class="item" id="b5"></div>
      </div>
    </div>
  </div> 
</body>

CSS:

document {
    background-color: #FFF;
}

.box {
    height: 180px;
    float: left;
    border-top-width: 5px;
    border-right-width: 5px;
    border-bottom-width: 5px;
    border-left-width: 5px;
    border-top-style: solid;
    border-right-style: solid;
    border-bottom-style: solid;
    border-left-style: solid;
    border-top-color: #999;
    border-right-color: #999;
    border-bottom-color: #999;
    border-left-color: #999;
    width: 150px;
    text-align: center;
    margin-left: 100px;
}
.item {
    position: absolute;
    font-size: 12px;
    height: 14px;
    background-color: #CCC;
    width: 110px;
    text-decoration: none;
    font-family: Arial, Helvetica, sans-serif;
    color: #999;
    margin-left: 6px;
    text-align: center;
}

#header, #footer {
    float: left;
    height: 200px;
    width: 100%;
}
.slot{
    border-top-width: 1px;
    border-right-width: 1px;
    border-bottom-width: 1px;
    border-left-width: 1px;
    border-top-style: dotted;
    border-right-style: dotted;
    border-bottom-style: dotted;
    border-left-style: dotted;
    height: 15px;
    width: 120px;
    margin-top: 2px;
    text-align: center;
    vertical-align: middle;
    line-height: 90px;
    margin-right: auto;
    margin-left: auto;
    }
.ui-selecting {
    background: #FECA40;
  }
.ui-selected {
    background-color: #F90;
  }
.green3 {
    background-color: #D9FFE2;
}

2 个答案:

答案 0 :(得分:4)

您可以使用document.elementFromPoint

Updated Fiddle

对于删除/还原原始可拖动的内容,我们会在drop事件中删除后执行以下操作:

  1. 检查droppable是否在drop事件中包含.item。 如果droppable尚未包含.item,请转到步骤2,否则转到步骤3
  2. 使用append()重置定位后
  3. css()对应.slot的元素
  4. 使用animate()方法将元素恢复为我们在.data()事件中使用start缓存的上一个位置。
  5. 用于删除/恢复被拖动的额外项目:

    • 我们在每个项目的左右可见区域找到元素 被拖动( 1px远离被拖动的元素,这是 应该使用document.elementFromPoint

    • 作为放置目标
    • 由于没有为这些元素触发实际的drop事件,我们会使用draggable的stop事件来检查 target 中是否有一个是.slot

    • 如果其中任何一个是.slot,则意味着该项目已被删除 droppable,我们继续上面提到的step1,否则我们转到step3 (手动将项目还原为原始位置


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


    其他参考资料:


    P.S:只有当draggable小于droppable时才会起作用(在这种情况下是

答案 1 :(得分:0)

如果您的意思是,您想要拖放某些内容并且想要在数据被丢弃的情况下还原,那么您可以使用以下代码作为样本来实现目标

&#13;
&#13;
$(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');
      }
    }
  });
});
&#13;
#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%;
}
&#13;
<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>
&#13;
&#13;
&#13;

点击以下链接查看演示http://jsfiddle.net/g90rau5p/3/

如果要删除多个项目,请使用可与jqueryUI一起使用的多端口jquery库。有关它的更多详细信息,请转到https://github.com/shvetsgroup/jquery.multisortable