使用 jquery 拖放更改 div 的位置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15343385/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Change position of divs with jquery drag an drop
提问by Stefan
I'm trying to build a website where the user can drag some items (one item in on div) to other divs on the page. It' not a table or so, just divs somewhere on the page.
我正在尝试构建一个网站,用户可以在其中将某些项目(div 中的一个项目)拖动到页面上的其他 div。它不是一个表格,只是页面上某个地方的 div。
With html5 drag&drop it works well, now I try to do this for mobile devices. I can drag items to divs, drop them there and block this dropzone, because only one element should be in a dropzone. I also can drag this element to another div or somewhere else on the page (droppable areas only work on first time a div is dropped) if I've had make a mistake but then I cannot drop another item in the div which is now empty again.
使用 html5 拖放效果很好,现在我尝试为移动设备执行此操作。我可以将项目拖到 div 中,将它们放在那里并阻止这个放置区,因为只有一个元素应该在放置区中。如果我犯了一个错误,我也可以将此元素拖动到另一个 div 或页面上的其他位置(可放置区域仅在第一次放置 div 时有效),但随后我无法将另一个项目放置在现在为空的 div 中再次。
How can I enable dropping in this Dropzone again?
如何再次启用在此 Dropzone 中放置?
And is it possible to two change the position of two divs if one is dragged on another?
如果一个被拖到另一个上,是否可以改变两个 div 的位置?
Here is the relevant part of my code:
这是我的代码的相关部分:
<script type="text/javascript">
$ (init);
function init() {
$(".dragzones").draggable({
start: handleDragStart,
cursor: 'move',
revert: "invalid",
});
$(".dropzones").droppable({
drop: handleDropEvent,
tolerance: "touch",
});
}
function handleDragStart (event, ui) {}
function handleDropEvent (event, ui) {
$(this).droppable('disable');
ui.draggable.position({of: $(this), my: 'left top', at: 'left top'});
ui.draggable.draggable('option', 'revert', "invalid");
}
</script>
<body>
<div id="alles">
<div class="dropzones" id="zone1"><div class="dragzones" id="drag1">Item 1</div></div>
<div class="dropzones" id="zone2"><div class="dragzones" id="drag2">Item 2</div></div>
<div class="dropzones" id="zone3"><div class="dragzones" id="drag3">Item 3</div></div>
<div class="dropzones" id="zone4"><div class="dragzones" id="drag4">Item 4</div></div>
<div class="dropzones" id="zone11"></div>
<div class="dropzones" id="zone12"></div>
<div class="dropzones" id="zone13"></div>
<div class="dropzones" id="zone14"></div>
</div>
</body>
EDIT: Here is the now working page: Drag&Drop Task
编辑:这是现在的工作页面:拖放任务
回答by Gajotres
Here's a working example: http://jsfiddle.net/Gajotres/zeXuM/
这是一个工作示例:http: //jsfiddle.net/Gajotres/zeXuM/
I think all of your problems are solved here.
我想你所有的问题都在这里解决了。
- enable/disable dropping works
- elements returning no longer drops them below other elements
- elements returning no longer hides/remove them
- better elements positioning (it looks better)
- it works on mobile devices (tested on Android 4.1.1 Chrome and iPhone)
- 启用/禁用删除工作
- 返回的元素不再将它们放在其他元素下方
- 返回的元素不再隐藏/删除它们
- 更好的元素定位(看起来更好)
- 它适用于移动设备(在 Android 4.1.1 Chrome 和 iPhone 上测试)
Here's a jQuery code used:
这是使用的jQuery代码:
$(document).on('pageshow', '#index', function(){
$(".dragzones").draggable({
start: handleDragStart,
cursor: 'move',
revert: "invalid",
});
$(".dropzones").droppable({
drop: handleDropEvent,
tolerance: "touch",
});
});
function handleDragStart (event, ui) { }
function handleDropEvent (event, ui) {
if (ui.draggable.element !== undefined) {
ui.draggable.element.droppable('enable');
}
$(this).droppable('disable');
ui.draggable.position({of: $(this),my: 'left top',at: 'left top'});
ui.draggable.draggable('option', 'revert', "invalid");
ui.draggable.element = $(this);
}
// This is a fix for mobile devices
/iPad|iPhone|Android/.test( navigator.userAgent ) && (function( $ ) {
var proto = $.ui.mouse.prototype,
_mouseInit = proto._mouseInit;
$.extend( proto, {
_mouseInit: function() {
this.element
.bind( "touchstart." + this.widgetName, $.proxy( this, "_touchStart" ) );
_mouseInit.apply( this, arguments );
},
_touchStart: function( event ) {
this.element
.bind( "touchmove." + this.widgetName, $.proxy( this, "_touchMove" ) )
.bind( "touchend." + this.widgetName, $.proxy( this, "_touchEnd" ) );
this._modifyEvent( event );
$( document ).trigger($.Event("mouseup")); //reset mouseHandled flag in ui.mouse
this._mouseDown( event );
//return false;
},
_touchMove: function( event ) {
this._modifyEvent( event );
this._mouseMove( event );
},
_touchEnd: function( event ) {
this.element
.unbind( "touchmove." + this.widgetName )
.unbind( "touchend." + this.widgetName );
this._mouseUp( event );
},
_modifyEvent: function( event ) {
event.which = 1;
var target = event.originalEvent.targetTouches[0];
event.pageX = target.clientX;
event.pageY = target.clientY;
}
});
})( jQuery );
Original author of a touchFix plugin used in this example is Oleg Slobodskoi.
本示例中使用的 touchFix 插件的原作者是Oleg Slobodskoi。
回答by Apostolos Emmanouilidis
EDITED:
编辑:
On each successful drop you can save the last drop object on the draggable. So when the draggable moves to another drop object you can enable the droppable of the previous drop object.
每次成功放置时,您都可以将最后一个放置对象保存在可拖动对象上。因此,当可拖动对象移动到另一个放置对象时,您可以启用前一个放置对象的可放置对象。
See below:
见下文:
Try to modify the handleDropEventto:
尝试将handleDropEvent修改为:
function handleDropEvent(event, ui) {
if (ui.draggable.lastDropObject !== undefined) {
ui.draggable.lastDropObject.droppable('enable');
}
var dropObject = $(this);
dropObject.droppable('disable');
ui.draggable.position({
of: $(this),
my: 'left top',
at: 'left top'
});
ui.draggable.draggable('option', 'revert', "invalid");
ui.draggable.lastDropObject = dropObject;
}
Full working example based on your source code:
基于您的源代码的完整工作示例:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Drag & Drop with jQuery</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="title" content="" />
<meta name="keywords" content="" />
<meta name="description" content="" />
<link href="http://www.didaktik.physik.uni-muenchen.de/forschung/elektronenbahnen/Betaversion/Tests/Styletest.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://www.didaktik.physik.uni-muenchen.de/forschung/elektronenbahnen/Betaversion/Tests/../Alle Seiten/JS/jquery.js"></script>
<script type="text/javascript" src="http://www.didaktik.physik.uni-muenchen.de/forschung/elektronenbahnen/Betaversion/Tests/../Alle Seiten/JS/jquery-ui-1.8.23.custom.min.js"></script>
<script type="text/javascript" src="http://www.didaktik.physik.uni-muenchen.de/forschung/elektronenbahnen/Betaversion/Tests/../Alle Seiten/JS/jquery.ui.touch-punch.min.js"></script>
<script type="text/javascript">
var test;
$(init);
function init() {
$(".dragzones")
.draggable({
start: handleDragStart,
cursor: 'move',
revert: "invalid"
});
$(".dropzones")
.droppable({
drop: handleDropEvent,
tolerance: "touch",
});
};
function handleDragStart(event, ui) {}
function handleDropEvent(event, ui) {
if (ui.draggable.lastDropObject !== undefined) {
ui.draggable.lastDropObject.droppable('enable');
}
var dropObject = $(this);
dropObject.droppable('disable');
ui.draggable.position({
of: $(this),
my: 'left top',
at: 'left top'
});
ui.draggable.draggable('option', 'revert', "invalid");
ui.draggable.lastDropObject = dropObject;
}
function check() {
var i = 1;
var richtige = 0;
while (i <= 10) {
var j = i + 10;
if (document.getElementById('zone' + j)
.innerHTML.search('drag' + i + '"') == 27) {
document.getElementById('zone' + j)
.style.border = '2px solid green';
richtige++;
} else {
document.getElementById('zone' + j)
.style.border = '2px solid red';
}
i++;
alert(document.getElementById(zone + j)
.innerHTML);
};
}
</script>
</head>
<body>
<div id="alles">
<div id="hintergrundbildZuordnungsaufgaben">
<img src="http://www.didaktik.physik.uni-muenchen.de/forschung/elektronenbahnen/Betaversion/Tests/../E-Feld/Bilder/Versuchsaufbau-Elektronenablenkroehre-unbeschriftet.png" width="740">
</div>
<div class="dropzones" id="zone1">
<div class="dragzones" id="drag1">Item 1</div>
</div>
<div class="dropzones" id="zone2">
<div class="dragzones" id="drag2">Item 2</div>
</div>
<div class="dropzones" id="zone3">
<div class="dragzones" id="drag3">Item 3</div>
</div>
<div class="dropzones" id="zone4">
<div class="dragzones" id="drag4">Item 4</div>
</div>
<div class="dropzones" id="zone5">
<div class="dragzones" id="drag5">Item 5</div>
</div>
<div class="dropzones" id="zone6">
<div class="dragzones" id="drag6">Item 6</div>
</div>
<div class="dropzones" id="zone7">
<div class="dragzones" id="drag7">Item 7</div>
</div>
<div class="dropzones" id="zone8">
<div class="dragzones" id="drag8">Item 8</div>
</div>
<div class="dropzones" id="zone9">
<div class="dragzones" id="drag9">Item 9</div>
</div>
<div class="dropzones" id="zone10">
<div class="dragzones" id="drag10">Item 10</div>
</div>
<div class="dropzones" id="zone11"></div>
<div class="dropzones" id="zone12"></div>
<div class="dropzones" id="zone13"></div>
<div class="dropzones" id="zone14"></div>
<div class="dropzones" id="zone15"></div>
<div class="dropzones" id="zone16"></div>
<div class="dropzones" id="zone17"></div>
<div class="dropzones" id="zone18"></div>
<div class="dropzones" id="zone19"></div>
<div class="dropzones" id="zone20"></div>
<button id="check" value="Check" onclick="check()">Check</button>
</div>
</body>
</html>
I hope this helps.
我希望这有帮助。
回答by EGL 2-101
You "Example" link looks like working correctly. But I would like to give generic solution to your problem.
您的“示例”链接看起来工作正常。但我想为您的问题提供通用解决方案。
Basically you watch status of dropzone. When user drops the item, you check if dropzone is available or not. if not set "revert" true.
基本上你看dropzone的状态。当用户放下项目时,您检查 dropzone 是否可用。如果没有设置“恢复”为真。
function handleDropEvent (event, ui) {
if ($(this).hasClass('occupied')) {
ui.draggable.draggable('option', 'revert', true);
return false;
}
$(this).append(ui.draggable);
ui.draggable.position({of: $(this), my: 'left top', at: 'left top'});
ui.draggable.css('z-index', 0);
setTimeout(validateDropzones, 0);
}
Full working example is here: http://jsfiddle.net/jaygiri/SRPm2/
完整的工作示例在这里:http: //jsfiddle.net/jaygiri/SRPm2/
Thanks.
谢谢。
回答by Scott
This is as far as I've gotten:
这是我得到的:
$ (init);
function init() {
$(".dragzones").draggable({
start: handleDragStart,
cursor: 'move',
revert: 'invalid',
opacity: .5,
});
$(".dropzones").droppable({
drop: handleDropEvent,
tolerance: "touch",
out: handleDropRemove
});
//prevents dragging to filled default droppables on start
$(".dropzones").each(function(){
if ($(this).html().length) {
$(this).addClass('taken');
}
});
}
function handleDragStart (event, ui) {}
function handleDropRemove(event, ui) {
//allows drop after removal
$(this).removeClass('taken');
}
function handleDropEvent (event, ui) {
if ($(this).hasClass('taken')) {
//rejects drop if full
ui.draggable.draggable('option', 'revert', true);
} else {
//accepts drop if enpty
ui.draggable.position({of: $(this), my: 'left top', at: 'left top'});
$(this).addClass('taken');
}
}
There are a couple issues I'm trying to sort still. Seems if the cursor hits the very bottom of a drop zone when it is filled, the out function is being called. I can't seem to figure out how to prevent that.
有几个问题我仍在努力解决。似乎如果光标在填充时击中放置区的最底部,则正在调用 out 函数。我似乎无法弄清楚如何防止这种情况发生。