我的Blog我做主^_^

          走向一條通往JAVA的不歸路...

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            64 隨筆 :: 68 文章 :: 77 評論 :: 0 Trackbacks
          // 工具類,使用Util的命名空間,方便管理
          var ?Util? = ? new ?Object();
          // 獲取http?header里面的UserAgent,瀏覽器信息

          Util.getUserAgent? = ?navigator.userAgent;
          // 是否是Gecko核心的Browser,比如Mozila、Firefox

          Util.isGecko? = ?Util.getUserAgent.indexOf( " Gecko " )? != ? - 1 ;
          // 是否是Opera

          Util.isOpera? = ?Util.getUserAgent.indexOf( " Opera " )? != ? - 1 ;
          // 獲取一個element的offset信息,其實就是相對于Body的padding以內的絕對坐標

          //
          后面一個參數如果是true則獲取offsetLeft,false則是offsetTop
          //
          關于offset、style、client等坐標的定義參考dindin的這個帖子:http://www.jroller.com/page/dindin/?anchor=pro_javascript_12
          Util.getOffset? = ? function ?(el,?isLeft)?{
          ????
          var ?retValue? = ? 0
          ;
          ????
          while ?(el? != ? null
          )?{
          ????????retValue?
          += ?el[ " offset " ? + ?(isLeft? ? ? " Left " ?:? " Top "
          )];
          ????????el?
          =
          ?el.offsetParent;
          ????}
          ????
          return
          ?retValue;
          };
          // 將一個function(參數中的funcName是這個fuction的名字)綁定到一個element上,并且以這個element的上下文運行,其實是一種繼承,這個可以google些文章看看

          Util.bindFunction? = ? function ?(el,?fucName)?{
          ????
          return ? function
          ?()?{
          ????????
          return
          ?el[fucName].apply(el,?arguments);
          ????};
          };
          // 重新計算所有的可以拖拽的element的坐標,對同一個column下面的可拖拽圖層重新計算它們的高度而得出新的坐標,防止遮疊

          //
          計算出來的坐標記錄在pagePosLeft和pagePosTop兩個屬性里面
          Util.re_calcOff? = ? function ?(el)?{
          ????
          for ?( var ?i? = ? 0 ;?i? < ?Util.dragArray.length;?i ++
          )?{
          ????????
          var ?ele? =
          ?Util.dragArray[i];
          ????????ele.elm.pagePosLeft?
          = ?Util.getOffset(ele.elm,? true
          );
          ????????ele.elm.pagePosTop?
          = ?Util.getOffset(ele.elm,? false
          );
          ????}
          ????
          var ?nextSib? =
          ?el.elm.nextSibling;
          ????
          while
          ?(nextSib)?{
          ????????nextSib.pagePosTop?
          -=
          ?el.elm.offsetHeight;
          ????????nextSib?
          =
          ?nextSib.nextSibling;
          ????}
          };

          // 隱藏Google?Ig中間那個table,也就是拖拽的容器,配合show一般就是刷新用,解決一些瀏覽器的怪癖

          Util.hide? = ? function ?()?{
          ????Util.rootElement.style.display?
          = ? " none "
          ;
          };
          // 顯示Google?Ig中間那個table,解釋同上

          Util.show? = ? function ?()?{
          ????Util.rootElement.style.display?
          = ? ""
          ;
          };

          // 移動時顯示的占位虛線框

          ghostElement? = ? null ;
          // 獲取這個虛線框,通過dom動態生成

          getGhostElement? = ? function ?()?{
          ????
          if ?( !
          ghostElement)?{
          ????????ghostElement?
          = ?document.createElement( " DIV "
          );
          ????????ghostElement.className?
          = ? " modbox "
          ;
          ????????ghostElement.backgroundColor?
          = ? ""
          ;
          ????????ghostElement.style.border?
          = ? " 2px?dashed?#aaa "
          ;
          ????????ghostElement.innerHTML?
          = ? " &nbsp; "
          ;
          ????}
          ????
          return
          ?ghostElement;
          };

          // 初始化可以拖拽的Element的函數,與拖拽無關的我去掉了

          function ?draggable(el)?{
          ????
          // 公用的開始拖拽的函數

          ???? this ._dragStart? = ?start_Drag;
          ????
          // 公用的正在拖拽的函數

          ???? this ._drag? = ?when_Drag;
          ????
          // 公用的拖拽結束的函數

          ???? this ._dragEnd? = ?end_Drag;
          ????
          // 這個函數主要用來進行拖拽結束后的dom處理

          ???? this ._afterDrag? = ?after_Drag;
          ????
          // 是否正在被拖動,一開始當然沒有被拖動

          ???? this .isDragging? = ? false ;
          ????
          // 將這個Element的this指針注冊在elm這個變量里面,方便在自己的上下文以外調用自己的函數等,很常用的方法

          ???? this .elm? = ?el;
          ????
          // 觸發拖拽的Element,在這里就是這個div上顯示標題的那個div

          ???? this .header? = ?document.getElementById(el.id? + ? " _h " );
          ????
          // 對于有iframe的element拖拽不同,這里檢測一下并記錄

          ???? this .hasIFrame? = ? this .elm.getElementsByTagName( " IFRAME " ).length? > ? 0 ;
          ????
          // 如果找到了header就綁定drag相關的event

          ???? if ?( this .header)?{
          ????????
          // 拖拽時的叉子鼠標指針

          ???????? this .header.style.cursor? = ? " move " ;
          ????????
          // 將函數綁定到header和element的this上,參照那個函數的說明

          ????????Drag.init( this .header,? this .elm);
          ????????
          // 下面三個語句將寫好的三個函數綁定給這個elemnt的三個函數鉤子上,也就實現了element從draggable繼承可拖拽的函數

          ???????? this .elm.onDragStart? = ?Util.bindFunction( this ,? " _dragStart " );
          ????????
          this .elm.onDrag? = ?Util.bindFunction( this ,? " _drag "
          );
          ????????
          this .elm.onDragEnd? = ?Util.bindFunction( this ,? " _dragEnd "
          );
          ????}
          };

          // 下面就是draggable里面用到的那4個function

          //
          公用的開始拖拽的函數
          function ?start_Drag()?{
          ????
          // 重置坐標,實現拖拽以后自己的位置馬上會被填充的效果

          ????Util.re_calcOff( this );
          ????
          // 記錄原先的鄰居節點,用來對比是否被移動到新的位置

          ???? this .origNextSibling? = ? this .elm.nextSibling;
          ????
          // 獲取移動的時候那個灰色的虛線框

          ???? var ?_ghostElement? = ?getGhostElement();
          ????
          // 獲取正在移動的這個對象的高度

          ???? var ?offH? = ? this .elm.offsetHeight;
          ????
          if
          ?(Util.isGecko)?{
          ????????
          // 修正gecko引擎的怪癖吧

          ????????offH? -= ?parseInt(_ghostElement.style.borderTopWidth)? * ? 2 ;
          ????}
          ????
          // 獲取正在移動的這個對象的寬度

          ???? var ?offW? = ? this .elm.offsetWidth;
          ????
          // 獲取left和top的坐標

          ???? var ?offLeft? = ?Util.getOffset( this .elm,? true );
          ????
          var ?offTop? = ?Util.getOffset( this .elm,? false
          );
          ????
          // 防止閃爍,現隱藏

          ????Util.hide();
          ????
          // 將自己的寬度記錄在style屬性里面

          ???? this .elm.style.width? = ?offW? + ? " px " ;
          ????
          // 將那個灰框設定得與正在拖動的對象一樣高,比較形象

          ????_ghostElement.style.height? = ?offH? + ? " px " ;
          ????
          // 把灰框放到這個對象原先的位置上

          ???? this .elm.parentNode.insertBefore(_ghostElement,? this .elm.nextSibling);
          ????
          // 由于要拖動必須將被拖動的對象從原先的盒子模型里面抽出來,所以設定position為absolute,這個可以參考一下css布局方面的知識

          ???? this .elm.style.position? = ? " absolute " ;
          ????
          // 設置zIndex,讓它處在最前面一層,當然其實zIndex=100是讓它很靠前,如果頁面里有zIndex>100的,那……

          ???? this .elm.style.zIndex? = ? 100 ;
          ????
          // 由于position=absolute了,所以left和top實現絕對坐標定位,這就是先前計算坐標的作用,不讓這個模型亂跑,要從開始拖動的地方開始移動

          ???? this .elm.style.left? = ?offLeft? + ? " px " ;
          ????
          this .elm.style.top? = ?offTop? + ? " px "
          ;
          ????
          // 坐標設定完畢,可以顯示了,這樣就不會閃爍了

          ????Util.show();
          ????
          // 這里本來有個ig_d.G,沒搞明白干什么用的,不過沒有也可以用,誰知道麻煩告訴我一聲,不好意思

          ???? // 還沒有開始拖拽,這里做個記號
          ???? this .isDragging? = ? false ;
          ????
          return ? false
          ;
          };
          // 在拖拽時的相應函數,由于綁定到鼠標的move這個event上,所以會傳入鼠標的坐標clientX,?clientY

          function ?when_Drag(clientX,?clientY)?{
          ????
          // 剛開始拖拽的時候將圖層變透明,并標記為正在被拖拽

          ???? if ?( ! this .isDragging)?{
          ????????
          this .elm.style.filter? = ? " alpha(opacity=70) "
          ;
          ????????
          this .elm.style.opacity? = ? 0.7
          ;
          ????????
          this .isDragging? = ? true
          ;
          ????}
          ????
          // 被拖拽到的新的column(當然也可以是原來那個)

          ???? var ?found? = ? null ;
          ????
          // 最大的距離,可能是防止溢出或者什么bug

          ???? var ?max_distance? = ? 100000000 ;
          ????
          // 遍歷所有的可拖拽的element,尋找離當前鼠標坐標最近的那個可拖拽元素,以便后面插入

          ???? for ?( var ?i? = ? 0 ;?i? < ?Util.dragArray.length;?i ++ )?{
          ????????
          var ?ele? =
          ?Util.dragArray[i];
          ????????
          // 利用勾股定理計算鼠標到遍歷到的這個元素的距離

          ???????? var ?distance? = ?Math.sqrt(Math.pow(clientX? - ?ele.elm.pagePosLeft,? 2 )? + ?Math.pow(clientY? - ?ele.elm.pagePosTop,? 2 ));
          ????????
          // 自己已經浮動了,所以不計算自己的

          ???????? if ?(ele? == ? this )?{
          ????????????
          continue
          ;
          ????????}
          ????????
          // 如果計算失敗繼續循環

          ???????? if ?(isNaN(distance))?{
          ????????????
          continue
          ;
          ????????}
          ????????
          // 如果更小,記錄下這個距離,并將它作為found

          ???????? if ?(distance? < ?max_distance)?{
          ????????????max_distance?
          =
          ?distance;
          ????????????found?
          =
          ?ele;
          ????????}
          ????}
          ????
          // 準備讓灰框落腳

          ???? var ?_ghostElement? = ?getGhostElement();
          ????
          // 如果找到了另外的落腳點

          ???? if ?(found? != ? null ? && ?_ghostElement.nextSibling? != ?found.elm)?{
          ????????
          // 找到落腳點就先把灰框插進去,這就是我們看到的那個灰框停靠的特效,有點像吸附的感覺,哈哈

          ????????found.elm.parentNode.insertBefore(_ghostElement,?found.elm);
          ????????
          if
          ?(Util.isOpera)?{
          ????????????
          // Opera的現實問題,要隱藏/顯示后才能刷新出變化

          ????????????document.body.style.display? = ? " none " ;
          ????????????document.body.style.display?
          = ? ""
          ;
          ????????}
          ????}
          };
          // 拖拽完畢

          function ?end_Drag()?{
          ????
          // 拖拽完畢后執行后面的鉤子,執行after_Drag(),如果布局發生了變動了就記錄到遠程服務器,保存你拖拽后新的布局順序

          ???? if ?( this ._afterDrag())?{
          ????????
          // remote?call?to?save?the?change

          ????}
          ????
          return ? true
          ;
          };
          // 拖拽后的執行鉤子

          function ?after_Drag()?{
          ????
          var ?returnValue? = ? false
          ;
          ????
          // 防止閃爍

          ????Util.hide();
          ????
          // 把拖拽時的position=absolute和相關的那些style都消除

          ???? this .elm.style.position? = ? "" ;
          ????
          this .elm.style.width? = ? ""
          ;
          ????
          this .elm.style.zIndex? = ? ""
          ;
          ????
          this .elm.style.filter? = ? ""
          ;
          ????
          this .elm.style.opacity? = ? ""
          ;
          ????
          // 獲取灰框

          ???? var ?ele? = ?getGhostElement();
          ????
          // 如果現在的鄰居不是原來的鄰居了

          ???? if ?(ele.nextSibling? != ? this .origNextSibling)?{
          ????????
          // 把被拖拽的這個節點插到灰框的前面

          ????????ele.parentNode.insertBefore( this .elm,?ele.nextSibling);
          ????????
          // 標明被拖拽了新的地方

          ????????returnValue? = ? true ;
          ????}
          ????
          // 移除灰框,這是這個灰框的生命周期應該就結束了

          ????ele.parentNode.removeChild(ele);
          ????
          // 修改完畢,顯示

          ????Util.show();
          ????
          if
          ?(Util.isOpera)?{
          ????????
          // Opera的現實問題,要隱藏/顯示后才能刷新出變化

          ????????document.body.style.display? = ? " none " ;
          ????????document.body.style.display?
          = ? ""
          ;
          ????}
          ????
          return
          ?returnValue;
          };
          // 可拖拽Element的原形,用來將event綁定到各個鉤子,這部分市比較通用的,netvibes也是基本完全相同的實現

          //
          這部分推薦看dindin的這個,也會幫助理解,http://www.jroller.com/page/dindin/?anchor=pro_javascript_12
          var ?Drag? = ?{
          ????
          // 對這個element的引用,一次只能拖拽一個Element

          ????obj: null ,?
          ????
          // element是被拖拽的對象的引用,elementHeader就是鼠標可以拖拽的區域

          ????init: function ?(elementHeader,?element)?{
          ????????
          // 將start綁定到onmousedown事件,按下鼠標觸發start

          ????????elementHeader.onmousedown? = ?Drag.start;
          ????????
          // 將element存到header的obj里面,方便header拖拽的時候引用

          ????????elementHeader.obj? = ?element;
          ????????
          // 初始化絕對的坐標,因為不是position=absolute所以不會起什么作用,但是防止后面onDrag的時候parse出錯了

          ???????? if ?(isNaN(parseInt(element.style.left)))?{
          ????????????element.style.left?
          = ? " 0px "
          ;
          ????????}
          ????????
          if
          ?(isNaN(parseInt(element.style.top)))?{
          ????????????element.style.top?
          = ? " 0px "
          ;
          ????????}
          ????????
          // 掛上空Function,初始化這幾個成員,在Drag.init被調用后才幫定到實際的函數,可以參照draggable里面的內容

          ????????element.onDragStart? = ? new ?Function();
          ????????element.onDragEnd?
          = ? new
          ?Function();
          ????????element.onDrag?
          = ? new
          ?Function();
          ????},
          ????
          // 開始拖拽的綁定,綁定到鼠標的移動的event上

          ????start: function ?(event)?{
          ????????
          var ?element? = ?Drag.obj? = ? this
          .obj;
          ????????
          // 解決不同瀏覽器的event模型不同的問題

          ????????event? = ?Drag.fixE(event);
          ????????
          // 看看是不是左鍵點擊

          ???????? if ?(event.which? != ? 1 )?{
          ????????????
          // 除了左鍵都不起作用

          ???????????? return ? true ;
          ????????}
          ????????
          // 參照這個函數的解釋,掛上開始拖拽的鉤子

          ????????element.onDragStart();
          ????????
          // 記錄鼠標坐標

          ????????element.lastMouseX? = ?event.clientX;
          ????????element.lastMouseY?
          =
          ?event.clientY;
          ????????
          // 將Global的event綁定到被拖動的element上面來

          ????????document.onmouseup? = ?Drag.end;
          ????????document.onmousemove?
          =
          ?Drag.drag;
          ????????
          return ? false
          ;
          ????},?
          ????
          // Element正在被拖動的函數

          ????drag: function ?(event)?{
          ????????
          // 解決不同瀏覽器的event模型不同的問題

          ????????event? = ?Drag.fixE(event);
          ????????
          // 看看是不是左鍵點擊

          ???????? if ?(event.which? == ? 0 )?{
          ????????????
          // 除了左鍵都不起作用

          ???????????? return ?Drag.end();
          ????????}
          ????????
          // 正在被拖動的Element

          ???????? var ?element? = ?Drag.obj;
          ????????
          // 鼠標坐標

          ???????? var ?_clientX? = ?event.clientY;
          ????????
          var ?_clientY? =
          ?event.clientX;
          ????????
          // 如果鼠標沒動就什么都不作

          ???????? if ?(element.lastMouseX? == ?_clientY? && ?element.lastMouseY? == ?_clientX)?{
          ????????????
          return ? false
          ;
          ????????}
          ????????
          // 剛才Element的坐標

          ???????? var ?_lastX? = ?parseInt(element.style.top);
          ????????
          var ?_lastY? =
          ?parseInt(element.style.left);
          ????????
          // 新的坐標

          ???????? var ?newX,?newY;
          ????????
          // 計算新的坐標:原先的坐標+鼠標移動的值差

          ????????newX? = ?_lastY? + ?_clientY? - ?element.lastMouseX;
          ????????newY?
          = ?_lastX? + ?_clientX? -
          ?element.lastMouseY;
          ????????
          // 修改element的顯示坐標

          ????????element.style.left? = ?newX? + ? " px " ;
          ????????element.style.top?
          = ?newY? + ? " px "
          ;
          ????????
          // 記錄element現在的坐標供下一次移動使用

          ????????element.lastMouseX? = ?_clientY;
          ????????element.lastMouseY?
          =
          ?_clientX;
          ????????
          // 參照這個函數的解釋,掛接上Drag時的鉤子

          ????????element.onDrag(newX,?newY);
          ????????
          return ? false
          ;
          ????},
          ????
          // Element正在被釋放的函數,停止拖拽

          ????end: function ?(event)?{
          ????????
          // 解決不同瀏覽器的event模型不同的問題

          ????????event? = ?Drag.fixE(event);
          ????????
          // 解除對Global的event的綁定

          ????????document.onmousemove? = ? null ;
          ????????document.onmouseup?
          = ? null
          ;
          ????????
          // 先記錄下onDragEnd的鉤子,好移除obj

          ???????? var ?_onDragEndFuc? = ?Drag.obj.onDragEnd();
          ????????
          // 拖拽完畢,obj清空

          ????????Drag.obj? = ? null ;
          ????????
          return
          ?_onDragEndFuc;
          ????},?
          ????
          // 解決不同瀏覽器的event模型不同的問題

          ????fixE: function ?(ig_)?{
          ????????
          if ?( typeof ?ig_? == ? " undefined "
          )?{
          ????????????ig_?
          =
          ?window.event;
          ????????}
          ????????
          if ?( typeof ?ig_.layerX? == ? " undefined "
          )?{
          ????????????ig_.layerX?
          =
          ?ig_.offsetX;
          ????????}
          ????????
          if ?( typeof ?ig_.layerY? == ? " undefined "
          )?{
          ????????????ig_.layerY?
          =
          ?ig_.offsetY;
          ????????}
          ????????
          if ?( typeof ?ig_.which? == ? " undefined "
          )?{
          ????????????ig_.which?
          =
          ?ig_.button;
          ????????}
          ????????
          return
          ?ig_;
          ????}
          };



          // 下面是初始化的函數了,看看上面這些東西怎么被調用

          var ?_IG_initDrag? = ? function ?(el)?{
          ????
          // column那個容器,在google里面就是那個table布局的tbody,netvibes用的<div>

          ????Util.rootElement? = ?el;
          ????
          // 這個tbody的行

          ????Util._rows? = ?Util.rootElement.tBodies[ 0 ].rows[ 0 ];
          ????
          // 列,google是3列,其實也可以更多

          ????Util.column? = ?Util._rows.cells;
          ????
          // 用來存取可拖拽的對象

          ????Util.dragArray? = ? new ?Array();
          ????
          var ?counter? = ? 0
          ;
          ????
          for ?( var ?i? = ? 0 ;?i? < ?Util.column.length;?i ++
          )?{
          ????????
          // 搜索所有的column

          ???????? var ?ele? = ?Util.column[i];
          ????????
          for ?( var ?j? = ? 0 ;?j? < ?ele.childNodes.length;?j ++
          )?{
          ????????????
          // 搜索每一column里面的所有element

          ???????????? var ?ele1? = ?ele.childNodes[j];
          ????????????
          // 如果是div就把它初始化為一個draggable對象

          ???????????? if ?(ele1.tagName? == ? " DIV " )?{
          ????????????????Util.dragArray[counter]?
          = ? new
          ?draggable(ele1);
          ????????????????counter
          ++
          ;
          ????????????}
          ????????}
          ????}
          };

          // google的頁面里可以拖動的部分的id是"t_1"

          //
          掛載到onload,載入完畢執行。不過實際上google沒有用onload。
          //
          而是寫在頁面最下面,異曲同工吧,也許直接寫在頁面是種怪癖,或者也有可能是兼容性考慮。

          // 請將下面兩條被注釋掉的代碼加,到你自己下載的一個google?ig頁面里面,把里面的所有其余script刪除,掛上這個js也可以拖拽了,哈哈
          //
          _table=document.getElementById("t_1");
          //
          window.onload?=?_IG_initDrag(_table);

          // 其實看懂這些代碼對學習javascript很有益,希望對大家能有幫助


          posted on 2007-01-13 18:05 java_蟈蟈 閱讀(251) 評論(0)  編輯  收藏 所屬分類: JAVASCRIPT
          主站蜘蛛池模板: 墨脱县| 平舆县| 广水市| 嘉定区| 英吉沙县| 睢宁县| 长丰县| 九台市| 利津县| 龙岩市| 枣庄市| 清原| 宁陕县| 会昌县| 浮梁县| 阿拉尔市| 隆子县| 乌兰察布市| 莱阳市| 额敏县| 巴彦淖尔市| 天津市| 界首市| 谢通门县| 马鞍山市| 陆良县| 甘孜县| 嘉义市| 隆林| 涟水县| 蒙阴县| 扬中市| 陇川县| 华宁县| 湄潭县| 汨罗市| 东乌珠穆沁旗| 西安市| 随州市| 淳安县| 吉木乃县|