• 仿iGoogle自定义首页模块拖拽


    关于js拖拽早已是老生常谈,网上一搜一大坨,但是有很多并不是很完善,或者兼容性不够,或者功能不全,并且这样的东西还是自己写的好用。我打算在(一)中主要对js拖拽功能的注意点进行罗列,力求简单;在(二)中利用(一)的拖拽去实现类似google个性化首页的拖拽模块功能。

      首先贴上完整code(IE/FF)

    代码
    <!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" >
    <head>
    <title></title>
    <script type="text/javascript">
    var Common = {
    getEvent:
    function() {//ie/ff
    if (document.all) {
    return window.event;
    }
    func
    = getEvent.caller;
    while (func != null) {
    var arg0 = func.arguments[0];
    if (arg0) {
    if ((arg0.constructor == Event || arg0.constructor == MouseEvent) || (typeof (arg0) == "object" && arg0.preventDefault && arg0.stopPropagation)) {
    return arg0;
    }
    }
    func
    = func.caller;
    }
    return null;
    },
    getMousePos:
    function(ev) {
    if (!ev) {
    ev
    = this.getEvent();
    }
    if (ev.pageX || ev.pageY) {
    return {
    x: ev.pageX,
    y: ev.pageY
    };
    }

    if (document.documentElement && document.documentElement.scrollTop) {
    return {
    x: ev.clientX
    + document.documentElement.scrollLeft - document.documentElement.clientLeft,
    y: ev.clientY
    + document.documentElement.scrollTop - document.documentElement.clientTop
    };
    }
    else if (document.body) {
    return {
    x: ev.clientX
    + document.body.scrollLeft - document.body.clientLeft,
    y: ev.clientY
    + document.body.scrollTop - document.body.clientTop
    };
    }
    },
    getItself:
    function(id) {
    return "string" == typeof id ? document.getElementById(id) : id;
    },
    getViewportSize: { w: (window.innerWidth)
    ? window.innerWidth : (document.documentElement && document.documentElement.clientWidth) ? document.documentElement.clientWidth : document.body.offsetWidth, h: (window.innerHeight) ? window.innerHeight : (document.documentElement && document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.offsetHeight },
    isIE: document.all
    ? true : false,
    setOuterHtml:
    function(obj, html) {
    var Objrange = document.createRange();
    obj.innerHTML
    = html;
    Objrange.selectNodeContents(obj);
    var frag = Objrange.extractContents();
    obj.parentNode.insertBefore(frag, obj);
    obj.parentNode.removeChild(obj);
    }
    }

    ///------------------------------------------------------------------------------------------------------
    var Class = {
    create:
    function() {
    return function() { this.init.apply(this, arguments); }
    }
    }
    var Drag = Class.create();
    Drag.prototype
    = {
    init:
    function(titleBar, dragDiv, Options) {
    //设置点击是否透明,默认不透明
    titleBar = Common.getItself(titleBar);
    dragDiv
    = Common.getItself(dragDiv);
    this.dragArea = { maxLeft: 0, maxRight: Common.getViewportSize.w - dragDiv.offsetWidth - 2, maxTop: 0, maxBottom: Common.getViewportSize.h - dragDiv.offsetHeight - 2 };
    if (Options) {
    this.opacity = Options.opacity ? (isNaN(parseInt(Options.opacity)) ? 100 : parseInt(Options.opacity)) : 100;
    this.keepOrigin = Options.keepOrigin ? ((Options.keepOrigin == true || Options.keepOrigin == false) ? Options.keepOrigin : false) : false;
    if (this.keepOrigin) { this.opacity = 50; }
    if (Options.area) {
    if (Options.area.left && !isNaN(parseInt(Options.area.left))) { this.dragArea.maxLeft = Options.area.left };
    if (Options.area.right && !isNaN(parseInt(Options.area.right))) { this.dragArea.maxRight = Options.area.right };
    if (Options.area.top && !isNaN(parseInt(Options.area.top))) { this.dragArea.maxTop = Options.area.top };
    if (Options.area.bottom && !isNaN(parseInt(Options.area.bottom))) { this.dragArea.maxBottom = Options.area.bottom };
    }
    }
    else {
    this.opacity = 100, this.keepOrigin = false;
    }
    this.originDragDiv = null;
    this.tmpX = 0;
    this.tmpY = 0;
    this.moveable = false;

    var dragObj = this;

    titleBar.onmousedown
    = function(e) {
    var ev = e || window.event || Common.getEvent();
    //只允许通过鼠标左键进行拖拽,IE鼠标左键为1 FireFox为0
    if (Common.isIE && ev.button == 1 || !Common.isIE && ev.button == 0) {
    }
    else {
    return false;
    }

    if (dragObj.keepOrigin) {
    dragObj.originDragDiv
    = document.createElement("div");
    dragObj.originDragDiv.style.cssText
    = dragDiv.style.cssText;
    dragObj.originDragDiv.style.width
    = dragDiv.offsetWidth;
    dragObj.originDragDiv.style.height
    = dragDiv.offsetHeight;
    dragObj.originDragDiv.innerHTML
    = dragDiv.innerHTML;
    dragDiv.parentNode.appendChild(dragObj.originDragDiv);
    }

    dragObj.moveable
    = true;
    dragDiv.style.zIndex
    = dragObj.GetZindex() + 1;
    var downPos = Common.getMousePos(ev);
    dragObj.tmpX
    = downPos.x - dragDiv.offsetLeft;
    dragObj.tmpY
    = downPos.y - dragDiv.offsetTop;

    titleBar.style.cursor
    = "move";
    if (Common.isIE) {
    dragDiv.setCapture();
    }
    else {
    window.captureEvents(Event.mousemove);
    }

    dragObj.SetOpacity(dragDiv, dragObj.opacity);

    //FireFox 去除容器内拖拽图片问题
    if (ev.preventDefault) {
    ev.preventDefault();
    ev.stopPropagation();
    }

    document.onmousemove
    = function(e) {
    if (dragObj.moveable) {
    var ev = e || window.event || Common.getEvent();
    //IE 去除容器内拖拽图片问题
    if (document.all) //IE
    {
    ev.returnValue
    = false;
    }

    var movePos = Common.getMousePos(ev);
    dragDiv.style.left
    = Math.max(Math.min(movePos.x - dragObj.tmpX, dragObj.dragArea.maxRight), dragObj.dragArea.maxLeft) + "px";
    dragDiv.style.top
    = Math.max(Math.min(movePos.y - dragObj.tmpY, dragObj.dragArea.maxBottom), dragObj.dragArea.maxTop) + "px";

    }
    };

    document.onmouseup
    = function() {
    if (dragObj.keepOrigin) {
    if (Common.isIE) {
    dragObj.originDragDiv.outerHTML
    = "";
    }
    else {
    Common.setOuterHtml(dragObj.originDragDiv,
    "");
    }
    }
    if (dragObj.moveable) {
    if (Common.isIE) {
    dragDiv.releaseCapture();
    }
    else {
    window.releaseEvents(dragDiv.mousemove);
    }
    dragObj.SetOpacity(dragDiv,
    100);
    titleBar.style.cursor
    = "default";
    dragObj.moveable
    = false;
    dragObj.tmpX
    = 0;
    dragObj.tmpY
    = 0;
    }
    };
    }
    },
    SetOpacity:
    function(dragDiv, n) {
    if (Common.isIE) {
    dragDiv.filters.alpha.opacity
    = n;
    }
    else {
    dragDiv.style.opacity
    = n / 100;
    }

    },
    GetZindex:
    function() {
    var maxZindex = 0;
    var divs = document.getElementsByTagName("div");
    for (z = 0; z < divs.length; z++) {
    maxZindex
    = Math.max(maxZindex, divs[z].style.zIndex);
    }
    return maxZindex;
    }
    }

    window.onload
    = function() {
    new Drag("dragDiv", "dragDiv", { opacity: 100, keepOrigin: true }); //, area: { left: 50, right: 500, top: 100, bottom: 400}
    }
      

    </script>

    </head>
    <body>
    <div id="dragDiv" style="position:absolute; background-color:#FFFFFF;border:solid 1px #849BCA;200px;left:10px;top:10px;filter:alpha(opacity=100);opacity:1;">
    <table cellpadding="0" cellspacing="0" border="0" style="100%;border-collapse:collapse; ">
    <tr id="titleBar" style="height:22px; text-align:left; background-color:#547BC9;color:White; padding:3px;">
    <th align="left" unselectable="on" >Title</th>
    </tr>
    <tr style="height:130px;padding:3px;" align="left" valign="top" unselectable="on">
    <td><img src="http://images.cnblogs.com/logo_small.gif" alt="pic for drag" /> Content...</td> <!---->
    </tr>
    </table>
    </div>
    <div style="position:absolute; font-family:Tahoma;border:solid 1px #849BCA; background-color:#AAAAAA;200px;height:100px;left:210px;top:210px;filter:alpha(opacity=100);opacity:1; z-index:999">Are you able to cover me?</div>
    </body>
    </html>

    对Drag的使用:在window.onload中,必填参数是titleBar和dragDiv,后者是要拖拽的容器,前者是拖拽容器的可拖拽部位,譬如经常遇到的通过标题栏拖动整个DIV,则titleBar即为改标题栏。而{ opacity: 100, keepOrigin: true , area: { left: 50, right: 500, top: 100, bottom: 400}} 是可选参数,用于扩展功能,opacity设置透明度,keepOrigin设置拖拽过程中是否保留原来拖拽容器,area设置拖拽范围。

    1. 拖拽的基本原理:当mousedown时记下鼠标点击位置离拖拽容器左边沿的距离和上边沿的距离,即tmpX,tmpY;mousemove时通过定位拖拽容器的style.left/style.top,使拖拽容器进行移动,定位到哪里则由刚刚的tmpX/tmpY和当前鼠标所在位置计算得出;mouseup时,结束移动。
    2. “var dragObj = this;” 这句是为了在mousedown/mouseup/mousemove事件里对Drag对象的相关变量进行引用。因为在mousedown里的this是titleBar,mouseup/mousemove里的this是document.
    3. 当拖拽速度太快导致鼠标移出拖拽容器,而拖拽容器位置未变,用document.mousemove代替titleBar.mousemove即可。
    4. 设置拖拽容器可拖拽的范围,若未设置,则默认为当前窗口可视范围。Note:在设置范围的时候使用Math.max/min来处理,而不是用If语句判断,用后者的话会导致快速拖拽时未达到容许范围边沿即停止的状况。
    5. 当拖拽过程中,可设置是否保留原来拖拽容器,当拖拽结束,隐藏原来容器,默认不保留。
    6. 当拖拽时,可设置拖拽的容器是否透明及透明度多少,默认不透明。但若拖拽过程中设置保留原来拖拽容器,即keepOrigin: true,则设置透明度为50%。
    7. 使右键、鼠标中键等不能拖动,仅左键单击可以拖动。Note:IE鼠标左键为event.Button=1 FireFox为event.Button=0.
    8. 解决如果点击在图片上无法拖拽的问题:非常杯具的是IE通过ev.returnValue = false来防止图片的事件,注意是放在document.onmousemove中,而FireFox通过ev.preventDefault();ev.stopPropagation(); 但是是放在titleBar的mousedown事件中。
    9. 有一种情况,当浏览器窗口不是最大化的时候,你希望当鼠标在浏览器外移动时,浏览器里的拖拽容器仍然移动,这时就要使用鼠标事件捕获,IE中相应的是dragDiv.setCapture();与dragDiv.releaseCapture(); FF中是window.captureEvents(Event.mousemove);与window.releaseEvents(dragDiv.mousemove) 。
    10. 确保每次拖拽时拖拽容器的zindex都不会被其他块元素覆盖。

    点击下载

    首先这篇文章是基于 再谈js拖拽(一) code基础上的,进行改动实现的仿iGoogle自定义首页模块拖拽功能。将code贴上,你也可在下方进行下载。code未免枯燥,我将尽量用文字描述思路及注意点,所以即便你不看code也能根据文字翻译成你的code。

    代码
    1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    2  <html xmlns="http://www.w3.org/1999/xhtml" >
    3  <head>
    4 <title></title>
    5 <script type="text/javascript">
    6 var Common = {
    7 getEvent: function() {//ie/ff
    8   if (document.all) {
    9 return window.event;
    10 }
    11 func = getEvent.caller;
    12 while (func != null) {
    13 var arg0 = func.arguments[0];
    14 if (arg0) {
    15 if ((arg0.constructor == Event || arg0.constructor == MouseEvent) || (typeof (arg0) == "object" && arg0.preventDefault && arg0.stopPropagation)) {
    16 return arg0;
    17 }
    18 }
    19 func = func.caller;
    20 }
    21 return null;
    22 },
    23 getMousePos: function(ev) {
    24 if (!ev) {
    25 ev = this.getEvent();
    26 }
    27 if (ev.pageX || ev.pageY) {
    28 return {
    29 x: ev.pageX,
    30 y: ev.pageY
    31 };
    32 }
    33
    34 if (document.documentElement && document.documentElement.scrollTop) {
    35 return {
    36 x: ev.clientX + document.documentElement.scrollLeft - document.documentElement.clientLeft,
    37 y: ev.clientY + document.documentElement.scrollTop - document.documentElement.clientTop
    38 };
    39 }
    40 else if (document.body) {
    41 return {
    42 x: ev.clientX + document.body.scrollLeft - document.body.clientLeft,
    43 y: ev.clientY + document.body.scrollTop - document.body.clientTop
    44 };
    45 }
    46 },
    47 getElementPos: function(el) {
    48 el = this.getItself(el);
    49 var _x = 0, _y = 0;
    50 do {
    51 _x += el.offsetLeft;
    52 _y += el.offsetTop;
    53 } while (el = el.offsetParent);
    54 return { x: _x, y: _y };
    55 },
    56 getItself: function(id) {
    57 return "string" == typeof id ? document.getElementById(id) : id;
    58 },
    59 getViewportSize: { w: (window.innerWidth) ? window.innerWidth : (document.documentElement && document.documentElement.clientWidth) ? document.documentElement.clientWidth : (document.body?document.body.offsetWidth:0), h: (window.innerHeight) ? window.innerHeight : (document.documentElement && document.documentElement.clientHeight) ? document.documentElement.clientHeight : (document.body ? document.body.offsetHeight : 0) },
    60 isIE: document.all ? true : false,
    61 setOuterHtml: function(obj, html) {
    62 var Objrange = document.createRange();
    63 obj.innerHTML = html;
    64 Objrange.selectNodeContents(obj);
    65 var frag = Objrange.extractContents();
    66 obj.parentNode.insertBefore(frag, obj);
    67 obj.parentNode.removeChild(obj);
    68 },
    69 firstChild: function(parentObj, tagName) {
    70 if (Common.isIE) {
    71 return parentObj.firstChild;
    72 }
    73 else {
    74 var arr = parentObj.getElementsByTagName(tagName);
    75 return arr[0];
    76 }
    77 },
    78 lastChild: function(parentObj, tagName) {
    79 if (Common.isIE) {
    80 return parentObj.lastChild;
    81 }
    82 else {
    83 var arr = parentObj.getElementsByTagName(tagName);
    84 return arr[arr.length - 1];
    85 }
    86 },
    87 setCookie: function(name, value) {
    88 document.cookie = name + "=" + value;
    89 },
    90 getCookie: function(name) {
    91 var strCookie = document.cookie;
    92 var arrCookie = strCookie.split("; ");
    93 for (var i = 0; i < arrCookie.length; i++) {
    94 var arr = arrCookie[i].split("=");
    95 if (!arr[1]) {
    96 return "";
    97 }
    98 if (arr[0] == name) {
    99 return arr[1];
    100 }
    101 }
    102 return "";
    103 },
    104 delCookie: function(name) {
    105 var exp = new Date();
    106 exp.setTime(exp.getTime() - 1);
    107 var cval = this.getCookie(name);
    108 if (cval != null) document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
    109 }
    110 }
    111
    112 ///------------------------------------------------------------------------------------------------------
    113   var Class = {
    114 create: function() {
    115 return function() { this.init.apply(this, arguments); }
    116 }
    117 }
    118 var Drag = Class.create();
    119 Drag.prototype = {
    120 init: function(titleBar, dragDiv, Options) {
    121 //设置点击是否透明,默认透明60%
    122   titleBar = Common.getItself(titleBar);
    123 dragDiv = Common.getItself(dragDiv);
    124 this.dragArea = { maxLeft: -9999, maxRight: 9999, maxTop: -9999, maxBottom: 9999 };
    125 if (Options) {
    126 this.opacity = Options.opacity ? (isNaN(parseInt(Options.opacity)) ? 100 : parseInt(Options.opacity)) : 100;
    127 if (Options.area) {
    128 if (Options.area.left && !isNaN(parseInt(Options.area.left))) { this.dragArea.maxLeft = Options.area.left };
    129 if (Options.area.right && !isNaN(parseInt(Options.area.right))) { this.dragArea.maxRight = Options.area.right };
    130 if (Options.area.top && !isNaN(parseInt(Options.area.top))) { this.dragArea.maxTop = Options.area.top };
    131 if (Options.area.bottom && !isNaN(parseInt(Options.area.bottom))) { this.dragArea.maxBottom = Options.area.bottom };
    132 }
    133 }
    134 else {
    135 this.opacity = 60;
    136 }
    137 this.originDragDiv = null;
    138 this.tmpX = 0;
    139 this.tmpY = 0;
    140 this.moveable = false;
    141 this.dragArray = [];
    142
    143 var dragObj = this;
    144 var dragTbl = document.getElementById("dragTable");
    145
    146 titleBar.onmousedown = function(e) {
    147 var ev = e || window.event || Common.getEvent();
    148 //只允许通过鼠标左键进行拖拽,IE鼠标左键为1 FireFox为0
    149   if (Common.isIE && ev.button == 1 || !Common.isIE && ev.button == ground-color: #f5f5f5; color: #000000;">0) {
    150 }
    151 else {
    152 return false;
    153 }
    154
    155
    156 //处理特殊情况:在最上/下面MOVE时不碰到现有DIV的情况下,又回到起始拖拽的列最上/下方
    157   var tmpColId;
    158 for (c = 0; c < dragTbl.rows[0].cells.length; c++) {
    159 for (k = 0; k < dragTbl.rows[0].cells[c].getElementsByTagName("DIV").length; k++) {
    160 if (dragDiv.id == dragTbl.rows[0].cells[c].getElementsByTagName("DIV")[k].id) {
    161 tmpColId = c;
    162 break;
    163 }
    164 }
    165 }
    166 var tmpPosFirstChild = Common.getElementPos(Common.firstChild(dragTbl.rows[0].cells[tmpColId], "DIV"));
    167 var tmpPosLastChild = Common.getElementPos(Common.lastChild(dragTbl.rows[0].cells[tmpColId], "DIV"));
    168 var tmpObj = { colId: tmpColId, firstChildUp: tmpPosFirstChild.y, lastChildDown: tmpPosLastChild.y + Common.lastChild(dragTbl.rows[0].cells[tmpColId], "DIV").offsetHeight };
    169
    170 //保存当前可拖拽各容器的所在位置
    171   dragObj.dragArray = dragObj.RegDragsPos();
    172
    173 //插入虚线框
    174   var dashedElement = document.createElement("div");
    175 dashedElement.style.cssText = dragDiv.style.cssText;
    176 dashedElement.style.border = " dashed 2px #aaa ";
    177 dashedElement.style.marginBottom = "6px";
    178 dashedElement.style.width = dragDiv.offsetWidth - 2 * parseInt(dashedElement.style.borderWidth) + "px"; //减去boderWidth使虚线框大小保持与dragDiv一致
    179   dashedElement.style.height = dragDiv.offsetHeight - 2 * parseInt(dashedElement.style.borderWidth) + "px"; //加上px 保证FF正确
    180   dashedElement.style.position = "relative";
    181 if (dragDiv.nextSibling) {
    182 dragDiv.parentNode.insertBefore(dashedElement, dragDiv.nextSibling);
    183 }
    184 else {
    185 dragDiv.parentNode.appendChild(dashedElement);
    186 }
    187 //拖动时变为absolute
    188   dragDiv.style.width = dragDiv.offsetWidth + "px";
    189 dragDiv.style.position = "absolute";
    190
    191
    192 dragObj.moveable = true;
    193 dragDiv.style.zIndex = dragObj.GetZindex() + 1;
    194
    195 var downPos = Common.getMousePos(ev);
    196 dragObj.tmpX = downPos.x - dragDiv.offsetLeft;
    197 dragObj.tmpY = downPos.y - dragDiv.offsetTop;
    198
    199 if (Common.isIE) {
    200 dragDiv.setCapture();
    201 } else {
    202 window.captureEvents(Event.mousemove);
    203 }
    204
    205 dragObj.SetOpacity(dragDiv, dragObj.opacity);
    206
    207 //FireFox 去除容器内拖拽图片问题
    208   if (ev.preventDefault) {
    209 ev.preventDefault();
    210 ev.stopPropagation();
    211 }
    212
    213 document.onmousemove = function(e) {
    214 if (dragObj.moveable) {
    215 var ev = e || window.event ||t;background-color: #f5f5f5; color: #000000;"> Common.getEvent();
    216 //IE 去除容器内拖拽图片问题
    217   if (document.all) //IE
    218 {
    219 ev.returnValue = false;
    220 }
    221
    222 var movePos = Common.getMousePos(ev);
    223 dragDiv.style.left = Math.max(Math.min(movePos.x - dragObj.tmpX, dragObj.dragArea.maxRight), dragObj.dragArea.maxLeft) + "px";
    224 dragDiv.style.top = Math.max(Math.min(movePos.y - dragObj.tmpY, dragObj.dragArea.maxBottom), dragObj.dragArea.maxTop) + "px";
    225
    226 var targetDiv = null;
    227 for (var k = 0; k < dragObj.dragArray.length; k++) {
    228 if (dragDiv == dragObj.dragArray[i]) {
    229 continue;
    230 }
    231
    232 if (movePos.x > dragObj.dragArray[k].PosLeft && movePos.x < dragObj.dragArray[k].PosLeft + dragObj.dragArray[k].PosWidth
    233 && movePos.y > dragObj.dragArray[k].PosTop && movePos.y < dragObj.dragArray[k].PosTop + dragObj.dragArray[k].PosHeight
    234 ) {
    235 targetDiv = document.getElementById(dragObj.dragArray[k].DragId);
    236 if (movePos.y < dragObj.dragArray[k].PosTop + dragObj.dragArray[k].PosHeight / 2) {
    237 //往上移
    238 dashedElement.style.width = targetDiv.offsetWidth - 2 * parseInt(dashedElement.style.borderWidth) + "px";
    239 targetDiv.parentNode.insertBefore(dashedElement, targetDiv);
    240 }
    241 else {
    242 //往下移
    243 dashedElement.style.width = targetDiv.offsetWidth - 2 * parseInt(dashedElement.style.borderWidth) + "px";
    244 if (targetDiv.nextSibling) {
    245 targetDiv.parentNode.insertBefore(dashedElement, targetDiv.nextSibling);
    246 }
    247 else {
    248 targetDiv.parentNode.appendChild(dashedElement);
    249 }
    250 }
    251 }
    252 }
    253
    254 for (j = 0; j < dragTbl.rows[0].cells.length; j++) {
    255 var startLeft = Common.getElementPos(dragTbl.rows[0].cells[j]).x;
    256 if (movePos.x > startLeft && movePos.x < startLeft + dragTbl.rows[0].cells[j].offsetWidth) {
    257 ///列无DIV
    258 if (dragTbl.rows[0].cells[j].getElementsByTagName("div").length == 0) {
    259 dashedElement.style.width = dragTbl.rows[0].cells[j].offsetWidth - 2 * parseInt(dashedElement.style.borderWidth) + "px";
    260 dragTbl.rows[0].cells[j].appendChild(dashedElement);
    261 }
    262 else {
    263 var posFirstChild = Common.getElementPos(Common.firstChild(dragTbl.rows[0].cells[j], "DIV"));
    264 var posLastChild = Common.getElementPos(Common.lastChild(dragTbl.rows[0].cells[j], "DIV"));
    265 //处理特殊情况:在最上/下面MOVE时不碰到现有DIV的情况下,又回到起始拖拽的列最上/下方
    266 var tmpUp, tmpDown;
    267 if (tmpObj.colId == j) {
    268 tmpUp = tmpObj.firstChildUp;
    269 tmpDown = tmpObj.lastChildDown;
    270 }
    271 else {
    272 tmpUp = posFirstChild.y;
    273 tmpDown = posLastChild.y + Common.lastChild(dragTbl.rows[0].cells[j], "DIV").offsetHeight;
    274 }
    275
    276 if (movePos.y < tmpUp) {///从最上面插入虚线框
    277 dashedElement.style.width = Common.firstChild(dragTbl.rows[0].cells[j], "DIV").offsetWidth - 2 * parseInt(dashedElement.style.borderWidth) + "px";
    278 dragTbl.rows[0].cells[j].insertBefore(dashedElement, Common.firstChild(dragTbl.rows[0].cells[j], "DIV"));
    279 }
    280 else if (movePos.y > tmpDown) {///从最下面插入虚线框
    281 dashedElement.style.width = Common.lastChild(dragTbl.rows[0].cells[j], "DIV").offsetWidth - 2 * parseInt(dashedElement.style.borderWidth) + "px";
    282 dragTbl.rows[0].cells[j].appendChild(dashedElement);
    283 }
    284
    285 }
    286 }
    287 }
    288 }
    289 };
    290
    291 document.onmouseup = function() {
    292 if (dragObj.moveable) {
    293 if (Common.isIE) {
    294 dragDiv.releaseCapture();
    295 }
    296 else {
    297 window.releaseEvents(dragDiv.mousemove);
    298 }
    299 dragObj.SetOpacity(dragDiv, 100);
    300 dragObj.moveable = false;
    301 dragObj.tmpX = 0;
    302 dragObj.tmpY = 0;
    303
    304 //务必写在此IF内
    305 dragDiv.style.left = "";
    306 dragDiv.style.top = "";
    307 dragDiv.style.width = "";
    308 dragDiv.style.position = "";
    309 dashedElement.parentNode.insertBefore(dragDiv, dashedElement);
    310 dashedElement.parentNode.removeChild(dashedElement);
    311 }
    312
    313 };
    314
    315 }
    316 },
    317 SetOpacity: function(dragDiv, n) {
    318 if (Common.isIE) {
    319 dragDiv.filters.alpha.opacity = n;
    320 }
    321 else {
    322 dragDiv.style.opacity = n / 100;
    323 }
    324
    325 },
    326 GetZindex: function() {
    327 var maxZindex = 0;
    328 var divs = document.getElementsByTagName("div");
    329 for (z = 0; z < divs.length; z++) {
    330 maxZindex = Math.max(maxZindex, divs[z].style.zIndex);
    331 }
    332 return maxZindex;
    333 },
    334 RegDragsPos: function() {
    335 var arrDragDivs = new Array();
    336 var dragTbl = document.getElementById("dragTable");
    337 var tmpDiv, tmpPos;
    338 for (i = 0; i < dragTbl.getElementsByTagName("div").length; i++) {
    339 tmpDiv = dragTbl.getElementsByTagName("div")[i];
    340 if (tmpDiv.className = "dragDiv") {
    341 tmpPos = Common.getElementPos(tmpDiv);
    342 arrDragDivs.push({ DragId: tmpDiv.id, PosLeft: tmpPos.x, PosTop: tmpPos.y, PosWidth: tmpDiv.offsetWidth, PosHeight: tmpDiv.offsetHeight });
    343 }
    344 }
    345 return arrDragDivs;
    346 }
    347 }
    348
    349 window.onload = function() {
    350 var dragTbl = document.getElementById("dragTable");
    351 if (Common.getCookie("configArr")) {
    352 var configArr = eval("(" + Common.getCookie("configArr") + ")");
    353 for (i = 0; i < dragTbl.rows[0].cells.length; i++) {
    354 for (j = 0; j < configArr[i].length; j++) {
    355 dragTbl.rows[0].cells[i].appendChild(document.getElementById(configArr[i][j]));
    356 }
    357 }
    358 }
    359 new Drag("titleBar1", "dragDiv1");
    360 new Drag("titleBar2", "dragDiv2");
    361 new Drag("titleBar3", "dragDiv3");
    362 new Drag("titleBar4", "dragDiv4");
    363 new Drag("titleBar5", "dragDiv5");
    364 }
    365
    366 window.onunload = function() {
    367 var dragTbl = document.getElementById("dragTable");
    368 var configArr = "";
    369 for (i = 0; i < dragTbl.rows[0].cells.length; i++) {
    370 var tmpStr = "";
    371 for (j = 0; j < dragTbl.rows[0].cells[i].getElementsByTagName("DIV").length; j++) {
    372 tmpStr += (tmpStr == "" ? "" : ",") + "'" + dragTbl.rows[0].cells[i].getElementsByTagName("DIV")[j].id + "'";
    373 }
    374 configArr += (configArr == "" ? "" : ",") + "[" + tmpStr + "]";
    375 }
    376 //format like: [['dragDiv3','dragDiv5'],['dragDiv4','dragDiv1'],['dragDiv2']]
    377 Common.setCookie("configArr", "[" + configArr + "]");
    378 }
    379 </script>
    380 <style type="text/css">
    381 .spanDiv{
    382 position:relative;
    383 width:5px;
    384 height:5px;
    385 }
    386
    387 .dragDiv,.nodragDiv{
    388 position:relative;
    389 filter:alpha(opacity=100);
    390 opacity:1;
    391 margin-bottom:6px;
    392 background-color:#FFFFFF;
    393 }
    394 </style>
    395 </head>
    396 <body >
    397 <script type="text/javascript">
    398
    399 </script>
    400 <table id="dragTable" cellpadding="3" style=" border:solid 0px green;98%;">
    401 <tr>
    402 <td valign="top" style="30%">
    403 <div class="dragDiv" id="dragDiv1" >
    404 <table cellpadding="0" cellspacing="0" border="1" style="100%;border-collapse:collapse; border-color:Blue">
    405 <tr id="titleBar1" style="height:22px; text-align:left; background-color:#547BC9;color:White; padding:3px;cursor:move;">
    406 <th align="left" unselectable="on" >Title1</th>
    407 </tr>
    408 <tr style="height:130px;padding:3px;" align="left" valign="top" >
    409 <td unselectable="on">Content1...</td>
    410 </tr>
    411 </table>
    412 </div>
    413 <div class="dragDiv" id="dragDiv2">
    414 <table cellpadding="0" cellspacing="0" border="1" style="100%;border-collapse:collapse; border-color:Blue">
    415 <tr id="titleBar2" style="height:22px; text-align:left; background-color:#547BC9;color:White; padding:3px;cursor:move;">
    416 <th align="left" unselectable="on" >Title2</th>
    417 </tr>
    418 <tr style="height:130px;padding:3px;" align="left" valign="top" >
    419 <td unselectable="on">Content2...</td>
    420 </tr>
    421 </table>
    422 </div>
    423 </td>
    424 <td valign="top" style="50%">
    425 <div class="dragDiv" id="dragDiv3">
    426 <table cellpadding="0" cellspacing="0" border="1" style="100%;border-collapse:collapse; border-color:Blue">
    427 <tr id="titleBar3" style="height:22px; text-align:left; background-color:#547BC9;color:White; padding:3px;cursor:move;">
    428 <th align="left" unselectable="on" >Title3</th>
    429 </tr>
    430 <tr style="height:230px;padding:3px;" align="left" valign="top" >
    431 <td unselectable="on">Content3...</td>
    432 </tr>
    433 </table>
    434 </div>
    435 </td>
    436 <td valign="top" style="20%">
    437 <div class="dragDiv" id="dragDiv4">
    438 <table cellpadding="0" cellspacing="0" border="1" style="100%;border-collapse:collapse; border-color:Blue">
    439 <tr id="titleBar4" style="height:22px; text-align:left; background-color:#547BC9;color:White; padding:3px;cursor:move;">
    440 <th align="left" unselectable="on" >Title4</th>
    441 </tr>
    442 <tr style="height:130px;padding:3px;" align="left" valign="top" >
    443 <td unselectable="on">Content4...</td>
    444 </tr>
    445 </table>
    446 </div>
    447 <div class="dragDiv" id="dragDiv5">
    448 <table cellpadding="0" cellspacing="0" border="1" style="100%;border-collapse:collapse; border-color:Blue">
    449 <tr id="titleBar5" style="height:22px; text-align:left; background-color:#547BC9;color:White; padding:3px;cursor:move;">
    450 <th align="left" unselectable="on" >Title5</th>
    451 </tr>
    452 <tr style="height:130px;padding:3px;" align="left" valign="top" >
    453 <td unselectable="on">Content5...</td>
    454 </tr>
    455 </table>
    456 </div>
    457 </td>
    458 </tr>
    459 </table>
    460 </body>
    461 </html>
    462

    1. 准备

    1.1 由于模块拖拽中使用虚线框,所以去除(一)中拖拽的保持原有DIV的功能(即keepOrigin);
    1.2 在新建Drag对象时如未设置拖拽时透明值,默认改为60%的透明度;

    1.3 将拖拽范围上下左右默认设置为9999,因为模块拖拽超过当前可视窗口是必要的。

    1.4 在(一)中有个BUG,即用IE第一次打开页面报缺少对象的错,如要重现,右键文件选择IE打开,刷新后或者将文件拖到已有IE浏览器中无法重现。原因Common.getViewportSize中有document.body.offsetWidth,IE中第一次打开,当解析到这句时,document.body不存在,所以取offsetWidth时错误。所以要么把这段放到body标签中,要么进行对document.body的判断。

    1.5 HTML结构:这里使用的是Table,在TD中存放要拖拽的DIV。当然也可以全部用DIV布局。但是拖拽的DIV的postion要设为relative,因为他是在文档流中的,absolute则是脱离文档流。

    2. 思路及注意点

    2.1 在mouseDown时,插入虚线框DIV,这里要注意设置虚线框的position为relative,插入到当前拖拽DIV所处列的文档流中,同时把当前拖拽DIV的position改为absolute,使脱离文档流来进行拖拽。虚线框DIV的宽度要注意减去2倍的boderWidth,否则虚线框将撑大当前列,造成文档布局移位。同时,保证插入虚线框DIV的code要在赋当前拖拽DIV的ZIndex值前面,以保证当前拖拽DIV的ZIndex最大。

    2.2 在mouseUp时,插入当前拖拽DIV至虚线框前,将当前拖拽DIV的position、left、top、width清空,进入文档流。然后删除虚线框。

    2.3 模块自定义拖拽的核心操作即在mouseMove时。
    2.3.1 首先是虚线框的高度宽度处理,我的处理是高度保持不变,宽度取所移动到当前列的宽度。
    2.3.2 然后核心问题是:什么时候让虚线框移动到什么位置。

    我的处理是:拿当前拖拽中的鼠标位置与页面可拖拽的各DIV的绝对位置进行比较。所以在mouseDown时还要记住当前页面可拖拽DIV的绝对位置和宽度高度(RegDragsPos方法中),存入数组。
    当拖拽中鼠标进入某DIV区域内,如在该DIV上半部,则虚线框插到该DIV的上方,如在下半部则插在下方。
    当拖拽中鼠标并未触及某具体DIV区域内,在外部游离时,则首先判断处于那一列范围内,然后如果该列没有可拖拽DIV,则虚线框直接插入该列;若该列有DIV,则判断鼠标位置处于该列第一个DIV上方,则往上插,处于该列最下面DIV下方,则往下插。至此所有可能情况均处理。
    有一特殊情况,譬如,当前拖拽DIV在最上方游离,鼠标不碰及任何DIV,从第一列开始,移动到第二第三列虚线框插入均正常,但是回到第一列时发现无法插入。因为此时当前拖拽的DIV仍然作为第一列的第一个DIV,在判断是否位于该列第一个DIV上方时不符合条件无法执行虚线框插入的操作。所以在mouseDown时临时记下该列第一个DIV的top和最后一个DIV 下沿绝对位置,以此比较。

    对于什么时候让虚线框移动到什么位置,IGoogle以前版本的处理是:找到取距离当前鼠标位置这点最近的可拖拽DIV(取最短的两点间距离),然后让虚线框插入该DIV处。现在版本不清楚怎么做的。

    3.拖拽之后保存当前模块布局,使刷新页面仍保持自定义的模块布局。
    其实是在window.onunload中用cookie记下当前布局状态,如: [['dragDiv3','dragDiv5'],['dragDiv4','dragDiv1'],['dragDiv2']] 。window.onload中去布局。实际应用中可以将此插入后台数据库进行保存。

    over了,貌似啰嗦啊,哎。接下来我将写关于js动画特效的系列,给自己布置点任务先。

    点击下载


           快速评论通道--您对本文的宝贵意见:
           
    感谢您的鼓励和批评,它将是我进步的动力

  • 相关阅读:
    andriod的数据传递方法
    Activity生命周期详解
    android 和主线程有关的小问题
    java解析Excel(xls、xlsx两种格式)
    菜鸟感想一
    springboot 填坑一 springboot java.sql.SQLException: Access denied for user ''@'localhost' (using password: NO)
    git 第一次提交至仓库
    andriod studio报错 Emulator: emulator: ERROR: x86 emulation currently requires hardware acceleration! Emulator: Process finished with exit code 1
    通过以太坊发行代币(token)
    nginx+tomcat 配置负载均衡集群 (转载)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1765012.html
Copyright © 2020-2023  润新知