<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Terry.Li-彬

    虛其心,可解天下之問;專其心,可治天下之學;靜其心,可悟天下之理;恒其心,可成天下之業。

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      143 隨筆 :: 344 文章 :: 130 評論 :: 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_java_12
    Util.getOffset  =    (el, isLeft) {
        
    var  ret  =   0 ;
        
    while  (el  !=   null ) {
            ret 
    +=  el[ " offset "   +  (isLeft  ?   " Left "  :  " Top " )];
            el 
    =  el.offsetParent;
        }
        
    return  ret;
    };
    // 將一個(參數中的funcName是這個fuction的名字)綁定到一個element上,并且以這個element的上下文運行,其實是一種繼承,這個可以google些文章看看
    Util.bind  =    (el, fucName) {
        
    return    () {
            
    return  el[fucName].apply(el, arguments);
        };
    };
    // 重新計算所有的可以拖拽的element的坐標,對同一個column下面的可拖拽圖層重新計算它們的高度而得出新的坐標,防止遮疊
    //
    計算出來的坐標記錄在pagePosLeft和pagePosTop兩個屬性里面
    Util.re_calcOff  =    (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  =    () {
        Util.rootElement.style.display 
    =   " none " ;
    };
    // 顯示Google Ig中間那個table,解釋同上
    Util.show  =    () {
        Util.rootElement.style.display 
    =   "" ;
    };

    // 移動時顯示的占位虛線框
    ghostElement  =   null ;
    // 獲取這個虛線框,通過dom動態生成
    getGhostElement  =    () {
        
    if  ( ! ghostElement) {
            ghostElement 
    =  createElement( " DIV " );
            ghostElement.className 
    =   " modbox " ;
            ghostElement.backgroundColor 
    =   "" ;
            ghostElement.style.border 
    =   " 2px dashed #aaa " ;
            ghostElement.innerHTML 
    =   " &nbsp; " ;
        }
        
    return  ghostElement;
    };

    // 初始化可以拖拽的Element的函數,與拖拽無關的我去掉了
      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  =  getElementById(el.id  +   " _h " );
         // 對于有i的element拖拽不同,這里檢測一下并記錄
         this .hasI  =   this .elm.getElementsByTagName( " I " ).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.bind( this ,  " _dragStart " );
             this .elm.onDrag  =  Util.bind( this ,  " _drag " );
             this .elm.onDragEnd  =  Util.bind( this ,  " _dragEnd " );
        }
    };

    // 下面就是draggable里面用到的那4個
    // 公用的開始拖拽的函數
      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 ;
    };

    // 初始化可以拖拽的Element的函數,與拖拽無關的我去掉了
      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  =  getElementById(el.id  +   " _h " );
         // 對于有i的element拖拽不同,這里檢測一下并記錄
         this .hasI  =   this .elm.getElementsByTagName( " I " ).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.bind( this ,  " _dragStart " );
             this .elm.onDrag  =  Util.bind( this ,  " _drag " );
             this .elm.onDragEnd  =  Util.bind( this ,  " _dragEnd " );
        }
    };
    // 下面就是draggable里面用到的那4個
    // 公用的開始拖拽的函數
      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
      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的現實問題,要隱藏/顯示后才能刷新出變化
                body.style.display  =   " none " ;
                body.style.display  =   "" ;
            }
        }
    };
    // 拖拽完畢
      end_Drag() {
         // 拖拽完畢后執行后面的鉤子,執行after_Drag(),如果布局發生了變動了就記錄到遠程服務器,保存你拖拽后新的布局順序
         if  ( this ._afterDrag()) {
             // remote call to save the change
        }
         return   true ;
    };
    // 拖拽后的執行鉤子
      after_Drag() {
         var  return  =   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);
             // 標明被拖拽了新的地方
            return  =   true ;
        }
         // 移除灰框,這是這個灰框的生命周期應該就結束了
        ele.parentNode.removeChild(ele);
         // 修改完畢,顯示
        Util.show();
         if  (Util.isOpera) {
             // Opera的現實問題,要隱藏/顯示后才能刷新出變化
            body.style.display  =   " none " ;
            body.style.display  =   "" ;
        }
         return  return;
    };


    // 可拖拽Element的原形,用來將event綁定到各個鉤子,這部分市比較通用的,netvibes也是基本完全相同的實現
    // 這部分推薦看dindin的這個,也會幫助理解,http://www.jroller.com/page/dindin/?anchor=pro_java_12
    var  Drag  =  {
         // 對這個element的引用,一次只能拖拽一個Element
        obj: null ,
         // element是被拖拽的對象的引用,elementHeader就是鼠標可以拖拽的區域
        init:   (elementHeader, element) {
             // 將start綁定到down事件,按下鼠標觸發start
            elementHeader.down  =  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 " ;
            }
             // 掛上空,初始化這幾個成員,在Drag.init被調用后才幫定到實際的函數,可以參照draggable里面的內容
            element.onDragStart  =   new  ();
            element.onDragEnd  =   new  ();
            element.onDrag  =   new  ();
        },
         // 開始拖拽的綁定,綁定到鼠標的移動的event上
        start:   (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上面來
            up  =  Drag.end;
            move  =  Drag.drag;
             return   false ;
        },
         // Element正在被拖動的函數
        drag:   (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:   (event) {
             // 解決不同瀏覽器的event模型不同的問題
            event  =  Drag.fixE(event);
             // 解除對Global的event的綁定
            move  =   null ;
            up  =   null ;
             // 先記錄下onDragEnd的鉤子,好移除obj
             var  _onDragEndFuc  =  Drag.obj.onDragEnd();
             // 拖拽完畢,obj清空
            Drag.obj  =   null ;
             return  _onDragEndFuc;
        },
         // 解決不同瀏覽器的event模型不同的問題
        fixE:   (ig_) {
             if  ( typeof  ig_  ==   " undefined " ) {
                ig_  =  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  =     (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"
    // 掛載到,載入完畢執行。不過實際上google沒有用。
    // 而是寫在頁面最下面,異曲同工吧,也許直接寫在頁面是種怪癖,或者也有可能是兼容性考慮。

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

    // 其實看懂這些代碼對學習java很有益,希望對大家能有幫助
    posted on 2008-02-13 22:51 禮物 閱讀(765) 評論(0)  編輯  收藏 所屬分類: JavaCAJakarta
    主站蜘蛛池模板: 国产免费人成视频尤勿视频| 久久免费观看国产精品| 亚洲成A人片77777国产| 国产无遮挡无码视频免费软件| 亚洲成在人线电影天堂色| 日本免费的一级v一片| 国产成人免费ā片在线观看老同学| 亚洲日韩乱码中文无码蜜桃| 四虎永久免费地址在线网站| 三年片在线观看免费大全电影| 亚洲成在人线在线播放无码| 亚洲AV永久无码区成人网站 | 免费在线黄色电影| 亚洲视频无码高清在线| 亚洲日韩乱码中文无码蜜桃臀网站 | 羞羞视频免费网站入口| 亚洲国产人成在线观看69网站 | 我们的2018在线观看免费高清| 香蕉97碰碰视频免费| 亚洲美女视频免费| 国产精品亚洲mnbav网站 | 热久久精品免费视频| 99re6在线视频精品免费下载| 香港特级三A毛片免费观看| 2020天堂在线亚洲精品专区| 亚洲av无码专区国产乱码在线观看 | 久久久久亚洲AV成人网人人网站| 最近免费中文字幕4| 日韩免费高清大片在线| 成人片黄网站色大片免费观看cn | jizz免费在线影视观看网站| 亚洲乱码无人区卡1卡2卡3| 337p日本欧洲亚洲大胆色噜噜 | 一级毛片直播亚洲| 成人免费毛片内射美女APP| 免费无码一区二区三区| a在线观看免费视频| 特色特黄a毛片高清免费观看| 亚洲熟妇AV乱码在线观看| 亚洲精品视频在线播放| 亚洲欧洲日产国码久在线观看 |