亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

基于JQuery的列表拖動排序實現代碼

2019-11-20 21:55:25
字體:
來源:轉載
供稿:網友

要求

拖動排序,從名字就不難想像,就是按住一行數據拖到想要的排序位置,保存新的排序隊列。

思路

首先給列表行建立錨點,綁定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,每一行的classname
var lineHeight=Math.ceil(tbodyHeight/lineNum);

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

當mousedown事件觸發后,就要開始計算鼠標移動的距離,用于判斷該行到底要移動到什么位置

復制代碼 代碼如下:

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+dgid).css('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({
  '-moz-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':'',
  '-webkit-user-select':'',
  'user-select':''
 });
});

考慮到通用性,所以后面的代碼里,不會使用.disableSelection();

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

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

var moveDistance=e.pageY-thisLineTop;

根據不同的方向作不同的處理

復制代碼 代碼如下:

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

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

向上移動和向下移動使用了不同的插入方法,before和after,可以試著想一下為什么要使用before和after。

移動完了,還得把按下鼠標時使用的效果給去除掉

復制代碼 代碼如下:

$("#dgf").remove();//移除提示層
$("#"+setting.linePre+dgid).css('background','');//將高亮的行變為普通
dgid='';//將移動行的ID值空
thisLineTop=0;//將移動行的Top值至0
$('body').css('cursor','default');//更改鼠標手勢為默認

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

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

復制代碼 代碼如下:

/*
*
*  DragList.js
*  @author fuweiyi <fuwy@foxmail.com>

*/
(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<focusIndex?thisIndex:focusIndex;
   var end=thisIndex<focusIndex?focusIndex: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="<div id='dg_mask'><img src='"+setting.maskLoadIcon+"' alt='' /> 正在使勁的保存...</div>";
   $('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="<div id='dgf' style='padding:5px 10px;border:1px solid #444;background-color:#fff;filter:alpha(opacity="+setting.tipsOpacity+");moz-opacity:"+setting.tipsOpacity/100+";opacity:"+setting.tipsOpacity/100+";position:absolute;left:"+left+"px;top:"+top+"px;'>移動一條記錄</div>";
   $('body').append(floatdiv);
  }

  function unselect(){
   $('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; };
    });
   });
  }

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

使用

復制代碼 代碼如下:

<table cellpadding="5" cellspacing="0" class="listtable" id="listtable">
 <thead>
  <tr>
   <td class="td50">拖動</td>
   <td class="td220">名稱</td>
  </tr>
 </thead>
 <tbody id="drag_table">
  <!--{loop $lists $k $list}-->
  <tr id="list_{$list['id']}" action-id="{$list['id']}" class="drag_line">
   <td><div class="drag_orders" action-id="{$list['id']}"><img src="{SYS_URL}views/admin/images/move.png" alt="" /></div></div></td>
   <td>這里是一行</td>
  </tr>
  <!--{/loop}-->
 </tbody>
</table>
<script type="text/javascript">
$("#drag_table").DragList({
 dgLine:'drag_line',
 dgButton:'drag_orders',
 id:'action-id',
 linePre:'list_',
 JSONUrl:'{_ADMIN}?controller=contents&method=focus_form',
 maskLoadIcon:'{SYS_URL}views/admin/images/loading.gif'
});
</script>

參數主要是dgLine,dgButton,id,linePre和JSONUrl,通過看HTML代碼,應該不難理解。

關于拖動排序就是這么多了,當然還可以把效果做得更漂亮些,提示更清楚點,有助于用戶體驗

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久久网站| 国产精品极品美女粉嫩高清在线| 精品久久久精品| 欧美老女人在线视频| 久热99视频在线观看| 97国产精品视频人人做人人爱| 国产午夜精品久久久| 色婷婷综合成人| 成人免费看吃奶视频网站| 亚洲跨种族黑人xxx| 欧美大片在线免费观看| 国产美女被下药99| 国产欧美韩国高清| 亚洲性av网站| 91成品人片a无限观看| 亚洲一区二区三区在线视频| 成人乱色短篇合集| 57pao成人国产永久免费| 欧美性猛交xxxx乱大交极品| 欧美视频在线免费看| 日韩av电影免费观看高清| 亚洲精品电影在线| 成人久久18免费网站图片| 日韩在线观看免费全集电视剧网站| 欧美一区二区三区精品电影| 亚洲综合日韩中文字幕v在线| 欧美性xxxxxx| 日韩精品中文在线观看| 久久精品亚洲94久久精品| 久久精品国产欧美亚洲人人爽| 91久久精品国产91久久| 日韩高清免费观看| 亚洲国产中文字幕久久网| 日本道色综合久久影院| 亚洲欧美中文在线视频| 高潮白浆女日韩av免费看| 青青草原成人在线视频| 日韩精品中文字幕在线播放| 亚洲女同精品视频| 国产综合久久久久| 福利微拍一区二区| 国产91在线高潮白浆在线观看| 国产精品中文字幕在线观看| 黑人精品xxx一区一二区| 91精品国产99久久久久久| 国产精选久久久久久| 欧美性猛交xxxx偷拍洗澡| 国产精品欧美一区二区| 欧美精品亚州精品| 日韩视频免费在线观看| 欧美黑人狂野猛交老妇| 亚洲日本中文字幕| 亚洲欧美中文另类| 一区国产精品视频| 亚洲欧美激情一区| 久久成人18免费网站| 日韩专区中文字幕| 亚洲qvod图片区电影| 久久久久久中文| 55夜色66夜色国产精品视频| 青青青国产精品一区二区| 欧美视频一二三| 国产精品永久免费在线| 日韩欧美国产中文字幕| 精品久久久久久久久久久久久| 国产成人在线亚洲欧美| 精品少妇一区二区30p| 美女精品视频一区| 亚洲精品国产精品久久清纯直播| 日本午夜精品理论片a级appf发布| 久久免费国产精品1| 欧美极品美女视频网站在线观看免费| 欧美多人乱p欧美4p久久| 91国产高清在线| 色先锋久久影院av| 亚洲国产成人久久综合一区| 一区二区三区国产视频| 美女福利视频一区| 久久99热精品这里久久精品| 国产精品久久久久久久久影视| 一本一道久久a久久精品逆3p| 中文字幕亚洲欧美日韩2019| 亚洲理论片在线观看| 欧美精品福利在线| 国产精品久久久久久久久久东京| 日韩电影在线观看永久视频免费网站| 久久伊人精品天天| 久久久久久久久91| 国产精品综合久久久| 国产成人精品在线观看| 亚洲欧洲日本专区| 亚洲一区二区久久久| 亚洲国产精品字幕| 97精品国产97久久久久久免费| 欧美午夜激情在线| 欧美精品电影在线| 国产欧美亚洲精品| 亚洲影院色无极综合| 久久资源免费视频| 国产精品88a∨| 国产精品久久久91| 国产精品入口日韩视频大尺度| 欧美香蕉大胸在线视频观看| 国产精品视频一区二区高潮| 91国产视频在线播放| 亚洲福利视频在线| 亚洲最大av在线| 亚洲精品综合精品自拍| 国产精品久久久av| 亚洲色图av在线| 日韩av电影免费观看高清| 乱亲女秽乱长久久久| 日韩高清中文字幕| 日韩在线视频网| 亚洲欧美日韩精品久久| 综合136福利视频在线| 亚洲欧洲午夜一线一品| 欧美高清视频免费观看| 一区二区av在线| 国产精品麻豆va在线播放| 欧美理论片在线观看| 在线看欧美日韩| 日韩美女主播视频| 一本色道久久88综合亚洲精品ⅰ| 亚洲在线免费视频| 亚洲精品av在线播放| 欧美老女人性视频| 欧美成人免费一级人片100| 欧美激情精品久久久久久黑人| 综合国产在线观看| 91在线播放国产| 亚洲精品国产精品自产a区红杏吧| 国产不卡视频在线| 国内精品久久久久久久久| 久久久亚洲天堂| 国产一区二区三区精品久久久| 国产精品7m视频| 91av福利视频| 亚洲精品美女久久久久| 日韩电影免费观看在线| 国产男女猛烈无遮挡91| 日本a级片电影一区二区| 日本一区二区三区在线播放| 欧美一级视频在线观看| 青青久久av北条麻妃黑人| 精品免费在线观看| 国产亚洲精品久久久优势| 久久亚洲春色中文字幕| 国产一区二区三区在线播放免费观看| 98精品国产自产在线观看| 欧美国产精品va在线观看| 欧美日韩999| 8x拔播拔播x8国产精品| 久久久视频在线| 精品国产欧美一区二区五十路| 国产日韩欧美视频在线| 中文字幕亚洲欧美一区二区三区| 另类色图亚洲色图| 日韩欧美一区二区在线| 亚洲图片制服诱惑| 97国产精品免费视频| 亚洲美女黄色片| 亚洲女人天堂色在线7777| 精品国产乱码久久久久久虫虫漫画|