简体   繁体   English

使用Jquery UI拖放多个选定的可拖动对象并还原无效的可拖动对象

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

Drawing a box with cursor (lasso) will select multiple .item in this JSFiddle example . 在此JSFiddle示例中,使用光标(套索)绘制一个框将选择多个.item

Selected .item 's become draggable. 选定的.item变为可拖动。 Empty .slot without an .item inside is a valid droppable. .slot没有.item.slot是有效的可放置对象。

When you drop multiple draggables on multiple droppables, only the .item which mouse is on will revert if its corresponding droppable not valid. 当您将多个可拖动对象拖放到多个可.item对象上时,如果其相应的可.item ,则仅鼠标所在的.item会还原。

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: 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: 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 . 您可以使用document.elementFromPoint

Updated Fiddle 更新的小提琴

For dropping/reverting the original draggable, we do the following once it is dropped in drop event: 对于拖放/还原原始可拖动对象,一旦在drop事件中将其拖放 ,我们将执行以下操作:

  1. Check whether the droppable contains an .item or not in the drop event. 检查drop事件中是否可.item包含.item If the droppable doesn't already contain an .item , Go to step 2, else go to step3 如果droppable尚不包含.item ,请转到步骤2,否则请转到步骤3
  2. append() the element to corresponding .slot after resetting the positioning using css() 追加()的元素对应的.slot使用复位定位之后css()
  3. Revert the element using animate() method to previous position which we cached using .data() on start event. 使用animate()方法将元素还原到我们在start事件时使用.data()缓存的先前位置。

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 ) using document.elementFromPoint . 我们使用document.elementFromPoint 要拖动的每个项目的左右可见区域中找到元素( 距离要拖动的元素1px远,这应该是放置目标 )。

  • 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 由于这些元素没有触发任何实际的drop事件,因此我们利用draggable的stop事件来检查目标的任何一个是否为.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 ) 如果它们中的任何一个.slot ,则意味着该项目已放置在可放置对象上,请继续执行上述步骤1,否则转到步骤3( 手动将项目还原到其原始位置


 $(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: 其他参考:


PS: This will only work if the draggable is smaller than droppable ( Which is true in this case ) PS:这仅在可拖动对象小于可放置对象时才有效( 在这种情况下为true

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/ 单击下面的链接查看演示http://jsfiddle.net/g90rau5p/3/

If you want multiple items drop, use multisort jquery library which can be used along with jqueryUI. 如果要删除多个项目,请使用可与jqueryUI一起使用的multisort jquery库。 For more details about it go to https://github.com/shvetsgroup/jquery.multisortable 有关它的更多详细信息,请访问https://github.com/shvetsgroup/jquery.multisortable

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM