Drag and drop multiple selected draggable objects and return invalid using jQuery UI

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

Selected .item become draggable. An empty .slot without .item inside is a valid droppable.

When you delete multiple draggable objects in multiple drop-down folders, only the .item tag on which the mouse is installed will return if its corresponding droppable is invalid.

How to make each draggable if it falls on an invalid droppable?

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; } 
+5
source share
2 answers

You can use document.elementFromPoint .

Updated Fiddle

To drop / return the original dragged file, we do the following as soon as it falls into the drop event:

  • Check if droppable .item .item or not in drop event. If droppable already does not contain .item , go to step 2 and go to step 3
  • add () element to corresponding .slot after resetting positioning with css()
  • Cancel the element using the animate() method to the previous position, which we cached with .data() in the start event.

Dropping / returning additional items being dragged:

  • We find elements in the left and right visible areas of each element (1px away from the element that is being dragged, which is assumed to be a drop target) using document.elementFromPoint .

  • Since the actual drop event does not .slot for these elements, we use the drag and drop stop event to check if any of the .slot targets

  • If any of them is .slot , which means that the item has been dropped on top of droppable, go to step 1 above, otherwise we go to step 3 (manually reset the item to its 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 links:


PS: This will only work if draggable is less than droppable (which is true in this case)

+4
source

If you mean you want to drag something and you want to return if the data is deleted in the wrong area, then you can use the following code as a template to achieve your goal

 $(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 link below to see a demo http://jsfiddle.net/g90rau5p/3/

If you want to remove multiple elements, use the jquery multitasking library, which can be used with jqueryUI. For more information about this, go to https://github.com/shvetsgroup/jquery.multisortable

0
source

Source: https://habr.com/ru/post/1206505/


All Articles