使用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:
- 在
drop
中检查可放置对象是否包含.item
>事件. 如果该可放置对象尚未包含.item
,请转到步骤2,否则转到步骤3
使用 append()元素对应的 - 使用
animate()
方法将元素还原到我们使用.data()
"nofollow">start
事件.
.slot
http://api.jquery.com/css"rel =" nofollow> css()
- Check whether the droppable contains an
.item
or not in thedrop
event. If the droppable doesn't already contain an.item
, Go to step 2, else go to step3 - append() the element to corresponding
.slot
after resetting the positioning usingcss()
- Revert the element using
animate()
method to previous position which we cached using.data()
onstart
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) using
document.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
如果它们中的任何一个是.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:仅当可拖动对象小于可放置对象(在这种情况下,这是正确的)