首頁 > web前端 > js教程 > 主體

基於JQuery的列表拖曳排序實作碼_jquery

WBOY
發布: 2016-05-16 17:20:54
原創
1270 人瀏覽過

要求

拖曳排序,從名字就不難想像,就是按住一行資料拖曳到想要的排序位置,儲存新的排序佇列。

思路

先給清單行建立錨點,綁定mousedown和mouseup事件,當滑鼠移動到想要插入的位置時,將物件行移到目標行,然後對其經過的所有行進行排序處理。

思路很簡單,但這裡面還是有幾個問題要注意

1、移動到什麼位置可以視為要插入到目標行的位置。
2、移動出了頂端和底端時,判斷為第一和最後。
3、向上移動和向下移動的處理

解決

關於事件

Javascript裡滑鼠按下和放開事件為onmousedown,onmouseup,JQuery裡是mousedown,mouseup,所以,這裡使用mousedown和mouseup

首先,要知道介面有多少行,每一行有多高,因為要判斷滑鼠的移動距離

複製程式碼

程式碼如下:


var tbodyHeight=setting.frame.outerHeight();  //setting.frame,父親物件
var lineNum=$("." setting.dgLine) .length;  //setting.dgLine,每一行的classnamevar lineHeight=Math.ceil(tbodyHeight/lineNum);

之所有要取lineNum(行數),除了計算行高外,還有個目的是要使用index(),透過序列索引值來進行移動行到目標位置

當mousedown事件觸發後,就要開始計算滑鼠移動的距離,用於判斷該行到底要移動到什麼位置 複製程式碼

程式碼如下:


dgid=$(this).attr(>

dgid=$(this).attr(setting.id );  //移動行的ID,setting.id,是每一行用來標記ID的名稱
thisIndex=$("#" setting.linePre dgid).index(); //該行的索引,setting .linePre,每一行ID關休學thisLineTop=$("#" setting.linePre dgid).offset().top; //該行的top值

topDistance=thisIndex*lineHeight;  //該行距離第一行頂端的距離
downDistance=(lineNum-thisIndex-1)*lineHeight; //該行距離最後一行底端的距離

dgid主要是用來區分每一行的標識,一般的列表都是程式循環輸出來的,如果沒有這樣一個ID,就分不出哪行是哪行,所以,在HTML上,需要定義一個存放ID的傢伙。程式透過attr就是來取這個值,保證每一行都有自己唯一的值。

thisLineTop,主要是用來和滑鼠移動位置進行高度計算,然後根據行高、索引值來判斷是移動到哪一行了。還有個作用是用來確定是否按在了移動錨點上,如果有值,說明是,那後面的mouseup就是成立的,如果沒有值,說明沒有按到錨點上,mouseup不執行任何操作。為什麼要這樣做呢?因為不管在頁面的什麼位置點滑鼠,都會觸發mouseup事件,如果沒有一個判斷,就會不停的執行,就會產生一些問題。

topDistance和downDistance,用來判斷滑鼠有沒有移出清單的範圍,如果移除了,也就是滑鼠移動的距離大於topDistance或downDistance,那就可以判斷為需要移動到第一行或最後一行。 mousedown事件主要做的,就是這幾件事情,當然,為了效果,還可以增加一些東西
複製程式碼


程式碼如下:


$("#" setting.linePre ('background',setting.lineHighlight); //高亮移動行
var left=e.pageX 20;
var top=e.pageY;
dg_tips(left,top);  //建立一個提示圖層
$('body').css('cursor','move'); //更改頁面的滑鼠手勢
$("body").disableSelection(); //禁止按下滑鼠後移動滑鼠時選取頁面元素setting.frame.mousemove(function(e){  //讓提示圖層跟著滑鼠移動

$("#dgf").css({"left":e. pageX setting.tipsOffsetLeft 'px',"top":e.pageY 'px'});

});

這些的目的,只是讓操作起來更有效果,例如高亮行,就是要讓使用者知道,他們操作的是哪一行。提示層的作用也是一樣。 關於禁止選中,.disableSelection();這是jQuery_UI裡帶的方法,如果你有使用jQuery_UI,那可以直接使用它,如果沒有使用,可以這樣做
複製程式碼 程式碼如下:

$('body').each(function() {         
 $(this).attr('unselectable', 'on').css({
user. select':'none',
  '-webkit-user-select':'none',
  'user-select':'none'
 }).each(function() {
this.onselectstart = function() { return false; };
 });
});

取消禁止選擇

複製程式碼 程式碼如下:

$('body').each(function() {          
 $(this).attr('unselectable', '').css({
  '-moz-user-select':'' ',
  'user-select':''
 });
});

考慮到通用性,所以後面的程式碼裡,不會使用.disableSelection();

好了,下面是mouseup事件。這裡mouseup事件是綁定在body上的,因為mouseup如果只是綁定在錨點上,那麼當滑鼠移出錨點的時候,再放開滑鼠,會發現,這個mouseup事件不執行了,因為它會認為是別的物件的mouseup。所以,最保險的方法是用$('body').mouseup。這樣基本上就不會有問題。

mouseup觸發後,首先就要判斷thisLineTop是不是有值,防止無意義的事件執行。跟著判斷滑鼠移動的距離是正還是負,也就是向上移動還是向下移動。

var moveDistance=e.pageY-thisLineTop;

依不同的方向作不同的處理

複製程式碼 程式碼如下:
if(moveDistance thisIndex!=0){
  moveDistance=Math.abs(moveDistance);  //為負數的時候,取一下絕對值
  if(moveDistance>lineHeight/2){ //判斷移動距離是否超過行高行高行的1/2
   if(moveDistance>topDistance){ //如果移動距離大於該行到頂邊的距離
    focusIndex=0;
   }else{
M. moveDistance/lineHeight);
   }
   $("." setting.dgLine).eq(focusIndex).before($("#" setting.linePre dgid));//將該行插入目標位置
  }
 }
}else{
 if(thisIndex!=lineNum-1){
  if(moveDistance>lineHeight/2 lineHeight){    focusIndex=lineNum-1;
   }else{
    focusIndex=thisIndex Math.ceil(moveDistance/lineHeight)-1;  }
 }
}



之所以判斷移動距離是否超過行高的1/2,是因為如果只移動一小點,可以視作不移動。在計算目標索引值的時候,使用了Math.ceil,最進位,而當移動距離大於0的時候,取了進位還要-1,因為是向下嘛。

向上移動和向下移動使用了不同的插入方法,before和after,可以試著想為什麼要使用before和after。
移動完了,還得把按下滑鼠時使用的效果給去除掉

複製程式碼

程式碼如下:$("#dgf").remove();remove(); //移除提示圖層$("#" setting.linePre dgid).css('background','');//將高亮的行變成普通dgid='';//將移動行的ID值空thisLineTop=0;//將移動行的Top值至0
$('body').css('cursor','default');//更改滑鼠手勢為預設



基本上的情況就是這樣,主要問題就是在處理移動和判斷在哪裡插入的問題上。其它的都非常簡單。

下面給出完整的封裝程序,包括更新資料部分

複製程式碼

程式碼如下:

/*
*
*  DragList.js
*  @author fuweiyi

*/
(function($){
 $.fn.DragList=function(setting){
  var _setting = {
   frame : $(this),
   dgLine : 'DLL',
   dgButton : 'DLB',
   id : 'action-id',
   linePre : 'list_',
   lineHighlight : '#ffffcc',
   tipsOpacity : 80,
   tipsOffsetLeft : 20,
   tipsOffsetTop : 0,
   JSONUrl : '',
   JSONData : {},
   maskLoaddingIcon : '',
   maskBackgroundColor : '#999',
   maskOpacity : 30,
   maskColor : '#000',
   maskLoadIcon:'',
  };
  var setting = $.extend(_setting,setting);

  var dgid='',thisIndex,thisLineTop=0,topDistance,downDistance;
  var tbodyHeight=setting.frame.outerHeight();
  var lineNum=$("."+setting.dgLine).length;
  var lineHeight=Math.ceil(tbodyHeight/lineNum);

  $("."+setting.dgButton).mousedown(function(e){
   dgid=$(this).attr(setting.id);
   thisIndex=$("#"+setting.linePre+dgid).index();
   var left=e.pageX+20;
   var top=e.pageY;
   thisLineTop=$("#"+setting.linePre+dgid).offset().top;
   topDistance=thisIndex*lineHeight;
   downDistance=(lineNum-thisIndex-1)*lineHeight;
   $("#"+setting.linePre+dgid).css('background',setting.lineHighlight);

   dg_tips(left,top);
   $('body').css('cursor','move');
   unselect();
   setting.frame.mousemove(function(e){
    $("#dgf").css({"left":e.pageX+setting.tipsOffsetLeft+'px',"top":e.pageY+'px'});
   });
  });

  $('body').mouseup(function(e){
   if(thisLineTop>0){
    var moveDistance=e.pageY-thisLineTop;
    if(moveDistance<0){
if(thisIndex!=0){
moveDistance=Math.abs(moveDistance);
if(moveDistance>lineHeight/2){
       if(moveDistance>topDistance){
        focusIndex=0;
       }else{
        focusIndex=thisIndex-Math.ceil(moveDistance/lineHeight);
       }
       $("."+setting.dgLine).eq(focusIndex).before($("#"+setting.linePre+dgid));
       dg_update(thisIndex,focusIndex);
      }
     }
    }else{
     if(thisIndex!=lineNum-1){
      if(moveDistance>lineHeight/2+lineHeight){
       if(moveDistance>downDistance){
        focusIndex=lineNum-1;
       }else{
        focusIndex=thisIndex+Math.ceil(moveDistance/lineHeight)-1;
       }
       $("."+setting.dgLine).eq(focusIndex).after($("#"+setting.linePre+dgid));
       dg_update(thisIndex,focusIndex);
      }
     }
    }
    $("#dgf").remove();
    $("#"+setting.linePre+dgid).css('background','');
    dgid='';
    thisLineTop=0;
    $('body').css('cursor','default');
    onselect();
   }
  });

  function dg_update(thisIndex,focusIndex){
   dg_mask();
   var start=thisIndex var end=thisIndex var ids='',vals='';
for(var i=start;i<=end;i++){
ids+=i==start?$("."+setting.dgLine).eq(i).attr(setting.id):','+$("."+setting.dgLine).eq(i).attr(setting.id);
vals+=i==start?i:','+i;
}
$.getJSON(setting.JSONUrl,{'do':'changeorders','ids':ids,'vals':vals},function(d){
$("#dg_mask").remove();
});
}

function dg_mask(){
var W=setting.frame.outerWidth();
var H=setting.frame.outerHeight();
var top=setting.frame.offset().top;
var left=setting.frame.offset().left;
var mask="

正在使劲的保存...
";
   $('body').append(mask);
   $("#dg_mask").css({"background":"#999","position":'absolute',' width':W 'px','height':H 'px','line-height':H 'px','top':top 'px','left':left 'px','filter': 'alpha(opacity='setting.maskOpacity')','moz-opacity':setting.maskOpacity/100,'opacity':setting.maskOpacity/100,'text-align':'center','color':' #000'});
  }

  function dg_tips(left,top){
   var floatdiv="

移動一條記錄
";
   $('body').append(floatdiv);
  }

function unselect(){
   $('body').each(function() {          
    $(this).L('不能選擇'可以選擇 ' -user-select':'none',
     '-webkit-user-select':'none',
     'user-select':'none'
    'user-select':'none'
    ).each(function(
     this.onselectstart = function() { return false; };
    });
   });    $( this).attr('不可選擇', '').css({
 -webkit-user-select':'',
     '使用者選擇':''
    });
   });
  }
   });
  }
   });
  }


使用

複製程式碼程式碼如下: 
  

   

  
 
 
  
  
   
   
  
  
 
拖曳 姓名
div>
這裡是一行

關於拖曳排序就這麼多了,當然還可以把效果做得更漂亮一些,提示點更明確,有利於用戶體驗
相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板