javascript 拖動(dòng)表格行實(shí)現(xiàn)代碼
行拖動(dòng)的實(shí)現(xiàn)思路非常簡單,選中一行,往上拖就與上面的行交換位置,往下拖就與下面的行交換位置。問題是如何得到交換行。我見過一個(gè)非常詳細(xì)的教程,它會(huì)把表格里的每一行的高度與Y坐標(biāo)計(jì)算出來,換言之,都時(shí)是比較e.pageX是否在[rowTop,rowBottom]區(qū)間之內(nèi)。但這也帶來第二個(gè)問題,有多少行就有多個(gè)這樣的區(qū)間。于是解法就變成取事件源對(duì)象,然后再往上取其父對(duì)象,如果其父對(duì)象是TR元素,就取其[rowTop,rowBottom]區(qū)間....思路非常直接,同時(shí)也客觀做出一個(gè)限制——不能使用代理拖動(dòng)。先不談是拖動(dòng)代理還是拖動(dòng)實(shí)物,光是在移動(dòng)鼠標(biāo)的過程要做的計(jì)算量就非常大,幸好還在IE的承受范圍之內(nèi)。有更好的方法嗎?
人之所以先入為主,因?yàn)樗臀罩@么幾把鎖匙。如果他手上的鎖匙非常多時(shí),他在開門時(shí)就會(huì)稍微停下來,認(rèn)真挑選了。因此熟悉掌握越多的原生API就越好,我們就才獲取更優(yōu)的選項(xiàng)。換一個(gè)思路,在拖動(dòng)時(shí)(mousedown)保存當(dāng)前行及其樣式與坐標(biāo),拖動(dòng)中取得鼠標(biāo)所在位置上的元素,這個(gè)元素是使用一個(gè)巧妙的API取得document.elementFromPoint(x,y)。通常情況,我們?nèi)〉玫氖荰D,當(dāng)然如果你在里面塞進(jìn)一個(gè)DIV,那就是DIV羅。然后我們?cè)偃〉闷銽R元素,然后比較mousedown時(shí)保存的TR元素是不是同一個(gè)元素,不是同一個(gè)元素,我們才做進(jìn)一步的操作。這時(shí)我們就要判其是向上移向下移,簡單的減法而已。接著是交換兩行,使用insertBefore。最后當(dāng)mouseup時(shí),還原行的樣式就是!由于沒有復(fù)雜的坐標(biāo)計(jì)算,整個(gè)程式出奇的高效!
完整演示代碼
<!doctype html>
<html>
<head>
<title>表格行拖動(dòng)</title>
<script>
window.onload = function(){
//綁定事件
var addEvent = document.addEventListener ? function(el,type,callback){
el.addEventListener( type, callback, !1 );
} : function(el,type,callback){
el.attachEvent( "on" + type, callback );
}
//移除事件
var removeEvent = document.removeEventListener ? function(el,type,callback){
el.removeEventListener( type, callback );
} : function(el,type,callback){
el.detachEvent( "on" + type, callback);
}
//精確獲取樣式
var getStyle = document.defaultView ? function(el,style){
return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
} : function(el,style){
style = style.replace(/\-(\w)/g, function($, $1){
return $1.toUpperCase();
});
return el.currentStyle[style];
}
var dragManager = {
clientY:0,
draging:function(e){//mousemove時(shí)拖動(dòng)行
var dragObj = dragManager.dragObj;
if(dragObj){
e = e || event;
if(window.getSelection){//w3c
window.getSelection().removeAllRanges();
}else if(document.selection){
document.selection.empty();//IE
}
var y = e.clientY;
var down = y > dragManager.clientY;//是否向下移動(dòng)
var tr = document.elementFromPoint(e.clientX,e.clientY);
if(tr && tr.nodeName == "TD"){
tr = tr.parentNode
dragManager.clientY = y;
if( dragObj !== tr){
tr.parentNode.insertBefore(dragObj, (down ? tr.nextSibling : tr));
}
};
}
},
dragStart:function(e){
e = e || event;
var target = e.target || e.srcElement;
if(target.nodeName === "TD"){
target = target.parentNode;
dragManager.dragObj = target;
if(!target.getAttribute("data-background")){
var background = getStyle(target,"background-color");
target.setAttribute("data-background",background)
}
//顯示為可移動(dòng)的狀態(tài)
target.style.backgroundColor = "#ccc";
target.style.cursor = "move";
dragManager.clientY = e.clientY;
addEvent(document,"mousemove",dragManager.draging);
addEvent(document,"mouseup",dragManager.dragEnd);
}
},
dragEnd:function(e){
var dragObj = dragManager.dragObj
if (dragObj) {
e = e || event;
var target = e.target || e.srcElement;
if(target.nodeName === "TD"){
target = target.parentNode;
dragObj.style.backgroundColor = dragObj.getAttribute("data-background");
dragObj.style.cursor = "default";
dragManager.dragObj = null;
removeEvent(document,"mousemove",dragManager.draging);
removeEvent(document,"mouseup",dragManager.dragEnd);
}
}
},
main:function(el){
addEvent(el,"mousedown",dragManager.dragStart);
}
}
var el = document.getElementById("table");
dragManager.main(el);
}
</script>
<style>
.table{
width:60%;
border: 1px solid red;
border-collapse: collapse;
}
.table td{
border: 1px solid red;
height: 20px;
}
</style>
</head>
<body>
<h1>表格行拖動(dòng)</h1>
<table id="table" class="table">
<tbody>
<tr>
<td>1</td>
<td>One</td>
<td>dom.require</td>
</tr>
<tr id="2" >
<td class="2">2</td>
<td>Two</td>
<td>ControlJS </td>
</tr>
<tr id="3" >
<td class="3">3</td>
<td>Three</td>
<td>HeadJS</td>
</tr>
<tr id="4" >
<td class="4">4</td>
<td>Four</td>
<td>LAB.js</td>
</tr>
<tr id="5" >
<td class="5">5</td>
<td>Five</td>
<td>$script.js</td>
</tr>
<tr id="6" >
<td class="6">6</td>
<td>Six</td>
<td>NBL.js</td>
</tr>
</tbody>
</table>
</body>
</html>
核心代碼
window.onload = function(){
//綁定事件
var addEvent = document.addEventListener ? function(el,type,callback){
el.addEventListener( type, callback, !1 );
} : function(el,type,callback){
el.attachEvent( "on" + type, callback );
}
//移除事件
var removeEvent = document.removeEventListener ? function(el,type,callback){
el.removeEventListener( type, callback );
} : function(el,type,callback){
el.detachEvent( "on" + type, callback);
}
//精確獲取樣式
var getStyle = document.defaultView ? function(el,style){
return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
} : function(el,style){
style = style.replace(/\-(\w)/g, function($, $1){
return $1.toUpperCase();
});
return el.currentStyle[style];
}
var dragManager = {
clientY:0,
draging:function(e){//mousemove時(shí)拖動(dòng)行
var dragObj = dragManager.dragObj;
if(dragObj){
e = e || event;//清除選區(qū)
if(window.getSelection){//w3c
window.getSelection().removeAllRanges();
}else if(document.selection){
document.selection.empty();//IE
}
var y = e.clientY;
var down = y > dragManager.clientY;//是否向下移動(dòng)
var tr = document.elementFromPoint(e.clientX,e.clientY);
if(tr && tr.nodeName == "TD"){
tr = tr.parentNode
dragManager.clientY = y;
if( dragObj !== tr){
tr.parentNode.insertBefore(dragObj, (down ? tr.nextSibling : tr));
}
};
}
},
dragStart:function(e){
e = e || event;
var target = e.target || e.srcElement;
if(target.nodeName === "TD"){
target = target.parentNode;
dragManager.dragObj = target;
if(!target.getAttribute("data-background")){
var background = getStyle(target,"background-color");
target.setAttribute("data-background",background)
}
//顯示為可移動(dòng)的狀態(tài)
target.style.backgroundColor = "#ccc";
target.style.cursor = "move";
dragManager.clientY = e.clientY;
addEvent(document,"mousemove",dragManager.draging);
addEvent(document,"mouseup",dragManager.dragEnd);
}
},
dragEnd:function(e){
var dragObj = dragManager.dragObj
if (dragObj) {
e = e || event;
var target = e.target || e.srcElement;
if(target.nodeName === "TD"){
target = target.parentNode;
dragObj.style.backgroundColor = dragObj.getAttribute("data-background");
dragObj.style.cursor = "default";
dragManager.dragObj = null;
removeEvent(document,"mousemove",dragManager.draging);
removeEvent(document,"mouseup",dragManager.dragEnd);
}
}
},
main:function(el){
addEvent(el,"mousedown",dragManager.dragStart);
}
}
var el = document.getElementById("table");
dragManager.main(el);
}
實(shí)現(xiàn)代碼二
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head >
<title>無標(biāo)題頁</title>
</head>
<body>
<table id="tb1" border="1" cellpadding="3">
<tr>
<th>移動(dòng)</th>
<th>數(shù)據(jù)</th>
<th>數(shù)據(jù)</th>
<th>數(shù)據(jù)</th>
</tr>
<tr>
<td>*</td>
<td>11111111111</td>
<td>sdgergserhserhserh</td>
<td>awegaw</td>
</tr>
<tr>
<td>*</td>
<td>222222222</td>
<td>serherwwwwww</td>
<td>fafafff</td>
</tr>
<tr>
<td>*</td>
<td>333333333</td>
<td>qqqqqqqwewer</td>
<td>yukyuk</td>
</tr>
</table>
<script type="text/javascript">
var curTr = null;
var tb1 = document.getElementById('tb1');
var trs = tb1.getElementsByTagName('tr');
tb1.onselectstart = function(){
if(curTr){
document.selection.empty(); return true;
}
};
for(var i=1; i<trs.length; i++) {
var tds = trs[i].getElementsByTagName('td');
tds[0].style.cursor = 'move';
tds[0].onmousedown = function(){
curTr = this.parentNode;
curTr.style.backgroundColor = '#eff';
};
tds[0].onmouseover = function() {
if(curTr && curTr != this.parentNode) {
this.parentNode.swapNode(curTr);
}
}
}
document.body.onmouseup = function(){
if(curTr){
curTr.style.backgroundColor = '';
curTr = null;
}
};
</script>
</body>
</html>
注:不兼容firefox,在IE和chrome下測(cè)試通過哦。
相關(guān)文章
JavaScript第一個(gè)分水嶺之?dāng)?shù)組的基本操作
Arrays(數(shù)組) 數(shù)組是一個(gè)固定長度的存儲(chǔ)相同數(shù)據(jù)類型的數(shù)據(jù)結(jié)構(gòu),數(shù)組中的元素被存儲(chǔ)在一段連續(xù)的內(nèi)存空間中,下面這篇文章主要給大家介紹了關(guān)于JavaScript第一個(gè)分水嶺之?dāng)?shù)組的基本操作,需要的朋友可以參考下2022-04-04
JS在Chrome瀏覽器中showModalDialog函數(shù)返回值為undefined的解決方法
這篇文章主要介紹了JS在Chrome瀏覽器中showModalDialog函數(shù)返回值為undefined的解決方法,涉及javascript針對(duì)谷歌瀏覽器事件判定相關(guān)操作技巧,需要的朋友可以參考下2016-08-08
javascript實(shí)現(xiàn)文字跑馬燈效果
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)文字跑馬燈效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06
刷新頁面實(shí)現(xiàn)方式總結(jié)(HTML,ASP,JS)
多種方法實(shí)現(xiàn)頁面的刷新代碼2008-11-11
微信小程序動(dòng)態(tài)添加和刪除組件的現(xiàn)實(shí)
這篇文章主要介紹了微信小程序動(dòng)態(tài)添加和刪除組件的現(xiàn)實(shí),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
可以用鼠標(biāo)拖動(dòng)的DIV實(shí)現(xiàn)思路及代碼
DIV可以拖動(dòng)的效果,想必大家都有見到過吧,在本文也為大家實(shí)現(xiàn)一個(gè)不錯(cuò)的可以用鼠標(biāo)拖動(dòng)的div,感興趣的各位不要錯(cuò)過2013-10-10
javascript數(shù)組遍歷的方法實(shí)例分析
這篇文章主要介紹了javascript數(shù)組遍歷的方法,結(jié)合實(shí)例形式分析了javascript數(shù)組遍歷及相關(guān)的some、every、filter、map等方法的使用技巧,需要的朋友可以參考下2016-09-09
JS數(shù)組合并push與concat區(qū)別分析
這篇文章主要介紹了JS數(shù)組合并push與concat區(qū)別,結(jié)合實(shí)例形式分析了JavaScript中針對(duì)數(shù)組合并操作使用push與concat的區(qū)別,需要的朋友可以參考下2015-12-12

