拖动Html元素集合 Drag and Drop any item


Posted in Javascript onDecember 22, 2006

<style content="text/css">
li {
  MARGIN-BOTTOM: 10px
}
ul {
  MARGIN-TOP: 5px
}
.DragContainer {
  BORDER-RIGHT: #669999 2px solid; PADDING-RIGHT: 5px; BORDER-TOP: #669999 2px solid; PADDING-LEFT: 5px; FLOAT: left; PADDING-BOTTOM: 0px; MARGIN: 3px; BORDER-LEFT: #669999 2px solid; WIDTH: 100px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 2px solid
}
.OverDragContainer {
  BORDER-RIGHT: #669999 2px solid; PADDING-RIGHT: 5px; BORDER-TOP: #669999 2px solid; PADDING-LEFT: 5px; FLOAT: left; PADDING-BOTTOM: 0px; MARGIN: 3px; BORDER-LEFT: #669999 2px solid; WIDTH: 100px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 2px solid
}
.OverDragContainer {
  BACKGROUND-COLOR: #eee
}
.DragBox {
  BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.OverDragBox {
  BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.DragDragBox {
  BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.miniDragBox {
  BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 10px; MARGIN-BOTTOM: 5px; PADDING-BOTTOM: 2px; BORDER-LEFT: #000 1px solid; WIDTH: 94px; CURSOR: pointer; PADDING-TOP: 2px; BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: verdana, tahoma, arial; BACKGROUND-COLOR: #eee
}
.OverDragBox {
  BACKGROUND-COLOR: #ffff99
}
.DragDragBox {
  BACKGROUND-COLOR: #ffff99
}
.DragDragBox {
  FILTER: alpha(opacity=50); BACKGROUND-COLOR: #ff99cc
}
LEGEND {
  FONT-WEIGHT: bold; FONT-SIZE: 12px; COLOR: #666699; FONT-FAMILY: verdana, tahoma, arial
}
FIELDSET {
  PADDING-RIGHT: 3px; PADDING-LEFT: 3px; PADDING-BOTTOM: 3px; PADDING-TOP: 3px
}
.History {
  FONT-SIZE: 10px; OVERFLOW: auto; WIDTH: 100%; FONT-FAMILY: verdana, tahoma, arial; HEIGHT: 82px
}
#DragContainer8 {
  BORDER-RIGHT: #669999 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: #669999 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 0px; BORDER-LEFT: #669999 1px solid; WIDTH: 110px; PADDING-TOP: 5px; BORDER-BOTTOM: #669999 1px solid; HEIGHT: 110px
}
.miniDragBox {
  FLOAT: left; MARGIN: 0px 5px 5px 0px; WIDTH: 20px; HEIGHT: 20px
}
pre{border:1 solid #CCC;background-color:#F8F8F0;padding:10px;}
</style>
<script content="text/javascript">

// 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 nodes...skip these
      if(cObj.childNodes[j].nodeName=='#text') continue;

      cObj.childNodes[j].setAttribute('DragObj', cDrag);
    }
  }
}

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 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 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 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);
}

</script>

<!--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>

Javascript 相关文章推荐
TextArea 控件的最大长度问题(js json)
Dec 16 Javascript
js 创建快捷方式的代码(fso)
Nov 19 Javascript
js动态加载以及确定加载完成的代码
Jul 31 Javascript
jquery ui对话框实例代码
May 10 Javascript
jQuery之按钮组件的深入解析
Jun 19 Javascript
js实现快速分享功能(你的文章分享工具)
Jun 25 Javascript
jquery图片放大功能简单实现
Aug 01 Javascript
jquery实现兼容浏览器的图片上传本地预览功能
Oct 14 Javascript
javascript中动态加载js文件多种解决办法总结
Nov 15 Javascript
Easyui form combobox省市区三级联动
Jan 13 Javascript
微信小程序排坑指南详解
May 23 Javascript
vue中使用element-ui进行表单验证的实例代码
Jun 22 Javascript
拖动一个HTML元素
Dec 22 #Javascript
JavaScript中Array 对象相关的几个方法
Dec 22 #Javascript
JavaScript事件列表解说
Dec 22 #Javascript
改进:论坛UBB代码自动插入方式
Dec 22 #Javascript
用javascript获取地址栏参数
Dec 22 #Javascript
在IE下:float属性会影响offsetTop的取值
Dec 22 #Javascript
Javascript实现的分页函数
Dec 22 #Javascript
You might like
php AJAX实例根据邮编自动完成地址信息
2008/11/23 PHP
探讨如何把session存入数据库
2013/06/07 PHP
html静态页面调用php文件的方法
2014/11/13 PHP
thinkphp特殊标签用法概述
2014/11/24 PHP
PHP中常用的三种设计模式详解【单例模式、工厂模式、观察者模式】
2019/06/14 PHP
Nigma vs Alliance BO5 第二场2.14
2021/03/10 DOTA
javaScript矢量图表库-gRaphael几行代码实现精美的条形图/饼图/点图/曲线图
2013/01/09 Javascript
放弃用你的InnerHTML来输出HTML吧 jQuery Tmpl不详细讲解
2013/04/20 Javascript
React.js入门实例教程之创建hello world 的5种方式
2016/05/11 Javascript
AngularJS通过$location获取及改变当前页面的URL
2016/09/23 Javascript
DOM 事件的深入浅出(二)
2016/12/05 Javascript
微信小程序实现弹出菜单
2018/07/19 Javascript
Vue 中的受控与非受控组件的实现
2018/12/17 Javascript
vue实现微信获取用户信息的方法
2019/03/21 Javascript
解决layui动态添加的元素click等事件触发不了的问题
2019/09/20 Javascript
浅谈layui里的上传控件问题
2019/09/26 Javascript
在Layui中实现开关按钮的效果实例
2019/09/29 Javascript
element-ui 本地化使用教程详解
2019/10/28 Javascript
python基础教程之实现石头剪刀布游戏示例
2014/02/11 Python
测试、预发布后用python检测网页是否有日常链接
2014/06/03 Python
Python实现的监测服务器硬盘使用率脚本分享
2014/11/07 Python
用Python制作简单的朴素基数估计器的教程
2015/04/01 Python
python中json格式数据输出的简单实现方法
2016/10/31 Python
python如何以表格形式打印输出的方法示例
2019/06/21 Python
tensorflow 查看梯度方式
2020/02/04 Python
Python之关于类变量的两种赋值区别详解
2020/03/12 Python
python如何实现word批量转HTML
2020/09/30 Python
HTML5中使用postMessage实现Ajax跨域请求的方法
2016/04/19 HTML / CSS
新西兰床上用品和家居用品购物网站:Adairs
2018/04/27 全球购物
俄罗斯香水和化妆品在线商店:Aroma-butik
2020/02/28 全球购物
Yahoo-PHP面试题2
2014/12/06 面试题
会计专业个人自我鉴定
2014/03/21 职场文书
服务员岗位职责范本
2015/04/09 职场文书
圣诞晚会主持词开场白
2015/05/28 职场文书
计算机实训心得体会
2016/01/14 职场文书
HTML中table表格拆分合并(colspan、rowspan)
2021/04/07 HTML / CSS