javascript实现表格排序 编辑 拖拽 缩放
javascript实现表格排序 编辑 拖拽 缩放
发布时间:2016-12-30 来源:查字典编辑
摘要:简单表格排序可以双击编辑自定义编辑后的规则可拖动列进行列替换可推动边框进行列宽度的缩放复制代码代码如下:Tablebody{font-siz...

简单表格排序

可以双击编辑 自定义编辑后的 规则

可拖动列进行列替换

可推动边框进行列宽度的缩放

复制代码 代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

<title>Table</title>

</head>

<style type="text/css">

body{ font-size:12px}

#tab{ border-collapse: collapse;}

.edit{ height:16px; width:98%; background-color:#EFF7FF; font-size:12px; border:0px;}

#tab thead td{ background:url(http://images.cnblogs.com/cnblogs_com/wtcsy/192373/r_t.bmp);color:#183C94;word-break:break-all}

#tab tbody td{overflow:hidden;word-break:break-all;}

#tab td{border: 1px solid #CECFCE;height:20px;line-height:20px;vertical-align:middle; }

#tab td.tc{text-align:center;}

.div{width:10px;height:6px; border:1px solid #999999; background-color:#FFFFFF; position:absolute; display:none;}

.line{ width:2px; background-color:#999999; position:absolute; display:none}

.dr{height:100%;width:2px;background:#CECFCE;float:right;margin-right:-1px;cursor:sw-resize}

.r{float:right;}

.l{float:left;}

#tab thead td.thover{ background-image:url(http://album.hi.csdn.net/app_uploads/wtcsy/20081126/000054336.p.gif);background-repeat:repeat-x;}

</style>

<body >

<table id="tab" border="0" cellspacing="1" cellpadding="0">

<thead>

<tr>

<td width="80"class="tc" ><span>ID</span><div></div></td>

<td width="80"class="tc"><span>选中</span><div></div></td>

<td width="130"><span>姓名</span><div></div></td>

<td width="130" ><span>生日</span><div></div></td>

<td width="220" ><span>备注</span><div></div></td>

</tr>

</thead>

<tbody>

<tr>

<td height="16">1</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>小三</td>

<td>1982-05-27</td>

<td>杯具,全是杯具</td>

</tr>

<tr>

<td>3</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>李四</td>

<td>1983-06-27</td>

<td>恩恩我魔兽技术不错</td>

</tr>

<tr>

<td>2</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>王五</td>

<td>1987-05-27</td>

<td>波斯王子 时之刃还不错</td>

</tr>

<tr>

<td>4</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>赵六</td>

<td>1988-05-27</td>

<td>我叫赵六</td>

</tr>

<tr>

<td>5</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>朱八</td>

<td>1984-05-27</td>

<td>洗洗睡吧</td>

</tr>

<tr>

<td>6</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>阿斯多夫</td>

<td>1984-06-27</td>

<td>阿斯多夫暗室逢灯</td>

</tr>

<tr>

<td>7</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>杯具</td>

<td>1984-06-27</td>

<td>很多的杯具</td>

</tr>

<tr>

<td>8</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>餐具</td>

<td>1984-02-27</td>

<td>很多的餐具</td>

</tr>

<tr>

<td>8</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>洗具</td>

<td>1984-08-27</td>

<td>很多的洗具</td>

</tr>

<tr>

<td>9</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>内牛满面</td>

<td>1984-12-27</td>

<td>10快一晚</td>

</tr>

<tr>

<td>10</td>

<td><input type ="checkbox"><input name="ss" type="radio" /></td>

<td>犀利哥</td>

<td>1984-12-21</td>

<td>嘿嘿</td>

</tr>

</tbody>

</table>

<script language="javascript">

(function(window,undefined){

window.Sys = function (ua){

var b = {

ie: /msie/.test(ua) && !/opera/.test(ua),

opera: /opera/.test(ua),

safari: /webkit/.test(ua) && !/chrome/.test(ua),

firefox: /firefox/.test(ua),

chrome: /chrome/.test(ua)

},vMark = "";

for (var i in b) {

if (b[i]) { vMark = "safari" == i " : i; break; }

}

b.version = vMark && RegExp("(")[/: ]([d.]+)").test(ua) ";

b.ie6 = b.ie && parseInt(b.version, 10) == 6;

b.ie7 = b.ie && parseInt(b.version, 10) == 7;

b.ie8 = b.ie && parseInt(b.version, 10) == 8;

return b;

}(window.navigator.userAgent.toLowerCase());

window.Sys.ie6&&document.execCommand("BackgroundImageCache", false, true);

window.$ = function(Id){

return document.getElementById(Id);

};

window.addListener = function(element,e,fn){

!element.events&&(element.events = {});

element.events[e]&&(element.events[e][addListener.guid++]=fn)||(element.events[e] = {'0':fn});

element.addEventListener?element.addEventListener(e,fn,false):element.attachEvent("on" + e,fn);

};

window.addListener.guid = 1;

window.removeListener = function(element,e,fn){

var handlers = element.events[e],type;

if(fn){

for(type in handlers)

if(handlers[type]===fn){

element.removeEventListener?element.removeEventListener(e,fn,false):element.detachEvent("on" + e,fn);

delete handlers[type];

}

}else{

for(type in handlers){

element.removeEventListener?element.removeEventListener(e,handlers[type],false):element.detachEvent("on" + e,handlers[type]);

delete handlers[type];

}

}

};

window.setStyle = function(e,o){

if(typeof o=="string")

e.style.cssText=o;

else

for(var i in o)

e.style[i] = o[i];

};

var slice = Array.prototype.slice;

window.Bind = function(object, fun) {

var args = slice.call(arguments).slice(2);

return function() {

return fun.apply(object, args);

};

};

window.BindAsEventListener = function(object, fun,args) {

var args = slice.call(arguments).slice(2);

return function(event) {

return fun.apply(object, [event || window.event].concat(args));

}

};

//copy from jQ

window.Extend = function(){

var target = arguments[0] || {}, i = 1, length = arguments.length, deep = true, options;

if ( typeof target === "boolean" ) {

deep = target;

target = arguments[1] || {};

i = 2;

}

if ( typeof target !== "object" && Object.prototype.toString.call(target)!="[object Function]")

target = {};

for(;i<length;i++){

if ( (options = arguments[ i ]) != null )

for(var name in options){

var src = target[ name ], copy = options[ name ];

if ( target === copy )

continue;

if ( deep && copy && typeof copy === "object" && !copy.nodeType ){

target[ name ] = arguments.callee( deep, src || ( copy.length != null ? [ ] : { } ), copy );

}

else if(copy !== undefined)

target[ name ] = copy;

}

}

return target;

};

window.objPos = function(o){

var x = 0, y = 0;

do{x += o.offsetLeft;y += o.offsetTop;}while((o=o.offsetParent));

return {'x':x,'y':y};

}

window.Class = function(properties){

var _class = function(){return (arguments[0] !== null && this.initialize && typeof(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this;};

_class.prototype = properties;

return _class;

};

window.hasClass = function(element, className){

return element.className.match(new RegExp('(s|^)'+className+'(s|$)'));

} ;

window.addClass = function(element, className) {

!this.hasClass(element, className)&&(element.className += " "+className);

}

window.removeClass = function(element, className) {

hasClass(element, className)&&(element.className = element.className.replace(new RegExp('(s|^)'+className+'(s|$)'),' '));

}

})(window);

var Table = new Class({

options :{

minWidth : 62

},

initialize : function(tab,set){

this.table = tab;

this.rows = []; //里面记录所有tr的引用

this.sortCol = null; //记录哪列正在排序中

this.inputtd = null; //记录哪个td正在被编辑了

this.editconfig = {}; //编辑表格的规则和提示

this.thead = tab.getElementsByTagName('thead')[0];

this.theadTds = tab.getElementsByTagName('thead')[0].getElementsByTagName('td'); //常常用到的dom集合可以用个属性来引用

this.tbodyTds = tab.getElementsByTagName('tbody')[0].getElementsByTagName('td');

this.closConfig = {

on : false,

td : null,

totd : null

};

this.widthConfig = {

td : null,

nexttd : null,

x : 0,

tdwidth : 0,

nexttdwidth : 0

};

Extend(this,this.options);

//不知道原因 反正不设置就会乱跳

(Sys.ie6||Sys.chrome)&&(tab.width=tab.offsetWidth)

//记录那些checkbox,radio被选中了 ie6在做dom操作的时候不会记住这些状态

if(Sys.ie6){

this.checkbox = {};

var checkboxs = tab.getElementsByTagName('input'),i=0,l=checkboxs.length;

for(;i<l;i++)

(checkboxs[i].type=="checkbox"||checkboxs[i].type=="radio")&&

addListener(checkboxs[i],"click",Bind(this,function(elm,i){

elm.checked==true?(this.checkbox[i] = elm):(delete this.checkbox[i]);

},checkboxs[i],i));

};

var i=0,l=set.length,rows =tab.tBodies[0].rows,d=document,tabTads=tab.getElementsByTagName('td'),length=this.theadTds.length;

//编辑用的input

this.input = d.createElement('input');

this.input.type = "text";

this.input.className = 'edit';

//用于显示正在拖拽的div

this.div = d.body.appendChild(d.createElement('div'));

this.div.className ="div";

//进行缩放的时候显示的竖线

this.line = d.body.appendChild(d.createElement('div'));

this.line.className = 'line';

this.line.style.top = objPos(tab).y +"px";

//遍历set 做一些设置

for(;i<l;i++){

//给需要排序的猎头绑定事件

addListener(this.theadTds[set[i].id],'click',Bind(this,this.sortTable,this.theadTds[set[i].id],set[i].type));

//给需要编辑的表给列定义所需配置

set[i].edit&&(this.editconfig[set[i].id]={rule:set[i].edit.rule,message:set[i].edit.message});

}

//把 所有的tr放到一个数组 用于排序

for( i=0,l=rows.length;i<l;i++)

this.rows[i]=rows[i];

//遍历所有的td 做一些设置

for( i=0,l=tabTads.length;i<l;i++){

//将头部的td全部做上标记 拖拽的时候要用到

i<length&&tabTads[i].setAttribute('clos',i);

//将需要编辑的td添加edit属性

i>=length&&this.editconfig[i%length]&&tabTads[i].setAttribute('edit',i%length);

}

//绑定 拖拽 和缩放的操作

addListener(this.thead,'mousedown',BindAsEventListener(this,this.dragOrWidth));

//拖拽的时候 记录移动到了那列td上

addListener(this.thead,'mouseover',BindAsEventListener(this,this.theadHover));

//唉

addListener(this.thead,'mouseout',BindAsEventListener(this,this.theadOut));

//绑定编辑事件 根据e.srcElement or e.target去判断是哪个表格被编辑

addListener(tab,'dblclick',BindAsEventListener(this,this.edit));

//当离开input时候保存下修改的内容

addListener(this.input,'blur',Bind(this,this.save,this.input));

},

sortTable :function(td,type){ //td为点击的那个元素 n 为哪一列进行排序 type为进行什么类型的排序

var frag=document.createDocumentFragment(),span=td.getElementsByTagName('span')[0],str= span.innerHTML;

if(td===this.sortCol){

this.rows.reverse();

span.innerHTML =str.replace(/.$/,str.charAt(str.length-1)=="↓"") ;

}else{

this.rows.sort(this.compare(td.getAttribute('clos'),type));

span.innerHTML = span.innerHTML + "↑";

this.sortCol!=null&&(this.sortCol.getElementsByTagName('span')[0].innerHTML = this.sortCol.getElementsByTagName('span')[0].innerHTML.replace(/.$/,''));//把之前那列排序的标识去掉

};

for(var i=0,l=this.rows.length;i<l;i++)

frag.appendChild(this.rows[i]);

this.table.tBodies[0].appendChild(frag);

if(Sys.ie6){

for(var s in this.checkbox)

this.checkbox[s].checked = true;

}

this.sortCol = td; //记录哪一列正在排序中

},

compare :function(n,type){

return function (a1,a2){

var convert ={

int : function(v){return parseInt(v)},

float : function(v){return parseFloat(v)},

date : function(v){return v.toString()},

string : function(v){return v.toString()}

};

!convert[type]&&(convert[type]=function(v){return v.toString()});

a1 =convert[type](a1.cells[n].innerHTML);

a2 =convert[type](a2.cells[n].innerHTML);

return a1==a2?0:a1<a2?-1:1;

};

},

edit: function(e){

var elem = this.inputtd=e.srcElement || e.target;

if(!elem.getAttribute('edit'))return;

this.input.value = elem.innerHTML;

elem.innerHTML = "";

elem.appendChild(this.input);

this.input.focus();

},

save : function(elem){

var editinfo=this.editconfig[elem.parentNode.getAttribute('edit')],status={

"[object Function]" : 'length' in editinfo.rule&&editinfo.rule(this.input.value)||false,

"[object RegExp]" : 'test' in editinfo.rule&&editinfo.rule.test(this.input.value)||false

}[Object.prototype.toString.call(editinfo.rule)],_self=this;

//如果不符合条件 修改提示信息

typeof status != "boolean"&&(editinfo.message = status);

if(status===true){

this.inputtd.innerHTML = this.input.value;

this.inputtd=null;

}else{

alert(editinfo.message);

//firefox下 直接用input.focus()不会执行 用setTimeout可以执行

setTimeout(function(){_self.input.focus()},0);

}

},

theadHover : function(e){

var elem = e.srcElement || e.target;

if(elem.nodeName.toLowerCase() ==='td'&&this.closConfig.on){

this.closConfig.totd = elem.getAttribute('clos');

!hasClass(elem,'thover')&&addClass(elem,'thover');

}

},

theadOut : function(e){

var elem = e.srcElement || e.target;

if(elem.nodeName.toLowerCase() ==='td'&&this.closConfig.on)removeClass(elem,'thover')

},

dragOrWidth : function(e){

var elem = e.srcElement || e.target,widthConfig=this.widthConfig;

//执行拖拽

if(elem.nodeName.toLowerCase()==='td'){

this.closConfig.td = elem.getAttribute('clos');

addListener(document,'mousemove',BindAsEventListener(this,this.dragMove));

addListener(document,'mouseup',Bind(this,this.dragUp));

this.closConfig.on = true;

Sys.ie?this.thead.setCapture(false):e.preventDefault();

}

//执行宽度缩放

if(elem.nodeName.toLowerCase()==='div'){

Sys.ie?(e.cancelBubble=true):e.stopPropagation();

//如果是最后一个td里面的div 不进行缩放

if(this.theadTds[this.theadTds.length-1]===elem.parentNode)return

Sys.ie?this.thead.setCapture(false):e.preventDefault();

widthConfig.x = e.clientX;

widthConfig.td = elem.parentNode;

widthConfig.nexttd = widthConfig.td.nextSibling;

while(widthConfig.nexttd.nodeName.toLowerCase()!="td"){

widthConfig.nexttd = widthConfig.nexttd.nextSibling;

};

widthConfig.tdwidth = widthConfig.td.offsetWidth;

widthConfig.nexttdwidth = widthConfig.nexttd.offsetWidth;

this.line.style.height = this.table.offsetHeight +"px";

addListener(document,'mousemove',BindAsEventListener(this,this.widthMove));

addListener(document,'mouseup',Bind(this,this.widthUp));

}

},

dragMove : function(e){

window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

setStyle(this.div,{display:"block",left:e.clientX+9+"px",top:e.clientY+20+"px"});

},

dragUp :function(){

var closConfig = this.closConfig,rows = this.table.getElementsByTagName('tr'),td,n,o,i=0,l=rows.length;

this.div.style.display = "none";

removeListener(document,'mousemove');

removeListener(document,'mouseup');

Sys.ie&&this.thead.releaseCapture();

closConfig.on = false;

if(closConfig.totd===null)return;

removeClass(this.theadTds[closConfig.totd],'thover');

//在同一列 不进行列替换

if(closConfig.td === closConfig.totd)return;

//进行列替换 如果

if(closConfig.td*1+1===closConfig.totd*1){

n = closConfig.totd;

o = closConfig.td;

}else{

n = closConfig.td;

o = closConfig.totd;

}

for(;i<l;i++){

td = rows[i].getElementsByTagName('td');

rows[i].insertBefore(td[n],td[o]);

}

//重新标识表头

for(i=0,l=this.theadTds.length;i<l;i++)

this.theadTds[i].setAttribute('clos',i);

closConfig.totd=closConfig.td=null;

},

widthMove : function(e){

window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

var widthConfig = this.widthConfig,x = e.clientX - widthConfig.x,left = e.clientX,clientX=left;

if(clientX<widthConfig.x&&widthConfig.x - clientX>widthConfig.tdwidth-this.minWidth){

left = widthConfig.x - widthConfig.tdwidth+this.minWidth;

}

if(clientX>widthConfig.x&&clientX - widthConfig.x>widthConfig.nexttdwidth-this.minWidth){

left =widthConfig.x + widthConfig.nexttdwidth-this.minWidth;

}

setStyle(this.line,{display:"block",left:left+"px"});

},

widthUp : function(){

this.line.style.display = "none";

var widthConfig = this.widthConfig,x= parseInt(this.line.style.left) - widthConfig.x;

widthConfig.nexttd.style.width = widthConfig.nexttdwidth -x -1 +'px';

widthConfig.td.style.width = widthConfig.tdwidth + x -1 +'px';

Sys.ie&&this.thead.releaseCapture();

removeListener(document,'mousemove');

removeListener(document,'mouseup');

}

});

window.onload = function(){

function checkName(val){

if(val.replace(/^s+$/g,'')==='') return '姓名输入不能为空';

if(val.replace(/^s+|s+$/,'').length>10) return '姓名长度不能大于10个字符';

if(!/^[u4e00-u9fa5a-z]+$/i.test(val)) return '姓名只能输入中文或者是字母';

return true;

};

function checkRemark(val){

if(val.replace(/^s+$/g,'')==='') return '备注输入不能为空';

if(val.replace(/^s+|s+$/,'').length>15) return '备注长度不能大于15个字符';

if(!/^[u4e00-u9fa5ws]+$/i.test(val)) return '备注只能输入中文数字下划线空格';

return true;

}

var set = [

{id:0,type:"int"},

{id:2,type:"string",edit:{rule:checkName,message:''}},

{id:3,type:"date",edit:{rule:/^d{4}-d{2}-d{2}$/,message:"按这中格式输入日期 1985-02-30"}},

{id:4,type:"string",edit:{rule:checkRemark,message:''}}

];

new Table($("tab"),set);

}

</script>

</body>

</html>

已知BUG:

ie6下 中文不自动换行

非ie下字母和数字也不自动换行确实让人恼火

chrome浏览器下点击运行好像问题很大 拿到本地测试会比较好

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新Javascript教程学习
热门Javascript教程学习
编程开发子分类