转载 [转]如何在 JavaScript 中实现拖放 收藏

来源:http://www.javaeye.com/post/152142


译者说明:

终于完成了全文的翻译,由于时间比较参促,文章没有过多的校正与润色,阅读过程中难免会有些许生硬或不准确的感觉,请大家见量并指出,方便他人阅读。

原文作者将拖放功能的实现分步讲解,其核心的地方在于移动和放置元素时,鼠标、移动元素、目标元素关系的处理,只要这个问题处理好了,代码就很容易理解,译文仅供辅助参考之用,demo可以参考原文链接

[翻译]如何在 JavaScript 中实现拖放


JavaScript擅长于修改页面中的DOM元素,但是我们使用JavaScript通常只是实现一些简单功能,例如实现图片的翻转,网页中的标签页,等等。这篇文章将向你展示如何在页面中,对创建的元素实现拖放。

有许多理由让你在页面中加入拖放的功能,其中最简单的理由是重新组织数据。举个例子,你可能希望用户能够重组一系列的页面元素,通过放置一个input或 select组件在各个元素的旁边来代表它们的顺序是一种解决方案,使该组元素可以被拖放是一种替代方案。或者也许你想在网站上拥有一个可以被用户移动的导航窗口。这些都是使用拖放功能的简单理由,因为你能够实现!

在你的网页上实现拖放的效果并不是很复杂。首先,我们知道鼠标的位置,然后我们需要了解用户什么时候点击一个元素,以至于我们知道要准备开始拖动它,最后我们要移动这个元素。

捕获鼠标的移动

第一步,我们需要获取鼠标的坐标,通过一个函数并赋给document.onmousemove可以实现这一功能:

代码
  1. document.onmousemove = mouseMove;   
  2. function mouseMove(ev) {   
  3.   ev = ev || window.event;   
  4.   var mousePos = mouseCoords(ev);   
  5. }   
  6. function mouseCoords(ev) {   
  7.   if(ev.pageX || ev.pageY) {   
  8.     return {x:ev.pageX, y:ev.pageY};   
  9.   }   
  10.   return {   
  11.     x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,   
  12.     y:ev.clientY + document.body.scrollTop - document.body.clientTop   
  13.   };   
  14. }  

首先我们需要解释一下event对象。不论你什么时候移动、点击鼠标,或按键,等等,一个事件都会发生。在IE中,这个事件是全局的,它被存储在 window.event中,对于Firefox,及其他的浏览器来说,这个事件将被传递到任何指向这个页面动作的函数中。因此,我们使 document.onmousemove指向鼠标移动的函数,鼠标移动的函数获得事件对象。

上述代码中,ev在所有浏览器环境中都包含了event对象。在Firefox里,"||window.event"将被忽略,因为它已经包含事件。在IE中,ev的值为空,以至于需要将它的值设置为window.event。

本文中我们需要多次捕获到鼠标的坐标,因此我们写了一个mouseCoords方法,它有一个参数:event。

我们要再次讨论IE和其他浏览器之间的差异。Firefox和其他的浏览器使用event.pageX和event.pageY来表示鼠标相对于 document文档的位置。如果你有一个500*500的窗口,并且鼠标位于窗口中间,那么pageX和pageY的值将都是250。如果你将窗口向下滚动500象素,pageY的值为750。

如此相反的是,微软的IE使用event.clientX和event.clientY来表示鼠标相对于window窗口的位置,而不是当前 document文档。在相同的例子中,如果将鼠标放置于500*500窗口的中间,clientX和clientY值将均为250。如果向下滚动页面, clientY将仍为250,因为它是相对于window窗口来测量,而不是当前的document文档。因此,在鼠标位置中,我们应该引入 document文档body区域的scrollLeft和scrollTop属性。最后,IE中document文档实际并不在(0,0)的位置,在它周围有一个小(通常有2px)边框,document.body.clientLeft和document.body.clientTop包含了这个边框的宽度,从而还需要在鼠标位置中引入它们。

幸运的是,现在我们拥有了mouseCoords函数,不用再为获取鼠标位置担心了。

捕获鼠标的点击

下一步,我们必须知道鼠标何时点击及何时释放。如果我们跳过这一步,只要你的鼠标移动经过这些元素时,都将产生拖动这些元素的效果,这是令人讨厌并违反人的直觉的。

在这里,有两个函数可以帮助我们:onmousedown和onmouseup。先前我们已将document.onmousemove指向一个函数,因此从逻辑上似乎应该使document.onmousedown和document.onmouseup都指向函数。如果我们让 document.onmousedown指向一个函数,那么这个函数将会因为鼠标点击任何元素而执行:文本、图像、表格,等等。我们只想页面中特定的元素具有被拖放的功能,因此,我们可以通过如下方法实现:

代码
  1. document.onmouseup = mouseUp;   
  2. var dragObject = null;   
  3. function makeClickable(object) {   
  4.   object.onmousedown = function() {   
  5.   dragObject = this;   
  6.   }   
  7. }   
  8. function mouseUp(ev) {   
  9.   dragObject = null;   
  10. }  

我们现在有了一个变量dragObject,包含了你点击的任何元素。当你释放鼠标的时候,dragObject被设置为空,从而在dragObject非空的时候,我们需要进行拖动操作。

移动元素

我们现在已经知道如何捕获鼠标移动和点击。接下来需要做的就是移动任何我们想拖动的元素。首先,将一个元素准确移动到页面上我们想要的位置,该元素样式表的position值必须为absolute,这意味着你可以设置它的style.top或style.left,测量值相对于页面的左上角,因为我们所有的鼠标移动都是相对于页面左上角的,通常都是这样。

一旦我们设置了item.style.position='absolute',接下来就需要改变该元素top和left的位置,使它移动!

代码
  1. document.onmousemove = mouseMove;   
  2. document.onmouseup = mouseUp;   
  3. var dragObject = null ;   
  4. var mouseOffset = null ;   
  5. function  getMouseOffset(target, ev)  {   
  6.   ev = ev || window.event;   
  7.   var docPos = getPosition(target);   
  8.   var mousePos = mouseCoords(ev);   
  9.   return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y} ;   
  10. }   
  11.   
  12. function getPosition(e) {   
  13.    var left = 0;   
  14.    var top = 0;   
  15.    while (e.offsetParent) {   
  16.      left += e.offsetLeft;   
  17.      top += e.offsetTop;   
  18.      e = e.offsetParent;   
  19.   }   
  20.   left += e.offsetLeft;   
  21.   top += e.offsetTop;   
  22.   return {x:left, y:top} ;   
  23. }   
  24.   
  25. function mouseMove(ev) {   
  26.   ev = ev || window.event;   
  27.   var mousePos = mouseCoords(ev);   
  28.   if (dragObject) {   
  29.     dragObject.style.position = 'absolute';   
  30.     dragObject.style.top = mousePos.y - mouseOffset.y;   
  31.     dragObject.style.left = mousePos.x - mouseOffset.x;   
  32.     return false ;   
  33.   }   
  34. }   
  35.   
  36. function mouseUp() {   
  37.   dragObject = null ;   
  38. }   
  39.   
  40. function makeDraggable(item) {   
  41.   if (!item) return ;   
  42.   item.onmousedown = function (ev) {   
  43.     dragObject = this ;   
  44.     mouseOffset = getMouseOffset(this, ev);   
  45.     return false ;   
  46.   }   
  47. }  

你会注意到这些代码是以我们前面的例子为基础的(参考上篇文章),将它们放置在一起,你将能够随意的去移动元素。

当我们点击一个元素时,存储了另外的一个变量,mouseOffset。mouseOffset简单的包含了我们点击元素的位置信息。如果我们有一张 20*20px的图像,然后点击图像的中间,mouseOffset应该是{x:10, y:10}。如果我们点击图像的左上角,mouseOffset应为{x:0, y:0}。我们在鼠标移动后的位置信息中用到它。如果我们没有存储这个值,不论你点击元素的哪一个位置,元素相对于鼠标的位置都将会是相同的。

mouseOffset函数用到了另外一个函数getPosition。getPosition目的是返回元素相对于documemt文档的坐标位置。如果我们简单的去读取item.offsetLeft或item.style.left,得到的将是元素相对于它父元素的位置,而不是document文档的。在我们的脚本中,所有的元素都是相对于document文档的,因此需要这样做。

要完成获取元素相对于document文档位置的工作,getPosition从它自身的父级开始,循环获取它的left和top的值并累加,这样我们就得到了我们想要的元素距文档顶部和左侧的累计值。

当我们获取了这条信息并移动鼠标的时候,mouseMove开始运行。首先我们需要保证item.style.position值为absolute,接着,我们将元素移动到任何一个地方,鼠标位置都会减去我们之前记录的鼠标相对于元素的偏移量。当鼠标释放时,dragObject将被设置为null,并且mouseMove函数不再做任何事情。

放置元素

我们前面的例子已经处理了这个问题,仅仅是拖动一个元素,然后将它放下。然后,在我们放下元素的时候通常还有其他的目的,我们以拖动元素到垃圾回收站为例,或我们可能想让该元素和页面中某个特定的区域对齐。

不幸的是我们在这里进入了一个相对主要的问题。因为我们正在移动的元素总是直接处于我们的鼠标下,而不可能去引发mouseover、 mousedown、mouseup或鼠标对页面中其他元素的操作。如果你移动一个元素到垃圾回收站,你的鼠标会一直在移动元素的上方,而不是垃圾回收站。

那么我们该如何处理这个问题呢?这里有几种解决方案。在前面所提到的mouseOffset的目的是保证元素总是在鼠标下方正确的位置,如果你忽视了这点,然后总是使得元素在鼠标的右下方,你的鼠标将不会被你正在拖动的元素所隐藏,我们也不会碰到问题。但事实上往往不会这样,为了美观我们通常要保持元素在鼠标的下方。

另外一种选择是不移动你正在拖动的元素,你可以改变鼠标样式,来告诉使用者你正在拖动一个元素,直到你将它放置到某个地方。这解决了我们的问题,但是带来了和前面一种方案面临的同样问题:美观。

我们最后的一种解决方案既不影响你正在移动的元素,也不影响移动终点位置上的元素(例如垃圾回收站)。不幸的是,这比前面两种解决方案的难度更大。我们将要做的是获得一组我们要放置的目标,当鼠标释放时,我们手工检查当前鼠标相对于每个目标的位置,看鼠标是否释放在这个目标中某一个目标的位置上,如果是的,我们就知道我们已经将元素放置在我们的目标上了。

代码
  1. /**/ /*  
  2. All code from the previous example is needed with the exception  
  3. of the mouseUp function which is replaced below  
  4. */  
  5.   
  6. var dropTargets = [];   
  7.   
  8. function addDropTarget(dropTarget) {   
  9.   dropTargets.push(dropTarget);   
  10. }   
  11.   
  12. function mouseUp(ev) {   
  13.   ev = ev || window.event;   
  14.   var mousePos = mouseCoords(ev);   
  15.   
  16.   for (var i = 0; i < dropTargets.length; i ++) {   
  17.     var curTarget = dropTargets[i];   
  18.     var targPos = getPosition(curTarget);   
  19.     var targWidth = parseInt(curTarget.offsetWidth);   
  20.     var targHeight = parseInt(curTarget.offsetHeight);   
  21.   
  22.     if (   
  23.       (mousePos.x > targPos.x) &&    
  24.       (mousePos.  < (targPos.x + targWidth)) &&    
  25.       (mousePos.y > targPos.y) &&    
  26.       (mousePos.y < (targPos.y  +  targHeight))) {   
  27.        // dragObject was dropped onto curTarget!   
  28.     }   
  29.   }   
  30.   dragObject    =   null ;   
  31. }  

这个例子中当鼠标释放时,我们循环每个可能放置元素的目标,如果鼠标指针在目标上,我们则拥有了一个放置元素的事件,通过鼠标横坐标大于目标元素左侧横坐标(mousePos.x>targPos.x),小于目标元素右侧横坐标(mousePos.x<(targPos.x+ targWidth))来判定,对于Y坐标我们做同样的判断。如果所有的这些值都返回true,那么我们的鼠标就是在目标元素的范围内。

整合所有的功能

最后我们使用所有代码片断,来创建一个完整的拖放函数脚本。我们所要做的第一件事情是DOM操作,如果你对此并不十分熟悉,可以阅读《JavaScript Primer on DOM Manipulation》。

接下来的代码创建容器和容器组,使得在这些容器中可以拖动每个元素,这在本文第二个demo的基础上来完成。这段代码能够用来重新规划元素的顺序,将导航窗口放在页面的左侧或右侧,或再加入你所能想到的其他的功能。

我们将使用伪代码来一步步进行讲解,将真实的代码通过注释的方式留给读者查看。

1.当文档第一次被加载时,我们创建一个名为dragHelper的DIV标签,当我们开始移动一个元素的时候,dragHelper将成为一个隐藏元素,可以四处移动。真实的元素并不会被拖动,仅仅使用insertBefore和appendChild来移动。我们在开始的时候隐藏dragHelper。

2.我们创建mouseDown和mouseUp函数。起初,所有的这些函数都假设记录了鼠标按钮的状态,以至于iMouseDown变量在鼠标按下的时候为true,没有按下的时候为false。

3.我们创建一个全局变量DragDrops,以及一个函数CreateDragContainer。DragDrops包含一组相互关联的容器。传入CreateDragContainer的任何变量(代表容器)被组织成一个新的集合,使元素能够在这些容器间自由移动。通过setAttribute,CreateDragContainer函数同样将各容器中的元素绑定在一起。

4.现在我们的代码知道每个元素所在的集合,现在来看mouseMove函数。mouseMove函数首先设置了一个变量target,表示鼠标下面的目标元素,如果这个元素在集合(用getAttribute判断)中就继续下面操作:

4.1.首先,在必要的时候,我们运行一个简单的脚本来改变目标元素的class属性,这样就创造了一个翻动的效果。

4.2.然后我们检查鼠标是否点击(因为我们的代码已经运行到这里),如果事件发生:

4.2.1.设置变量curTarget为当前元素。
4.2.2.记录元素当前在文档中的位置,以便在需要的时候可以将它的值取回。
4.2.3.将当前元素克隆到dragHelper,使得我们能够移动元素的隐藏备份。
4.2.4.因为在dragHelper中我们完全拥有了拖动元素的一个备份,这个元素会始终在鼠标下,我们必须移除dragObj属性,让代码知道dragObj已不在集合中。
4.2.5.我们快速记录集合中每个元素当前的位置、宽度和高度。当元素第一次开始被拖动时,我们仅需做一次这种工作,否则每当鼠标移动的时候我们都必须做一次,甚至一秒内几百次。

4.3.如果鼠标没有点击,要么我们和之前拥有同样的目标元素,要么没有目标元素,不论哪种情况我们都不会做任何事情。

5.现在我们检查curTarget变量。curTarget应该仅包含一个被拖动的对象,因此如果它存在,表示我们正在拖动一个元素:

5.1.移动隐藏DIV到鼠标,这个元素和文章前面所创建的元素一样能够被拖动。

5.2.然后我们检查鼠标是否存在于当前集合中每个容器中。

5.2.1.如果鼠标在某个容器中,我们检查容器中的每个元素,查看我们正拖动的元素属于哪个位置。
5.2.2.然后我们将所拖动的元素放置在容器中另一个元素的前面,或容器的最后位置。
5.2.3.最后我们确定元素可见。

6.剩下的事情就是捕获mouseUp事件:
6.1.首先需要隐藏dragHelper:它不再被需要,因为我们没有拖动任何东西。
6.2.如果拖动的元素是可见的,它已经存在于任何它所属的容器中,所有工作已完成。
6.3.如果拖动的元素不可见,我们将它放回它原来所在的地方。

代码
// iMouseDown represents the current mouse button state: up or down   
/**//*
  
lMouseState represents the previous mouse button state so that we can  
check for button clicks and button releases:  
 
if(iMouseDown && !lMouseState) // button just clicked!  
if(!iMouseDown && lMouseState) // button just released!  
*/  
var mouseOffset = null;   
var iMouseDown  = false;   
var lMouseState = false;   
var dragObject  = null;   
  
// Demo 0 variables   
var DragDrops   = [];   
var curTarget   = null;   
var lastTarget  = null;   
var dragHelper  = null;   
var tempDiv     = null;   
var rootParent  = null;   
var rootSibling = null;   
  
Number.prototype.NaN0
=function(){return isNaN(this)?0:this;}   
  
function CreateDragContainer(){   
  
/**//*  
  Create a new "Container Instance" so that items from one "Set" can not  
  be dragged into items from another "Set"  
  
*/  
  
var cDrag = DragDrops.length;   
  DragDrops[cDrag] 
= [];   
  
  
/**//*  
  Each item passed to this function should be a "container".  Store each  
  of these items in our current container  
  
*/  
  
for(var i=0; i<arguments.length; i++){   
    
var cObj = arguments[i];   
    DragDrops[cDrag].push(cObj);   
    cObj.setAttribute(
'DropObj', cDrag);   
  
    
/**//*  
    Every top level item in these containers should be draggable.  Do this  
    by setting the DragObj attribute on each item and then later checking  
    this attribute in the mouseMove function  
    
*/  
    
for(var j=0; j<cObj.childNodes.length; j++){   
  
      
// Firefox puts in lots of #text nodesskip these   
      if(cObj.childNodes[j].nodeName=='#text'continue;   
  
      cObj.childNodes[j].setAttribute(
'DragObj', cDrag);   
    }   
  }   
}   
  
function mouseMove(ev){   
    ev 
= ev || window.event;   
  
    
/**//*  
    We are setting target to whatever item the mouse is currently on  
    Firefox uses event.target here, MSIE uses event.srcElement  
    
*/  
    
var target = ev.target || ev.srcElement;   
    
var mousePos = mouseCoords(ev);   
  
    
// mouseOut event - fires if the item the mouse is on has changed   
    if(lastTarget && (target!==lastTarget)){   
      
// reset the classname for the target element   
      var origClass = lastTarget.getAttribute('origClass');   
      
if(origClass) lastTarget.className = origClass;   
    }   
  
    
/**//*  
    dragObj is the grouping our item is in (set from the createDragContainer function).  
    if the item is not in a grouping we ignore it since it can't be dragged with this  
    script.  
    
*/  
    
var dragObj = target.getAttribute('DragObj');   
  
    
// if the mouse was moved over an element that is draggable   
    if(dragObj!=null){   
      
// mouseOver event - Change the item's class if necessary   
      if(target!=lastTarget){   
        
var oClass = target.getAttribute('overClass');   
        
if(oClass){   
          target.setAttribute(
'origClass', target.className);   
          target.className 
= oClass;   
        }   
      }   
  
      
// if the user is just starting to drag the element   
      if(iMouseDown && !lMouseState){   
        
// mouseDown target   
        curTarget = target;   
  
        
// Record the mouse x and y offset for the element   
        rootParent = curTarget.parentNode;   
        rootSibling 
= curTarget.nextSibling;   
  
        mouseOffset   
= getMouseOffset(target, ev);   
  
        
// We remove anything that is in our dragHelper DIV so we can put a new item in it.   
        for(var i=0; i<dragHelper.childNodes.length; i++) dragHelper.removeChild(dragHelper.childNodes[i]);   
  
        
// Make a copy of the current item and put it in our drag helper.   
        dragHelper.appendChild(curTarget.cloneNode(true));   
        dragHelper.style.display 
= 'block';   
  
        
// set the class on our helper DIV if necessary   
        var dragClass = curTarget.getAttribute('dragClass');   
        
if(dragClass){   
          dragHelper.firstChild.className 
= dragClass;   
        }   
  
        
// disable dragging from our helper DIV (it's already being dragged)   
        dragHelper.firstChild.removeAttribute('DragObj');   
  
        
/**//*  
        Record the current position of all drag/drop targets related  
        to the element.  We do this here so that we do not have to do  
        it on the general mouse move event which fires when the mouse  
        moves even 1 pixel.  If we don't do this here the script  
        would run much slower.  
        
*/  
        
var dragConts = DragDrops[dragObj];   
  
        
/**//*  
        first record the width/height of our drag item.  Then hide it since  
        it is going to (potentially) be moved out of its parent.  
        
*/  
        curTarget.setAttribute(
'startWidth',  parseInt(curTarget.offsetWidth));   
        curTarget.setAttribute(
'startHeight', parseInt(curTarget.offsetHeight));   
        curTarget.style.display  
= 'none';   
  
        
// loop through each possible drop container   
        for(var i=0; i<dragConts.length; i++){   
          
with(dragConts[i]){   
            
var pos = getPosition(dragConts[i]);   
  
            
/**//*  
            save the width, height and position of each container.  
 
            Even though we are saving the width and height of each  
            container back to the container this is much faster because  
            we are saving the number and do not have to run through  
            any calculations again.  Also, offsetHeight and offsetWidth  
            are both fairly slow.  You would never normally notice any  
            performance hit from these two functions but our code is  
            going to be running hundreds of times each second so every  
            little bit helps!  
 
            Note that the biggest performance gain here, by far, comes  
            from not having to run through the getPosition function  
            hundreds of times.  
            
*/  
            setAttribute(
'startWidth', parseInt(offsetWidth));   
            setAttribute(
'startHeight', parseInt(offsetHeight));   
            setAttribute(
'startLeft', pos.x);   
            setAttribute(
'startTop', pos.y);   
          }   
  
          
// loop through each child element of each container   
          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]);   
  
              
// save the width, height and position of each element   
              setAttribute('startWidth',  parseInt(offsetWidth));   
              setAttribute(
'startHeight', parseInt(offsetHeight));   
              setAttribute(
'startLeft',   pos.x);   
              setAttribute(
'startTop',    pos.y);   
            }   
          }   
        }   
      }   
    }   
  
    
// If we get in here we are dragging something   
    if(curTarget){   
      
// move our helper div to wherever the mouse is (adjusted by mouseOffset)   
      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);   
  
      
// check each drop container to see if our target object is "inside" the container   
      for(var i=0; i<dragConts.length; i++){   
        
with(dragConts[i]){   
          
if(((getAttribute('startLeft')) < xPos) &&   
            ((getAttribute(
'startTop')) < yPos) &&   
            ((getAttribute(
'startLeft'+ getAttribute('startWidth')) > xPos) &&   
            ((getAttribute(
'startTop')  + getAttribute('startHeight')) > yPos)){   
  
            
/**//*  
            our target is inside of our container so save the container into  
            the activeCont variable and then exit the loop since we no longer  
            need to check the rest of the containers  
            
*/  
            activeCont 
= dragConts[i];   
  
            
// exit the for loop   
            break;   
        }   
      }   
    }   
  
    
// Our target object is in one of our containers.  Check to see where our div belongs   
    if(activeCont){   
      
// beforeNode will hold the first node AFTER where our div belongs   
      var beforeNode = null;   
  
      
// loop through each child node (skipping text nodes).   
      for(var i=activeCont.childNodes.length-1; i>=0; i--){   
        
with(activeCont.childNodes[i]){   
          
if(nodeName=='#text'continue;   
  
            
// if the current item is "After" the item being dragged   
            if(   
              curTarget 
!= activeCont.childNodes[i] &&   
              ((getAttribute(
'startLeft'+ getAttribute('startWidth')) > xPos) &&   
              ((getAttribute(
'startTop')  + getAttribute('startHeight')) > yPos)){   
                beforeNode 
= activeCont.childNodes[i];   
        }   
      }   
    }   
  
    
// the item being dragged belongs before another item   
    if(beforeNode){   
      
if(beforeNode!=curTarget.nextSibling){   
        activeCont.insertBefore(curTarget, beforeNode);   
      }   
  
    
// the item being dragged belongs at the end of the current container   
    } else {   
      
if((curTarget.nextSibling) || (curTarget.parentNode!=activeCont)){   
        activeCont.appendChild(curTarget);   
      }   
    }   
  
    
// make our drag item visible   
    if(curTarget.style.display!=''){   
      curTarget.style.display  
= '';   
    }   
  } 
else {   
  
    
// our drag item is not in a container, so hide it.   
    if(curTarget.style.display!='none'){   
      curTarget.style.display  
= 'none';   
    }   
  }   
}   
  
  
// track the current mouse state so we can compare against it next time   
  lMouseState = iMouseDown;   
  
  
// mouseMove target   
  lastTarget  = target;   
  
  
// track the current mouse state so we can compare against it next time   
  lMouseState = iMouseDown;   
  
  
// this helps prevent items on the page from being highlighted while dragging   
  return false;   
}   
  
function mouseUp(ev){   
  
if(curTarget){   
    
// hide our helper object - it is no longer needed   
    dragHelper.style.display = 'none';   
  
    
// if the drag item is invisible put it back where it was before moving it   
    if(curTarget.style.display == 'none'){   
      
if(rootSibling){   
        rootParent.insertBefore(curTarget, rootSibling);   
      } 
else {   
        rootParent.appendChild(curTarget);   
      }   
    }   
  
    
// make sure the drag item is visible   
    curTarget.style.display = '';   
  }   
  curTarget  
= null;   
  iMouseDown 
= false;   
}   
  
function mouseDown(){   
  iMouseDown 
= true;   
  
if(lastTarget){   
    
return false;   
  }   
}   
  
document.onmousemove 
= mouseMove;   
document.onmousedown 
= mouseDown;   
document.onmouseup 
= mouseUp;   
  
window.onload 
= function(){   
  
// Create our helper object that will show the item while dragging   
  dragHelper = document.createElement('DIV');   
  dragHelper.style.cssText 
= 'position:absolute;display:none;';   
           
  CreateDragContainer(   
    document.getElementById(
'DragContainer1'),   
    document.getElementById(
'DragContainer2'),   
    document.getElementById(
'DragContainer3')   
  );   
  
  document.body.appendChild(dragHelper);   
}
代码
<!-- the mouse over and dragging class are defined on each item -->  
<div class ="DragContainer" id="DragContainer1">  
  
<div class="DragBox" id="Item1" overClass="OverDragBox" dragClass="DragDragBox">Item #1</div>  
  
<div class="DragBox" id="Item2" overClass="OverDragBox" dragClass="DragDragBox">Item #2</div>  
  
<div class="DragBox" id="Item3" overClass="OverDragBox" dragClass="DragDragBox">Item #3</div>  
  
<div class="DragBox" id="Item4" overClass="OverDragBox" dragClass="DragDragBox">Item #4</div>    
</div>  
<div class="DragContainer" id="DragContainer2" >  
  
<div class="DragBox" id="Item5" overClass="OverDragBox" dragClass="DragDragBox">Item #5</div>  
  
<div class="DragBox" id="Item6" overClass="OverDragBox" dragClass="DragDragBox">Item #6</div>  
  
<div class="DragBox" id="Item7" overClass="OverDragBox" dragClass="DragDragBox">Item #7</div>  
  
<div class="DragBox" id="Item8" overClass="OverDragBox" dragClass="DragDragBox">Item #8</div>  
</div>  
<div class="DragContainer" id="DragContainer3">  
  
<div class="DragBox" id="Item9" overClass="OverDragBox" dragClass="DragDragBox">Item #9</div>  
  
<div class="DragBox" id="Item10" overClass="OverDragBox" dragClass="DragDragBox">Item #10</div>  
  
<div class="DragBox" id="Item11" overClass="OverDragBox" dragClass="DragDragBox">Item #11</div>  
  
<div class="DragBox" id="Item12" overClass="OverDragBox" dragClass="DragDragBox">Item #12</div>  
</div>  

关于作者

Mark Kahn是一位Web Developer、DBA。可以通过这个网址跟他联系:http://www.jslibrary.org

原文链接:http://www.webreference.com/programming/javascript/mk/column2/3.html
译文链接:http://www.blogjava.net/flyingis/archive/2006/10/15/75277.html

发表于 @ 2007年02月09日 19:26:00|评论(loading...)

新一篇: [转]Memcached深度分析 | 旧一篇: PHP实现常见排序算法

用户操作
[即时聊天] [发私信] [加为好友]
heiyeluren
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
heiyeluren的公告

联系方式:


访问统计: free hit counter code
FeedSky订阅:
FeedSky订阅
文章分类
收藏
    ::eYou::
    kevin world
    lewis - 老吕
    qyb - BT的花
    Realzay的blog
    叶金荣
    天堂地狱鬼-dulao5's Blog
    沙漠之周
    狐狸糊涂
    老韩
    與子觀化
    鞋门
    ::Yahoo::
    glemir’s blog
    happy_fish - 分布式文件系统FastDFS
    LinZi's Blog
    Rainx
    stauren
    互联网,请记住我 - 162同学的技术博客
    冰的河
    北冥之鱼-张彪同学
    天韵之星
    小蚂蚁同学滴测试博客
    随网之舞 - kaven的DHTML博客
    风雪之隅
    ::朋友::
    【推荐】中文分类网
    DDR的博客
    kevin world
    miky
    PHPCup.cn论坛
    俺兄弟的blog
    冰河的技术博客:心随风动
    好旅网
    小少的技术博客
    无尘居
    晋陵路人的Blog
    李天华同学滴技术博客
    沙狐部落
    轻量级的editor
    ::网友::
    blankyao同学
    Code & Stock.
    Hello, Willko
    LionD8的Blog
    magiclab.cn
    MooPHP - 轻量级PHP框架
    Phzzy
    Xhttpd.cn
    张贺同学的博客
    技术大牛老余的博客
    抚琴居
    旋木木同学滴博客
    流水孟春
    矛盾网
    程序人生
    邢红瑞的blog
    阿健的博客
    :PHP博客:
    .: Easy style :.
    [琴剑楼]
    CoolCode.cn
    Haohappy的Blog
    Hightman
    iwind的blog
    Javascript开发站
    JD Space
    Nio's Weblog
    Open Source PHP
    PHP面对对象
    SourceForge.net
    trip的专栏
    UGIA.cn
    windix's blog
    Windix's Weblog
    一个藏袍
    俊麟 Michael`s blog
    偶然的blog
    刘敏的blog
    大龄青年的Blog
    廖宇雷的blog
    懒猫开始新生活blog
    某人的栖息地
    王春生的博客
    神仙
    :牛人blog:
    DBA notes
    http://blog.csdn.net/tingya/
    侯捷网站
    孟岩
    搜索引擎研究
    方舟
    王咏刚的BLOG
    竹笋炒肉
    荣耀
    车东[Blog^2]
    透明思考
    陈硕的Blog
    DHTML
    DHTMLGoodies
    FCKEditor
    Google Code
    Google Web Toolkit
    HTML Goodies
    HTML.it
    HTMLAre
    HTMLdog
    JavaScript Kit
    jQuery
    KindEditor
    Prototype
    TinyMCE
    W3 Schools
    Yahoo JavaScript Developer Center
    Yahoo! Developer Network
    Yahoo! UI Library (YUI)
    网页设计师Web标准
    Java国内站
    ChinaJavaWorld.com技术论坛
    IBM developerWorks 中国: Java
    Java中文站
    Java开源大全
    Java爱好者
    JR - Java翻译站
    J道-JDON
    Matrix: 与Java共舞
    中国Java开发网
    中文java技术网
    PHP国内站点
    CSDN PHP论坛
    Discuz!
    FleaPHP
    Google--PHP用户组
    IBM DeveloperWorks
    JavsScript技术讨论
    Nirvana Studio
    OpenPHP.cn
    PHPChina
    TiM Club
    中文 PFC 1.0 手册--PHP5的开发包
    中文 PFC 1.0 手册--PHP5的开发包
    中文PHP网
    太平洋--PHP开发区
    爱MySQL
    超越PHP
    PHP国外站点
    ADOdb
    Agavi Framework
    Cake PHP
    MySQL Performance Blog
    MySQL Performance Blog
    Nonaweb
    PEAR
    PECL
    PECL Windows
    PHP Builder
    PHP Classes
    PHP Classes
    PHP New Download
    PHP Security Consortium
    php.MVC
    php.MVC
    PHPkitchen(OO & MVC)
    phpPatterns
    PHP国外图书下载
    smart template
    Smarty
    SourceForge.net
    Symfony Framework
    Zend
    Zend Framework
    Unix C/C++
    Free Gentux
    周立发的blog(Linux C)
    Unix/Linux
    BSD智库
    ChinaUnix
    FreeBSDChina
    FreeLAMP
    IBM开发者Linux专区
    Linux Byte
    LinuxKit
    LinuxTS
    Linux伊甸园
    Linux技术中坚站
    Linux非常空间
    Love Unix
    NetBSD&OpenBSD中文用户组
    NetBSD中国社区
    Oracle中国用户讨论组
    OurLinux
    Unix中文
    Unix中文
    Unix中文宝库
    中国Linux公社
    中国Unix用户技术论坛
    中文FreeBSD用户组
    永远的Unix
    炎黄角马
    程序设计
    CSDN
    IBM开发者中心
    Microsoft TechNet: 主页
    MSDN 中文网站
    PHP中文站
    Sun技术社区
    中国IT认证实验室--企业应用技术
    中国协议分析网
    喜悦国际村
    太平洋电脑网---开发特区
    实用网站
    veBook(国外大量免费图书下载网站)
    Whois.net
    中国Web信息博物馆
    中国互联网络信息中心whois查询
    服务器系统信息查看
    网络安全
    AnySide.com
    CGI Secutiry
    K-OTik Security Monitoring
    Linux Security
    Packet Storm Security
    PHP Secure
    RFC中文文档索引
    Safemode.org
    SecuriTeam.com
    Security Corporation
    SecurityFocus
    SecurityTracker
    Zone-h (区域黑客,每天公布各国被黑的网站)
    中华安全网
    中国信息安全组织
    国家计算机网络应急处理中心
    安全天使
    安全焦点
    幻影旅团
    绿盟科技
    网络安全评估中心(cnns )
    在线手册
    Apache2.0中文文档
    Beyond Linux From Scratch
    Debian参考手册
    FreeBSD Porter 手册
    FreeBSD使用手册
    Linux C函数中文参考手册
    MySQL 4.1.0 中文参考手册
    NetBSD在线手册
    OpenBSD在线FAQ
    PHP ADODB 1.99版手册中文翻译(Tripc)
    PHP中文手册(国内)
    PHP中文手册(国外)
    PostgreSQL中文文档
    Red Hat Linux 9入门指南
    Red Hat Linux 9安装指南
    Red Hat Linux 9定制手册
    中国OSS技术手册中心
    技术文档手册中心-ChinaUnix
    存档
    Csdn Blog version 3.1a
    Copyright © heiyeluren