- 首页
- 其他开发
- 拖放多个选定的可拖动对象并使用 Jquery UI 还原无效的对象
拖放多个选定的可拖动对象并使用 Jquery UI 还原无效的对象
[英] Drag and drop multiple selected draggables and revert invalid ones using Jquery UI
本文介绍了拖放多个选定的可拖动对象并使用 Jquery UI 还原无效的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
在这个JSFiddle中绘制一个带有光标的框(套索)将选择多个.item
例子.
选定的 .item
变为可拖动的.里面没有 .item
的空 .slot
是一个有效的 droppable.
当你在多个 droppables 上放置多个 draggables 时,如果对应的 droppable 无效,只有鼠标所在的 .item
会恢复.
如果无效可拖放,如何使所有可拖拽恢复?
Javascript:
$(function () {//我们将在这里存储选定的对象选择的变量 = $([]),总计 = [],偏移 = {顶部:0,左:0};$(document).selectable({过滤器:.item",start: function (event, ui) {//从选择中移除可拖动,否则之前的选择仍然是可拖动的.$(total).draggable("destroy");},selected: function (event, ui) {//将所选推入 total[].total.push(ui.selected)},unselected: function (event, ui) {//console.log('unselect ui: ',ui)u = ui.unselected//从选择[]中删除未选择的.total = jQuery.grep(total, function (n) {返回 n !== u});//console.log('total array (unselected): ',total)},停止:功能(通风口,用户界面){//从total[]中删除重复的元素.jQuery.unique(总计)$(total).each(function () {$(this).draggable(dragOption)})//$(total).draggable(dragOption);//var widget = $( ".selector" ).draggable( "widget" );//console.log('widget: ',widget)console.log('断行---------------------------- ')}});//将拖动选项保存为Obj.拖动选项 = {不透明度:0.45,延迟:300,connectToSortable: ".slot"//,helper: 克隆",距离:5,snap: ".slot",snapMode:内部",回复:无效",开始:功能(事件,用户界面){console.log('可拖动开始 ui: ', ui)选择 = $(total).each(function () {var el = $(this);el.data("偏移量", el.offset())});offset = $(this).offset();//获取相对于文档的坐标},拖动:函数(事件,ui){//console.log(offset.top)var dt = ui.position.top - offset.top,dl = ui.position.left - offset.left;selected.not(this).each(function () {//创建变量,因为我们不需要继续调用 $("this")//el = 我们所在的当前元素//off = 这个元素在被选中时的位置,在拖动之前var el = $(this),off = el.data("偏移量");el.css({顶部:off.top + dt,左:off.left + dl});});},停止:功能(事件,用户界面){console.log('拖动停止 ui : ', ui)}};//将放置选项保存为Obj.dropOption = {接受:'.item',下降:功能(事件,用户界面){console.log('丢弃事件:', 事件);console.log('删除用户界面:', 用户界面)},activate: function (event, ui) {//console.log('this : ',this,'
ui : ',ui)},out: function (event, ui) {//console.log('out',$(this))},停用:功能(事件,用户界面){//console.log('停用')},容差:相交",instance: function (event, ui) {//console.log('instance ui : ',ui)},over: function (event, ui) {//console.log('this item : ',ui.draggable[0],'on this slot: ',this)},活动类:green3"}//使空槽可放置$(".slot:not(:has(>div))").droppable(dropOption)}) <!--文档准备就绪-->
HTML:
<div id="容器"><div id="header"></div><div class="box" id="boxA"><h4>框A</h4><div class="item" id="a1"></div>
<div class="item" id="a2"></div>
<div class="item" id="a3"></div>
<div class="slot" id="A4"></div><div class="slot" id="A5"></div>
<div class="box" id="boxB"><h4>框B</h4><div class="slot" id="B1"></div><div class="slot" id="B2"><div class="item" id="b2"></div>
<div class="slot" id="B3"></div><div class="slot" id="B4"></div><div class="slot" id="B5"><div class="item" id="b5"></div>
CSS:
文档{背景颜色:#FFF;}.盒子 {高度:180px;向左飘浮;边框顶部宽度:5px;边框右宽度:5px;边框底部宽度:5px;边框左宽度:5px;边框顶部样式:实心;边框右样式:实心;边框底部样式:实心;左边框样式:实心;边框顶部颜色:#999;边框右颜色:#999;边框底部颜色:#999;左边框颜色:#999;宽度:150px;文本对齐:居中;左边距:100px;}.物品 {位置:绝对;字体大小:12px;高度:14px;背景颜色:#CCC;宽度:110px;文字装饰:无;字体系列:Arial、Helvetica、sans-serif;颜色:#999;左边距:6px;文本对齐:居中;}#页眉页脚 {向左飘浮;高度:200px;宽度:100%;}.投币口{边框顶部宽度:1px;边框右宽度:1px;边框底部宽度:1px;边框左宽度:1px;边框顶部样式:虚线;边框右样式:虚线;边框底部样式:虚线;左边框样式:虚线;高度:15px;宽度:120px;边距顶部:2px;文本对齐:居中;垂直对齐:中间;行高:90px;右边距:自动;左边距:自动;}.ui-选择{背景:#FECA40;}.ui 选择 {背景色:#F90;}.green3 {背景颜色:#D9FFE2;}
解决方案
您可以使用 document.elementFromPoint
.
为了删除/恢复原始可拖动对象,我们在将其放入 drop<后执行以下操作/a> 事件:
- 在中检查droppable是否包含
.item
drop
事件.如果 droppable 尚未包含 .item
,请转到第 2 步,否则转到第 3 步 - append() 重置定位后的元素到对应的
.slot
使用 css()
- 使用
animate()
方法将元素恢复到我们之前的位置使用 .data()
缓存在 start
事件.
用于删除/还原被拖动的额外项目:
我们找到每个item左右可见区域的元素被拖动(距离被拖动元素1px,即应该是放置目标)使用document.elementFromPoint
.
由于没有为这些元素触发实际的 drop
事件,我们使用 stop 可拖动事件以检查 target 是否为 .slot
如果它们中的任何一个是 .slot
,这意味着该项目被丢弃在droppable,我们继续上面提到的step1,否则我们去step3(手动将项目恢复到原来的位置)
<小时>
$(function() {var dragOption = {延迟:10,距离:5,不透明度:0.45,回复:无效",恢复持续时间:100,开始:功能(事件,用户界面){$(".ui-selected").each(function() {$(this).data("原始", $(this).position());});},拖动:功能(事件,用户界面){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({位置:相对",左:偏移量.左,顶部:偏移量.top}).data("target", $.unique([targetLeft, targetRight]));});},停止:功能(事件,用户界面){$(".ui-selected").not(this).each(function() {var $target = $($(this).data("target")).filter(function(i, elm) {返回 $(this).is(".slot") &&!$(this).has(".item").length;});如果($target.length){$target.append($(this).css({顶部:0,左:0}))} 别的 {$(this).animate({顶部:0,左:0}, 慢的");}});$(".ui-selected").data("original", null).data(目标",空).removeClass("ui-selected");}},dropOption = {接受:'.item',activeClass: "green3",下降:功能(事件,用户界面){if ($(this).is(".slot") && !$(this).has(".item").length) {$(this).append(ui.draggable.css({顶部:0,左:0}));} 别的 {ui.draggable.animate({顶部:0,左:0}, 50);}}}$(".box").selectable({过滤器:.item",开始:功能(事件,用户界面){$(".ui-draggable").draggable("destroy");},停止:功能(事件,用户界面){$(".ui-selected").draggable(dragOption)}});$(".slot").droppable(dropOption);});
.box {向左飘浮;宽度:150px;高度:180px;文本对齐:居中;左边距:20px;边框:5px 实心 #999;}.投币口 {位置:相对;宽度:120px;高度:15px;边距顶部:2px;边距:0 自动;边框:1px 虚线;}.物品 {宽度:110px;高度:14px;边距:0 自动;z-索引:1;背景颜色:#CCC;}.ui-选择{背景:#FECA40;}.ui 选择 {背景色:#F90;}.green3 {背景颜色:#D9FFE2;}
<link href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" rel="样式表"/><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="容器"><div id="boxA" class="box"><h4>框A</h4><div id="A1" class="slot"><div id="a1" class="item"></div>
<div id="A2" class="slot"><div id="a2" class="item"></div>
<div id="A3" class="slot"><div id="a3" class="item"></div>
<div id="A4" class="slot"></div><div id="A5" class="slot"></div>
<div id="boxB" class="box"><h4>框B</h4><div id="B1" class="slot"></div><div id="B2" class="slot"><div id="b2" class="item"></div>
<div id="B3" class="slot"></div><div id="B4" class="slot"></div><div id="B5" class="slot"><div id="b5" class="item"></div>
<小时>其他参考:
<小时> P.S:这仅在可拖动小于可放置时才有效(在这种情况下是正确的)
Drawing a box with cursor (lasso) will select multiple .item
in this JSFiddle example.
Selected .item
's become draggable. Empty .slot
without an .item
inside is a valid droppable.
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:
$(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,'
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
.
For dropping/reverting the original draggable, we do the following once it is dropped in drop event:
- Check whether the droppable contains an
.item
or not in the drop
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 using css()
- 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:
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
.
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
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>
Other references:
P.S: This will only work if the draggable is smaller than droppable (Which is true in this case)
这篇关于拖放多个选定的可拖动对象并使用 Jquery UI 还原无效的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文