Simple table sorting
You can double-click to edit custom edited rules
Dragable columns for column replacement
Push borders to scale column widths
The code copy is as follows:
<!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:#FFFFF; 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" cellpacing="1" cellpadding="0">
<head>
<tr>
<tdclass="tc" ><span>ID</span><div></div></td>
<tdclass="tc"><span>Select</span><div></div></td>
<td><span>Name</span><div></div></td>
<td ><span>Birthday</span><div></div></td>
<td ><span>Remarks</span><div></div></td>
</tr>
</head>
<tbody>
<tr>
<td>1</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>Missy</td>
<td>1982-05-27</td>
<td>Cups, all cups</td>
</tr>
<tr>
<td>3</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>Li Si</td>
<td>1983-06-27</td>
<td>Yeah, I have good skills in Warcraft</td>
</tr>
<tr>
<td>2</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>Wang Wu</td>
<td>1987-05-27</td>
<td>The Persian Prince's Blade is not bad</td>
</tr>
<tr>
<td>4</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>Zhao Liu</td>
<td>1988-05-27</td>
<td>My name is Zhao Liu</td>
</tr>
<tr>
<td>5</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>Zhu Ba</td>
<td>1984-05-27</td>
<td>Sweep and go to bed</td>
</tr>
<tr>
<td>6</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>Asdorf</td>
<td>1984-06-27</td>
<td>Asdorf dark room with lights</td>
</tr>
<tr>
<td>7</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>Cup</td>
<td>1984-06-27</td>
<td>Many cups</td>
</tr>
<tr>
<td>8</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>Dinnerware</td>
<td>1984-02-27</td>
<td>Many tableware</td>
</tr>
<tr>
<td>8</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>Washing utensils</td>
<td>1984-08-27</td>
<td>Many wash utensils</td>
</tr>
<tr>
<td>9</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>The squid is full of face</td>
<td>1984-12-27</td>
<td>10 almost one night</td>
</tr>
<tr>
<td>10</td>
<td><input type ="checkbox"><input name="ss" type="radio" /></td>
<td>Cialis Brother</td>
<td>1984-12-21</td>
<td>Hehe</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 ? "version" : i; break; }
}
b.version = vMark && RegExp("(?:" + vMark + ")[///: ]([//d.]+)").test(ua) ? RegExp.$1 : "0";
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 = []; //Record all references of tr in it
this.sortCol = null; //Record which column is sorting
this.inputtd = null; //Record which td is being edited
this.editconfig = {}; //Rules and tips for editing tables
this.tead = tab.getElementsByTagName('head')[0];
this.headTds = tab.getElementsByTagName('head')[0].getElementsByTagName('td'); //The commonly used dom collection can be referenced with a property.
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);
//I don't know the reason, if you don't set it, you will jump randomly
(Sys.ie6||Sys.chrome)&&(tab.width=tab.offsetWidth)
//Record those checkboxes, radio is selected. IE6 will not remember these states when doing dom operations.
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 used for editing
this.input = d.createElement('input');
this.input.type = "text";
this.input.className = 'edit';
// Used to display the dragging div
this.div = d.body.appendChild(d.createElement('div'));
this.div.className ="div";
//The vertical line displayed when zooming
this.line = d.body.appendChild(d.createElement('div'));
this.line.className = 'line';
this.line.style.top = objPos(tab).y +"px";
//Travel the set to make some settings
for(;i<l;i++){
//Bind the headhunter event that needs to be sorted
addListener(this.headTds[set[i].id],'click',Bind(this,this.sortTable,this.headTds[set[i].id],set[i].type));
//Define the required configuration for the column to the table that needs to be edited
set[i].edit&&(this.editconfig[set[i].id]={rule:set[i].edit.rule,message:set[i].edit.message});
}
//Put all tr into an array for sorting
for( i=0,l=rows.length;i<l;i++)
this.rows[i]=rows[i];
//Travel through all tds and make some settings
for( i=0,l=tabTads.length;i<l;i++){
// When using the td on the head, you should use it when dragging it with marks.
i<length&&tabTads[i].setAttribute('clos',i);
//Add edit attribute to the td that needs to be edited
i>=length&&this.editconfig[i%length]&&tabTads[i].setAttribute('edit',i%length);
}
//Binding drag and zoom operations
addListener(this.tead,'mousedown',BindAsEventListener(this,this.dragOrWidth));
//When dragging, the record moves to that column td
addListener(this.tead,'mouseover',BindAsEventListener(this,this.theadHover));
//well
addListener(this.tead,'mouseout',BindAsEventListener(this,this.teadOut));
//Binding editing event determines which table is edited based on e.srcElement or e.target
addListener(tab,'dblclick',BindAsEventListener(this,this.edit));
//Save the modified content when leaving input
addListener(this.input,'blur',Bind(this,this.save,this.input));
},
sortTable :function(td,type){ //td is the element n that clicked. Which column is the sorting type. What type is the sorting.
var fragment=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(/.$/,''));//Remove the identifier of the previous column sort
};
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; //Record which column is sorting
},
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;
//If the conditions do not meet the requirements, modify the prompt information
typeof status != "boolean"&&(editinfo.message = status);
if(status===true){
this.inputtd.innerHTML = this.input.value;
this.inputtd=null;
}else{
alert(editinfo.message);
//Use input.focus() directly under firefox and cannot be executed without executing 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;
//Execute drag and drop
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.head.setCapture(false):e.preventDefault();
}
//Perform width scaling
if(elem.nodeName.toLowerCase()==='div'){
Sys.ie?(e.cancelBubble=true):e.stopPropagation();
//If it is the last td, the div will not be scaled
if(this.headTds[this.headTds.length-1]===elem.parentNode)return
Sys.ie?this.head.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.headTds[closConfig.totd],'thover');
//No column replacement is performed in the same column
if(closConfig.td ===closConfig.totd)return;
//Check column replacement
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]);
}
//Reidentify the header
for(i=0,l=this.headTds.length;i<l;i++)
this.headTds[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 'Name input cannot be empty';
if(val.replace(/^/s+|/s+$/,'').length>10) return 'The length of the name cannot be greater than 10 characters';
if(!/^[/u4e00-/u9fa5a-z]+$/i.test(val)) return 'The name can only be entered in Chinese or letters';
return true;
};
function checkRemark(val){
if(val.replace(/^/s+$/g,'')==='') return 'Note input cannot be empty';
if(val.replace(/^/s+|/s+$/,'').length>15) return 'Remarks length cannot be greater than 15 characters';
if(!/^[/u4e00-/u9fa5/w/s]+$/i.test(val)) return 'Notes can only enter Chinese numeric underscore space';
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:"Enter date 1985-02-30 in this format"}},
{id:4,type:"string",edit:{rule:checkRemark,message:''}}
];
new Table($("tab"),set);
}
</script>
</body>
</html>
Known bugs:
IE6 Chinese text does not automatically wrap
It's really annoying that letters and numbers don't automatically wrap them under ie.
Clicking on the Chrome browser seems to be a big problem and getting local tests will be better