使用Jquery UI拖放多个选定的可拖动对象并还原无效的可拖动对象 [英] Drag and drop multiple selected draggables and revert invalid ones using Jquery UI

查看:82
本文介绍了使用Jquery UI拖放多个选定的可拖动对象并还原无效的可拖动对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此 JSFiddle示例中,用光标(套索)绘制一个框会选择多个.item.

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

选定的.item变为可拖动.内部没有.item的空.slot是有效的可放置对象.

Selected .item's become draggable. Empty .slot without an .item inside is a valid droppable.

当您将多个可拖动对象拖放到多个可放置对象上时,如果相应的可放置对象无效,只有鼠标所在的.item会还原.

When you drop multiple draggables on multiple droppables, only the .item which mouse is on will revert if its corresponding droppable not valid.

如果每一个可拖动的恢复对象放置在无效可放置的对象上,该如何恢复?

How to make every draggable revert if it's dropped on invalid droppable?

JavaScript:

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

推荐答案

您可以使用

You can make use of document.elementFromPoint.

要删除/还原原始可拖动对象,将其拖放到 drop 事件:

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

  1. drop .item >事件. 如果该可放置对象尚未包含.item,请转到步骤2,否则转到步骤3
  2. 使用 append()元素对应的.slot http://api.jquery.com/css"rel =" nofollow> css()
  3. 使用 animate() 方法将元素还原到我们使用 .data() "nofollow"> start 事件.
  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:

  • 我们在每个项目的左侧和右侧可见区域中找到元素 被拖动(距被拖动的元素 1px,即 应该是放置目标),使用 document.elementFromPoint .

  • 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.

由于没有为这些元素触发实际的drop事件,因此我们使用

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

如果它们中的任何一个是.slot,则表示该项目被放到 droppable,我们继续执行上述步骤1,否则我们继续执行步骤3 (手动将项目还原到原始位置)

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>

其他参考文献:

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

P.S:仅当可拖动对象小于可放置对象(在这种情况下,这是正确的)

这篇关于使用Jquery UI拖放多个选定的可拖动对象并还原无效的可拖动对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆