JavaScript、 jQuery行拖拽、排序

對移動效果提取出了一個公共方法,用JS封裝了一個類,可以直接NEW出來,就可以使用了

    //進入拖動模式
    $("#editButton").click(function(){
        var moveObj = $("tbody tr");       

        //移動時輔助提示信息,重寫
        MoveTR.prototype.show_moveMsg = function(){
            show_moveMsg(this);//根據需求重寫的方法
        };

        //移動結果控制  重寫
        MoveTR.prototype.lesMove = function(){
            lesMove(this);  //根據需求重寫的方法 
        };
        var move = new MoveTR(moveObj); //爲行添加移動事件
    });

移動效果:
具體效果需要自己去重寫,包括移動結果的控制和顯示的提示信息
這裏寫圖片描述

移動層的顯示效果基本是複製的列表TR,具體可以參考下面的示例對css樣式進行調整。

.moveFloor {
    width:98%;
    position:absolute;
    opacity:0.6;
    filter:alpha(opacity=40); /* For IE8 and earlier */
    border:1px dashed Orange;
    border-radius:5px;
    box-shadow:5px 5px 2px #bbbbbb;
}

.moveMsg{
    position:absolute;
    border: 1px dashed Orange;
    background-color:Orange;
    border-radius:5px;
    box-shadow:3px 3px 2px #999999;
}
.moveMsg font{
    font:12px/180% Arial, Helvetica, sans-serif,"宋體";
    padding:1em 1em;
}

【1】在封裝的過程中遇到一個問題:

在用new MoveTR($(‘tr’));的時候,在構造函數中直接對所有tr註冊事件,事件執行的方法中需要再次調用MoveTR的方法,但此時使用this調用會產生問題,因爲此時的this已經指向了觸發事件的TR(DOM對象),和註冊事件外面的this指向的內容不同。所以此時要將外面的this重新起個名字 比如:var thisObj = this;這樣就可以在MoveTR成員內聲明的方法中調用MoveTR中的任意對象了,JS方法也是一種對象(Function對象)。想詳細瞭解,可以參考文章後面的鏈接。

【2】在拖動過程中要禁用鼠標的選擇文本功能:

如果不禁用,會產生拖拽過程中把列表內容選中的尷尬。
unselect() 禁用, onselect() 啓用
這裏寫圖片描述

MoveTR.js 可以作爲公共方法使用,需要jQuery插件支持

/* 
    爲行添加移動動作
    moveObjs 爲jQuery對象,tr數組
    複用根據需要重寫  show_moveMsg()  lesMove()  方法

*/  
function MoveTR(moveObjs){
    this.moveObjs = moveObjs;
    this.beginMoving = false;
    this.count = moveObjs.length;
    this.startObj = new Object();
    this.startIndex = 0;
    this.endIndex = 0;
    this.endObj = new Object();
    this.moveFloor_top =  0;
    this.trHeight = 0;
    this.addTop = 0;
    this.mouseShowHeight = 0 ;  //鼠標距離頂端距離
    this.init(); //【1】
}
MoveTR.prototype.init = function(){
    var movetrObj = this;  
    //【1】
    //注意這裏,此this指向MoveTR的實例,
    //而註冊事件function中的this指向觸發事件的元素(DOM對象)
    //所以此處this要重新命名,以防止後面無法調用MoveTR中的方法或元素
    if(movetrObj.moveObjs.length > 0){
        movetrObj.moveObjs.mousedown(function(obj){
            movetrObj.MouseDown(this,obj);
        });
        movetrObj.moveObjs.mouseup(function(obj){
            //MouseUpToMove(this,obj);
            movetrObj.MouseUp(obj);
        });
        movetrObj.moveObjs.mousemove(function(obj){
            //MouseMoveToMove(this,obj);
            movetrObj.MouseMove(obj);
        }); 
    }
}

MoveTR.prototype.clear = function(){
    if(this.count < 1){
        return "Error: count=0";
    }
    this.onselect();
    moveObjs.removeClass("moveElement");
}

MoveTR.prototype.MouseDown = function(obj, mouse){
         //鼠標點下事件
         //showWinMsg("這樣可以的","OK",0.1);
         this.startObj = obj;
         this.startIndex =$(obj ).parent().children().index(this.startObj);  //開始的tr index
         this.trHeight = $(this.startObj).css("height").replace("px","");
         this.startObj.style.zIndex = 1;
         this.minTop = $(this.startObj).parents('tbody').offset().top;
         this.maxTop = $(this.startObj).parent().children().eq(this.count - 1 ).offset().top -( - this.trHeight);
         //startObj.mouseDownY=mouse.clientY;
         //startObj.mouseDownX=mouse.clientX;
         this.beginMoving = true;
         this.startObj.setCapture();
         this.show_moveDiv();
}

MoveTR.prototype.MouseMove = function (mouse){
        //鼠標移動事件
        if(! this.beginMoving) {
             return false;
        }
        this.endIndex = Math.floor( this.addTop / this.trHeight ) + this.startIndex;   //獲得結束位置的 index, Math.floor向下取整,ceil向上取整
        this.endObj = $(this.startObj).parent().children().get( this.endIndex );
        this.mouseShowHeight = mouse.clientY;    //鼠標距離document上部基準線高度
        //$(this.startObj).addClass("clickTR");
        this.move_moveDiv();  //移動效果層
        this.show_moveMsg();  //顯示提示信息

}

MoveTR.prototype.MouseUp = function ( mouse){
     $(".moveFloor").remove();//刪除效果層
     $(".moveMsg").remove();//刪除提示信息層
     //鼠標彈起事件
    // showWinMsg(this.beginMoving,"OK",0.5);
     if(! this.beginMoving) {
         return false;
     }
    this.beginMoving = false;

    //鼠標相對開始單元格移動距離,單位px, + 滾動條捲上去的高度以修正誤差
    this.addTop = mouse.clientY - $(this.startObj).offset().top + $(document).scrollTop();  
    this.endIndex = Math.floor( this.addTop / this.trHeight ) + this.startIndex;   //獲得結束位置的 index, Math.floor向下取整,ceil向上取整
    this.endObj = $(this.startObj).parent().children().get( this.endIndex );
    this.lesMove();
}

//創建一個跟隨鼠標的移動層
MoveTR.prototype.show_moveDiv = function (){

        var floatdiv = $( this.startObj).eq(0).clone();//複製一個當前移動的對象
        floatdiv.addClass("moveFloor");  //移動層
        this.moveFloor_top = $(this.startObj).offset().top -5;
        var left = $(this.startObj).offset().left -3;
        floatdiv.css({'top':this.moveFloor_top +'px','left:':left +'px'});  //指定初始位置

        var children = floatdiv.children();
        if(children.length > 0){
            var ths = $(this.startObj).parents("table").find("thead tr").eq(0).children();  //獲得標題元素
            //alert(ths.length);
            var ths_index = 0;
            //獲取顯示的內容
            //showWinMsg(tds.length,"OK",1);
            for(var i =0 ;i< children.length;i++)
            {  
                var width = $(ths[ths_index]).css("width");
                if(width != "" && width !="undefined"){
                    $(children[i]).css({"width": width  }) ;
                    if(ths_index < ths.length-1){
                        ths_index ++ ;
                    }
                }else{
                    $(children[i]).css({"width": "50px" }) ;
                }
            }
        }
        $(this.startObj).parents('tbody').append(floatdiv);
        $(this.startObj).parents('tbody').append("<div id='moveMsg' class='moveMsg' hidden></div>");
    }
//移動  效果層
MoveTR.prototype.move_moveDiv = function  (){
    var hiddenHeight = $(document).scrollTop(); //滾動條上部隱藏高度
    var documentHeight = $(document).height();  //顯示區域總高度,隱藏+顯示
    var showHeight =  $(window).height();       //當前框架的高度

    var floatdiv =$(".moveFloor");
    this.addTop =  this.mouseShowHeight - $(this.startObj).offset().top + hiddenHeight;

    this.moveFloor_top = $(this.startObj).offset().top - 5 + this.addTop;

    //var trHeight = $(this.startObj).css("height").replace("px","");

    //showWinMsg(showHeight+"|"+maxTop+"|"+mouseShowHeight+"|"+top,"OK",1);
    if( this.mouseShowHeight > 0 && this.mouseShowHeight < hiddenHeight){
        $(document).scrollTop(hiddenHeight - this.trHeight );  //鼠標在顯示區域上部,向上滾動
    }
    if( this.mouseShowHeight > showHeight - 2 * this.trHeight ){
        $(document).scrollTop(hiddenHeight -( - this.trHeight ));   //鼠標持續向下移動,向下滾動
    }


    //var startIndex =$("#tableList tbody tr").index(this.startObj);
    //var endIndex = Math.floor( this.addTop/this.trHeight ) + this.startIndex;
    if( this.moveFloor_top < this.minTop ){
        this.moveFloor_top = this.minTop  - this.trHeight ;
    }
    if(this.moveFloor_top > this.maxTop){ 
        this.moveFloor_top = this.maxTop + Math.ceil(this.trHeight /3) ;
    }

    floatdiv.css({'top':this.moveFloor_top+'px'}); 

    this.presentObj = $(this.startObj).parent().children().get(this.endIndex );
}




MoveTR.prototype.lesMove = function(){
    if(this.startIndex == this.endIndex){
        return; 
    }else if(this.endIndex >= 0 && this.endIndex < this.count){
        //拖動後,如果目的位置與原位置的首頁顯示屬性不一致,則修改爲目的位置的值


        if(this.startIndex < this.endIndex){
            //往下拖動
            $(this.startObj).insertAfter(this.endObj);
        }else{
            //往上拖動
            $(this.startObj).insertBefore(this.endObj);
        }
    }
}

MoveTR.prototype.show_moveMsg  = function (){
    //輔助性提示信息
    //moveFlag  ()
    var showStr = "移動到";
    var moveMsg_left = this.trHeight - (-5);
    var moveMsg_top = this.moveFloor_top -(-this.trHeight-5) ;
    $(".moveMsg").css({'top':moveMsg_top+'px','left': moveMsg_left+'px'});
    $(".moveMsg").hide();
    if(showStr != ""){
        $(".moveMsg").html("<font>"+showStr+"</font>");
        $(".moveMsg").show();
    }
}
//禁用鼠標選擇文字
MoveTR.prototype.unselect = function(){
    $('body').each(function() {           
        $(this).attr('unselectable', 'on').css({
         '-moz-user-select':'none',
         '-webkit-user-select':'none',
         'user-select':'none'
        }).each(function() {
         this.onselectstart = function() { return false; };
        });
    });
}
//啓用鼠標選擇文字
MoveTR.prototype.onselect = function(){
    $('body').each(function() {           
        $(this).attr('unselectable', '').css({
         '-moz-user-select':'',
         '-webkit-user-select':'',
         'user-select':''
        });
    });
}
//幫助
MoveTR.prototype.help = function(){
    return 
    "爲行添加移動動作:<br>" 
    +"使用方法   var movetr = new MoveTR($('tbody tr') );  參數爲jQuery對象(tr數組)<br>"
    +"  //移動時輔助提示信息,重寫<br>" 
    +"  MoveTR.prototype.show_moveMsg = function(){<br>"    
    +"      show_moveMsg(this);<br>"    
    +"  };<br>" 
    +"  //移動結果控制  重寫<br>"   
    +"  MoveTR.prototype.lesMove = function(){<br>" 
    +"      lesMove(this);<br>" 
    +"  };<br>"
    +"複用根據需要重寫  show_moveMsg()  lesMove()  方法<br>";
}

參考資料:
認識JS中的FUNCTION和THIS:
http://www.cnblogs.com/yuzhongwusan/archive/2012/04/09/2438569.html

發佈了38 篇原創文章 · 獲贊 10 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章