网页开发经常会有实现拖拽效果的需求.要实现移动一个元素首先需要知道鼠标坐标,其次需要知道鼠标点击哪个网页元素最后就是借助DOM对象控制其位移,
最简单的一种拖拽就是排列元素.例如:对有一个序列的内容页面,用拖拽改变顺序.就像MSN的编辑页面一样.
脚本代码片段如下:
var Demos = [ ];
var nDemos = 8;
var mouseOffset = null;
var iMouseDown = false;
var lMouseState = false;
var dragObject = null;
var DragDrops = [ ];
var curTarget = null;
var lastTarget = null;
var dragHelper = null;
var tempDiv = null;
var rootParent = null;
var rootSibling = null;
var nImg = new Image();
var D1Target = null;
Number.prototype.NaN0=function(){return isNaN(this)?0:this;}
function CreateDragContainer(){
var cDrag = DragDrops.length;
DragDrops[ cDrag ] = [ ];
for(var i=0; i<arguments.length; i++){
var cObj = arguments[ i ];
DragDrops[ cDrag ].push(cObj);
cObj.setAttribute('DropObj', cDrag);
for(var j=0; j<cObj.childNodes.length; j++){
if(cObj.childNodes[ j ].nodeName=='#text') continue;
cObj.childNodes[ j ].setAttribute('DragObj', cDrag);
}
}
}
function getPosition(e){
var left = 0;
var top = 0;
while (e.offsetParent){
left += e.offsetLeft + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0);
top += e.offsetTop + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0);
e = e.offsetParent;
}
left += e.offsetLeft + (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0);
top += e.offsetTop + (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0);
return {x:left, y:top};
}
function mouseCoords(ev){
if(ev.pageX || ev.pageY){
return {x:ev.pageX, y:ev.pageY};
}
return {
x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
y:ev.clientY + document.body.scrollTop - document.body.clientTop
};
}
function writeHistory(object, message){
if(!object || !object.parentNode || !object.parentNode.getAttribute) return;
var historyDiv = object.parentNode.getAttribute('history');
if(historyDiv){
historyDiv = document.getElementById(historyDiv);
historyDiv.appendChild(document.createTextNode(object.id+': '+message));
historyDiv.appendChild(document.createElement('BR'));
historyDiv.scrollTop += 50;
}
}
function getMouseOffset(target, ev){
ev = ev || window.event;
var docPos = getPosition(target);
var mousePos = mouseCoords(ev);
return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
}
function mouseMove(ev){
ev = ev || window.event;
var target = ev.target || ev.srcElement;
var mousePos = mouseCoords(ev);
if(Demos[ 0 ] || Demos[ 4 ]){
if(lastTarget && (target!==lastTarget)){
writeHistory(lastTarget, 'Mouse Out Fired');
var origClass = lastTarget.getAttribute('origClass');
if(origClass) lastTarget.className = origClass;
}
var dragObj = target.getAttribute('DragObj');
if(dragObj!=null){
if(target!=lastTarget){
writeHistory(target, 'Mouse Over Fired');
var oClass = target.getAttribute('overClass');
if(oClass){
target.setAttribute('origClass', target.className);
target.className = oClass;
}
}
if(iMouseDown && !lMouseState){
writeHistory(target, 'Start Dragging');
curTarget = target;
rootParent = curTarget.parentNode;
rootSibling = curTarget.nextSibling;
mouseOffset = getMouseOffset(target, ev);
for(var i=0; i<dragHelper.childNodes.length; i++) dragHelper.removeChild(dragHelper.childNodes[ i ]);
dragHelper.appendChild(curTarget.cloneNode(true));
dragHelper.style.display = 'block';
var dragClass = curTarget.getAttribute('dragClass');
if(dragClass){
dragHelper.firstChild.className = dragClass;
}
dragHelper.firstChild.removeAttribute('DragObj');
var dragConts = DragDrops[ dragObj ];
curTarget.setAttribute('startWidth', parseInt(curTarget.offsetWidth));
curTarget.setAttribute('startHeight', parseInt(curTarget.offsetHeight));
curTarget.style.display = 'none';
for(var i=0; i<dragConts.length; i++){
with(dragConts[ i ]){
var pos = getPosition(dragConts[ i ]);
setAttribute('startWidth', parseInt(offsetWidth));
setAttribute('startHeight', parseInt(offsetHeight));
setAttribute('startLeft', pos.x);
setAttribute('startTop', pos.y);
}
for(var j=0; j<dragConts[ i ].childNodes.length; j++){
with(dragConts[ i ].childNodes[ j ]){
if((nodeName=='#text') || (dragConts[ i ].childNodes[ j ]==curTarget)) continue;
var pos = getPosition(dragConts[ i ].childNodes[ j ]);
setAttribute('startWidth', parseInt(offsetWidth));
setAttribute('startHeight', parseInt(offsetHeight));
setAttribute('startLeft', pos.x);
setAttribute('startTop', pos.y);
}
}
}
}
}
if(curTarget){
dragHelper.style.top = mousePos.y - mouseOffset.y;
dragHelper.style.left = mousePos.x - mouseOffset.x;
var dragConts = DragDrops[ curTarget.getAttribute('DragObj') ];
var activeCont = null;
var xPos = mousePos.x - mouseOffset.x + (parseInt(curTarget.getAttribute('startWidth')) /2);
var yPos = mousePos.y - mouseOffset.y + (parseInt(curTarget.getAttribute('startHeight'))/2);
for(var i=0; i<dragConts.length; i++){
with(dragConts[ i ]){
if((parseInt(getAttribute('startLeft')) < xPos) &&
(parseInt(getAttribute('startTop')) < yPos) &&
((parseInt(getAttribute('startLeft')) + parseInt(getAttribute('startWidth'))) > xPos) &&
((parseInt(getAttribute('startTop')) + parseInt(getAttribute('startHeight'))) > yPos)){
activeCont = dragConts[ i ];
break;
}
}
}
if(activeCont){
if(activeCont!=curTarget.parentNode){
writeHistory(curTarget, 'Moved into '+activeCont.id);
}
var beforeNode = null;
for(var i=activeCont.childNodes.length-1; i>=0; i--){
with(activeCont.childNodes[ i ]){
if(nodeName=='#text') continue;
if(curTarget != activeCont.childNodes[ i ] &&
((parseInt(getAttribute('startLeft')) + parseInt(getAttribute('startWidth'))) > xPos) &&
((parseInt(getAttribute('startTop')) + parseInt(getAttribute('startHeight'))) > yPos)){
beforeNode = activeCont.childNodes[ i ];
}
}
}
if(beforeNode){
if(beforeNode!=curTarget.nextSibling){
writeHistory(curTarget, 'Inserted Before '+beforeNode.id);
activeCont.insertBefore(curTarget, beforeNode);
}
} else {
if((curTarget.nextSibling) || (curTarget.parentNode!=activeCont)){
writeHistory(curTarget, 'Inserted at end of '+activeCont.id);
activeCont.appendChild(curTarget);
}
}
setTimeout(function(){
var contPos = getPosition(activeCont);
activeCont.setAttribute('startWidth', parseInt(activeCont.offsetWidth));
activeCont.setAttribute('startHeight', parseInt(activeCont.offsetHeight));
activeCont.setAttribute('startLeft', contPos.x);
activeCont.setAttribute('startTop', contPos.y);}, 5);
if(curTarget.style.display!=''){
writeHistory(curTarget, 'Made Visible');
curTarget.style.display = '';
curTarget.style.visibility = 'hidden';
}
} else {
if(curTarget.style.display!='none'){
writeHistory(curTarget, 'Hidden');
curTarget.style.display = 'none';
}
}
}
lMouseState = iMouseDown;
lastTarget = target;
}
if(Demos[ 2 ]){
document.getElementById('MouseXPosition').value = mousePos.x;
document.getElementById('MouseYPosition').value = mousePos.y;
}
if(dragObject){
dragObject.style.position = 'absolute';
dragObject.style.top = mousePos.y - mouseOffset.y;
dragObject.style.left = mousePos.x - mouseOffset.x;
}
lMouseState = iMouseDown;
if(curTarget || dragObject) return false;
}
function mouseUp(ev){
if(Demos[ 0 ] || Demos[ 4 ]){
if(curTarget){
writeHistory(curTarget, 'Mouse Up Fired');
dragHelper.style.display = 'none';
if(curTarget.style.display == 'none'){
if(rootSibling){
rootParent.insertBefore(curTarget, rootSibling);
} else {
rootParent.appendChild(curTarget);
}
}
curTarget.style.display = '';
curTarget.style.visibility = 'visible';
}
curTarget = null;
}
if(Demos[ 6 ] && dragObject){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
var dT = dragObject.getAttribute('droptarget');
if(dT){
var targObj = document.getElementById(dT);
var objPos = getPosition(targObj);
if((mousePos.x > objPos.x) && (mousePos.y > objPos.y) && (mousePos.x<(objPos.x+parseInt(targObj.offsetWidth))) && (mousePos.y<(objPos.y+parseInt(targObj.offsetHeight)))){
var nSrc = targObj.getAttribute('newSrc');
if(nSrc){
dragObject.src = nSrc;
setTimeout(function(){
if(!dragObject || !dragObject.parentNode) return;
dragObject.parentNode.removeChild(dragObject);
dragObject = null;
}, parseInt(targObj.getAttribute('timeout')));
} else {
dragObject.parentNode.removeChild(dragObject);
}
}
}
}
dragObject = null;
iMouseDown = false;
}
function mouseDown(ev){
ev = ev || window.event;
var target = ev.target || ev.srcElement;
iMouseDown = true;
if(Demos[ 0 ] || Demos[ 4 ]){
if(lastTarget){
writeHistory(lastTarget, 'Mouse Down Fired');
}
}
if(target.onmousedown || target.getAttribute('DragObj')){
return false;
}
}
function makeDraggable(item){
if(!item) return;
item.onmousedown = function(ev){
dragObject = this;
mouseOffset = getMouseOffset(this, ev);
return false;
}
}
function makeClickable(item){
if(!item) return;
item.onmousedown = function(ev){
document.getElementById('ClickImage').value = this.name;
}
}
function addDropTarget(item, target){
item.setAttribute('droptarget', target);
}
document.onmousemove = mouseMove;
document.onmousedown = mouseDown;
document.onmouseup = mouseUp;
window.onload = function(){
for(var i=0; i<nDemos; i++){
Demos[ i ] = document.getElementById('Demo'+i);
}
if(Demos[ 0 ]){
CreateDragContainer(document.getElementById('DragContainer1'), document.getElementById('DragContainer2'), document.getElementById('DragContainer3'));
CreateDragContainer(document.getElementById('DragContainer7'));
CreateDragContainer(document.getElementById('DragContainer8'));
}
if(Demos[ 4 ]){
CreateDragContainer(document.getElementById('DragContainer4'), document.getElementById('DragContainer5'), document.getElementById('DragContainer6'));
}
if(Demos[ 0 ] || Demos[ 4 ]){
dragHelper = document.createElement('DIV');
dragHelper.style.cssText = 'position:absolute;display:none;';
document.body.appendChild(dragHelper);
}
if(Demos[ 1 ]){
makeDraggable(document.getElementById('DragImage1'));
makeDraggable(document.getElementById('DragImage2'));
makeDraggable(document.getElementById('DragImage3'));
makeDraggable(document.getElementById('DragImage4'));
}
if(Demos[ 5 ]){
makeDraggable(document.getElementById('DragImage5'));
makeDraggable(document.getElementById('DragImage6'));
makeDraggable(document.getElementById('DragImage7'));
makeDraggable(document.getElementById('DragImage8'));
}
if(Demos[ 6 ]){
makeDraggable(document.getElementById('DragImage9'));
makeDraggable(document.getElementById('DragImage10'));
makeDraggable(document.getElementById('DragImage11'));
makeDraggable(document.getElementById('DragImage12'));
addDropTarget(document.getElementById('DragImage9'), 'TrashImage1');
addDropTarget(document.getElementById('DragImage10'), 'TrashImage1');
addDropTarget(document.getElementById('DragImage11'), 'TrashImage1');
addDropTarget(document.getElementById('DragImage12'), 'TrashImage1');
}
if(Demos[ 3 ]){
makeClickable(document.getElementById('ClickImage1'));
makeClickable(document.getElementById('ClickImage2'));
makeClickable(document.getElementById('ClickImage3'));
makeClickable(document.getElementById('ClickImage4'));
}
}