要求
拖曳排序,從名字就不難想像,就是按住一行資料拖曳到想要的排序位置,儲存新的排序佇列。
思路
先給清單行建立錨點,綁定mousedown和mouseup事件,當滑鼠移動到想要插入的位置時,將物件行移到目標行,然後對其經過的所有行進行排序處理。
思路很簡單,但這裡面還是有幾個問題要注意
1、移動到什麼位置可以視為要插入到目標行的位置。
2、移動出了頂端和底端時,判斷為第一和最後。
3、向上移動和向下移動的處理
解決
關於事件
Javascript裡滑鼠按下和放開事件為onmousedown,onmouseup,JQuery裡是mousedown,mouseup,所以,這裡使用mousedown和mouseup
首先,要知道介面有多少行,每一行有多高,因為要判斷滑鼠的移動距離
程式碼如下:
var tbodyHeight=setting.frame.outerHeight(); //setting.frame,父親物件
之所有要取lineNum(行數),除了計算行高外,還有個目的是要使用index(),透過序列索引值來進行移動行到目標位置
程式碼如下:
dgid=$(this).attr(>
dgid=$(this).attr(setting.id ); //移動行的ID,setting.id,是每一行用來標記ID的名稱
topDistance=thisIndex*lineHeight; //該行距離第一行頂端的距離
downDistance=(lineNum-thisIndex-1)*lineHeight; //該行距離最後一行底端的距離
thisLineTop,主要是用來和滑鼠移動位置進行高度計算,然後根據行高、索引值來判斷是移動到哪一行了。還有個作用是用來確定是否按在了移動錨點上,如果有值,說明是,那後面的mouseup就是成立的,如果沒有值,說明沒有按到錨點上,mouseup不執行任何操作。為什麼要這樣做呢?因為不管在頁面的什麼位置點滑鼠,都會觸發mouseup事件,如果沒有一個判斷,就會不停的執行,就會產生一些問題。
程式碼如下:
$("#" setting.linePre ('background',setting.lineHighlight); //高亮移動行
var left=e.pageX 20;
var top=e.pageY;
dg_tips(left,top); //建立一個提示圖層
$('body').css('cursor','move'); //更改頁面的滑鼠手勢
$("#dgf").css({"left":e. pageX setting.tipsOffsetLeft 'px',"top":e.pageY 'px'});
});
$('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':''
});
});
好了,下面是mouseup事件。這裡mouseup事件是綁定在body上的,因為mouseup如果只是綁定在錨點上,那麼當滑鼠移出錨點的時候,再放開滑鼠,會發現,這個mouseup事件不執行了,因為它會認為是別的物件的mouseup。所以,最保險的方法是用$('body').mouseup。這樣基本上就不會有問題。
mouseup觸發後,首先就要判斷thisLineTop是不是有值,防止無意義的事件執行。跟著判斷滑鼠移動的距離是正還是負,也就是向上移動還是向下移動。
var moveDistance=e.pageY-thisLineTop;
依不同的方向作不同的處理
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。
複製程式碼
基本上的情況就是這樣,主要問題就是在處理移動和判斷在哪裡插入的問題上。其它的都非常簡單。
下面給出完整的封裝程序,包括更新資料部分
複製程式碼
/*
*
* 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 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
for(var i=start;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':'',
'使用者選擇':''
});
});
}
});
}
});
}
使用

JavaScript核心數據類型在瀏覽器和Node.js中一致,但處理方式和額外類型有所不同。 1)全局對像在瀏覽器中為window,在Node.js中為global。 2)Node.js獨有Buffer對象,用於處理二進制數據。 3)性能和時間處理在兩者間也有差異,需根據環境調整代碼。

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

WebStorm Mac版
好用的JavaScript開發工具