JavascriptDataGrid Beta版,实现了一些基本功能,高级一些的数据处理方面的下一步实现。
效果演示地址:http://www.robchen.cn/datagrid/
<!
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=utf-8" />
< title > DataGrid </ title >
< script type ="text/javascript" > ...
var Class = ...{
create:function()...{
return function()...{
this.initialize.apply(this,arguments);
}
}
}
function $(id)...{
return document.getElementById(id);
}
String.prototype.trim = function()...{
return this.replace(/^s+|s+$/g,"");
}
String.prototype.escapeHTML = function()...{
var str = this;
str = str.replace("<","<");
str = str.replace(">",">");
str = str.replace(" "," ");
str = str.replace(/ ?/g,"<br/>");
return str;
}
String.prototype.unescapeHTML = function()...{
var str = this;
str = str.replace(/<s*brs*/?s*>/gi," ");
str = str.replace("<","<");
str = str.replace(">",">");
str = str.replace(" "," ");
return str;
}
//DataItem--------------------------------------------------------------
var DataItem = Class.create();
DataItem.prototype = ...{
initialize:function(td,name,dataRow/**//*,readOnly,mulitline*/)...{
this.dom = td;
this.dataRow = dataRow;
this.dom.dataItem = this;
if(arguments.length >= 4)...{
this.readOnly = arguments[3];
}
if(arguments.length >= 5)...{
this.mulitline = arguments[4];
}
this.name = name;
this.value = td.innerHTML.trim();
var _this = this;
this.dom.ondblclick = function()...{
_this.editMode();
}
},
dataRow:null,
readOnly:false,
mode:0,//0:read,1:edit
input:null,
name:null,
value:null,
dom:null,
mulitline:false,
readMode:function()...{
if(this.mode == 0)return;
this.mode == 0;
if(this.input == null)return;
this.value = this.dom.innerHTML = this.input.value.escapeHTML();
this.input = null;
},
editMode:function()...{
if((this.mode == 1 && this.input != null) || this.readOnly)return;
this.mode = 1;
if(this.mulitline)...{
var input = document.createElement("textarea");
input.style.height = this.dom.offsetHeight + 20 + "px";
}else...{
var input = document.createElement("input");
input.type = "text";
}
input.style.width = this.dom.offsetWidth + 20 + "px";
input.value = this.value.unescapeHTML();
this.dom.innerHTML = "";
this.dom.appendChild(input);
this.input = input;
this.input.focus();
var _this = this;
this.input.onblur = function()...{
_this.readMode();
}
}
}
//-----------------------------------------------------------------------
//DataRow----------------------------------------------------------------
var DataRow = Class.create();
DataRow.prototype = ...{
initialize:function(tr,dataGrid)...{
this.dom = tr;
this.dataGrid = dataGrid;
tr.dataRow = this;
var tds = tr.getElementsByTagName("td");
this.items = new Array();
this.selector = tds[0].getElementsByTagName("input")[0];
this.selector.dataRow = this;
for(var i = 1; i < tds.length ; i ++)...{
this.items.push(new DataItem(tds[i],this.dataGrid.cols.items[i],this));
}
},
dom:null,
dataGrid:null,
items:null,
getIndex:function()...{
for(var i = 0; i < this.dataGrid.rows.length; i ++)...{
if(this.dataGrid.rows[i] == this)return i;
}
},
remove:function()...{
this.dom.parentNode.removeChild(this.dom);
this.dataGrid.rows.splice(this.getIndex(),1);
}
}
//DataGrid--------------------------------------------------------------
var DataGrid = Class.create();
DataGrid.prototype = ...{
initialize:function(table)...{
this.dom = table;
table.dataGrid = this;
var trs = table.getElementsByTagName("tr");
this.cols.dom = trs[0];
this.cols.items = new Array();
this.cols.sort = ...{};
var tds = trs[0].getElementsByTagName("td");
this.selector = tds[0].getElementsByTagName("input")[0];
var _this = this;
this.selector.onclick = function()...{
for(var i = 0; i < _this.rows.length; i ++)...{
_this.rows[i].selector.checked = this.checked;
}
}
for(var i = 1; i < tds.length; i ++)...{
this.cols.items.push(tds[i].innerHTML);
this.cols.sort[tds[i].innerHTML] = -1;
}
this.rows = new Array();
for(var i = 1; i < trs.length; i ++)...{
this.rows.push(new DataRow(trs[i],this));
}
},
selector:null,
dom:null,
rows:null,
cols:...{
items:null,
sort:null,
dom:null
},
reBuild:function()...{
var tbody = this.dom.getElementsByTagName("tbody")[0];
this.dom.removeChild(tbody);
tbody = document.createElement("tbody");
tbody.appendChild(this.cols.dom);
for(var i = 0; i < this.rows.length; i ++)...{
tbody.appendChild(this.rows[i].dom);
}
this.dom.appendChild(tbody);
},
insertRow:function(args)...{
if(typeof arguments[1] != "undefined")...{
var index = arguments[1];
if(index < 0)index = 0;
if(index > this.rows.length)index = this.rows.length;
}else...{
var index = this.rows.length;
}
var tr = document.createElement("tr");
var td = document.createElement("td");
var selector = document.createElement("input");
selector.type = "checkbox";
td.appendChild(selector);
tr.appendChild(td);
for(var i = 0; i < this.cols.items.length; i ++)...{
var td = document.createElement("td");
if(args[i])td.innerHTML = args[i];
tr.appendChild(td);
}
var tbody = this.dom.getElementsByTagName("tbody")[0];
if(index == this.rows.length)...{
tbody.appendChild(tr);
this.rows.push(new DataRow(tr,this));
}else...{
tbody.insertBefore(tr,this.rows[index].dom);
this.rows.splice(index,0,new DataRow(tr,this));
}
},
selectedRows:function()...{
var s = new Array();
for(var i = 0; i < this.rows.length; i ++)...{
if(this.rows[i].selector.checked)s.push(this.rows[i]);
}
return s;
},
deleteRows:function(args)...{
if(typeof args == "undefined" || args.length == 0)return;
var a = new Array();
a = a.concat(args).sort().reverse();
var str = a.join(",");
var reg = /(^|,)([^,]+)((,d+)+)?,2/g;
while(str.match(reg))...{
str=str.replace(reg,"$1$2$3");
}
a = str.replace(/,+/g,",").split(",");
for(var i = 0; i < a.length; i ++)...{
try...{
this.rows[a[i]].remove();
}catch(e)...{}
}
},
sort:function(index,order)...{//order,1:asc,-1:desc
this.rows.sort(function(x,y)...{
if(x.items[index].value > y.items[index].value)...{
return order;
}else...{
return -1 * order;
}
});
this.reBuild();
},
customSort:function(index,formula)...{
this.rows.sort(formula);
this.reBuild();
},
exchange:function(rowA,rowB)...{
var temp = rowA;
this.rows[rowB.getIndex()] = rowA;
this.rows[temp.getIndex()] = rowB;
this.reBuild();
}
}
</ script >
< style > ...
body {...}{font-size:9pt;}
#grid {...}{border:1px solid #cccccc;}
#grid tr td {...}{border:1px solid #cccccc;}
#grid .head {...}{color:#FFFFFF;background-color:#999999;cursor:pointer;text-align:center;}
#test {...}{margin:30px 0 0 0;}
#test input {...}{width:40px;height:15px;border:1px solid #cccccc;margin:0 0 0 3px;}
</ style >
< script type ="text/javascript" > ...
window.onload = function()...{
var t = new DataGrid(document.getElementById("grid"));
$("b1").onclick = function()...{t.insertRow([$("i1").value,$("i2").value,$("i3").value],$("i4").value);};
$("b2").onclick = function()...{t.deleteRows($("d1").value.split(","));};
$("b3").onclick = function()...{t.exchange(t.rows[$("e1").value],t.rows[$("e2").value]);};
$("b4").onclick = function()...{
var s = t.selectedRows();
for(var i = 0; i < s.length; i ++)...{
s[i].remove();
}
}
var cols = t.cols.dom.getElementsByTagName("td");
for(var i = 1;i < cols.length; i ++)...{
cols[i].onclick = function()...{
var n = 0;
var temp = this;
while(temp.previousSibling)...{
temp = temp.previousSibling;
n ++;
}
var sort = 1;
if(t.cols.sort[this.innerHTML])...{
t.cols.sort[this.innerHTML] = sort = -1 * t.cols.sort[this.innerHTML];
}else...{
t.cols.sort[this.innerHTML] = sort;
}
t.sort(n-1,sort);
};
}
}
</ script >
</ head >
< body >
< table cellpadding ="0" cellspacing ="2" id ="grid" >
< tbody >
< tr class ="head" >< td >< input type ="checkbox" /></ td >< td > A </ td >< td > B </ td >< td > C </ td ></ tr >
< tr >< td >< input type ="checkbox" /></ td >< td > 22222 </ td >< td > dddd </ td >< td > 22222 </ td ></ tr >
< tr >< td >< input type ="checkbox" /></ td >< td > 33333 </ td >< td > cccc </ td >< td > 33333 </ td ></ tr >
< tr >< td >< input type ="checkbox" /></ td >< td > 22222 </ td >< td > dddd </ td >< td > 22222 </ td ></ tr >
< tr >< td >< input type ="checkbox" /></ td >< td > 33333 </ td >< td > cccc </ td >< td > 33333 </ td ></ tr >
</ tbody >
</ table >
< div id ="test" >
(所有行数从0开始计算) < br />
编辑:双击单元格进行数据编辑。 < br />
插入行:数据 < input type ="text" id ="i1" value ="a" />< input type ="text" id ="i2" value ="b" />< input type ="text" id ="i3" value ="c" /> 插入位置 < input type ="text" id ="i4" value ="0" />< button id ="b1" > 插入 </ button >< br />
删除指定行数据(多行用,隔开) < input type ="text" id ="d1" value ="0,1" />< button id ="b2" > 删除 </ button >< br />
删除选定行 < button id ="b4" > 删除 </ button >< br />
交换:将第 < input type ="text" id ="e1" value ="0" /> 行与第 < input type ="text" id ="e2" value ="1" /> 行交换 < button id ="b3" > 交换 </ button >< br />
排序:点击标头进行默认排序,提供自定义排序接口 < br />
灵活的编程支持,可扩展性强.(下一步实现:数据绑定,数据提取等)
</ div >
</ body >
</ html >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head >
< meta http-equiv ="Content-Type" content ="text/html; charset=utf-8" />
< title > DataGrid </ title >
< script type ="text/javascript" > ...
var Class = ...{
create:function()...{
return function()...{
this.initialize.apply(this,arguments);
}
}
}
function $(id)...{
return document.getElementById(id);
}
String.prototype.trim = function()...{
return this.replace(/^s+|s+$/g,"");
}
String.prototype.escapeHTML = function()...{
var str = this;
str = str.replace("<","<");
str = str.replace(">",">");
str = str.replace(" "," ");
str = str.replace(/ ?/g,"<br/>");
return str;
}
String.prototype.unescapeHTML = function()...{
var str = this;
str = str.replace(/<s*brs*/?s*>/gi," ");
str = str.replace("<","<");
str = str.replace(">",">");
str = str.replace(" "," ");
return str;
}
//DataItem--------------------------------------------------------------
var DataItem = Class.create();
DataItem.prototype = ...{
initialize:function(td,name,dataRow/**//*,readOnly,mulitline*/)...{
this.dom = td;
this.dataRow = dataRow;
this.dom.dataItem = this;
if(arguments.length >= 4)...{
this.readOnly = arguments[3];
}
if(arguments.length >= 5)...{
this.mulitline = arguments[4];
}
this.name = name;
this.value = td.innerHTML.trim();
var _this = this;
this.dom.ondblclick = function()...{
_this.editMode();
}
},
dataRow:null,
readOnly:false,
mode:0,//0:read,1:edit
input:null,
name:null,
value:null,
dom:null,
mulitline:false,
readMode:function()...{
if(this.mode == 0)return;
this.mode == 0;
if(this.input == null)return;
this.value = this.dom.innerHTML = this.input.value.escapeHTML();
this.input = null;
},
editMode:function()...{
if((this.mode == 1 && this.input != null) || this.readOnly)return;
this.mode = 1;
if(this.mulitline)...{
var input = document.createElement("textarea");
input.style.height = this.dom.offsetHeight + 20 + "px";
}else...{
var input = document.createElement("input");
input.type = "text";
}
input.style.width = this.dom.offsetWidth + 20 + "px";
input.value = this.value.unescapeHTML();
this.dom.innerHTML = "";
this.dom.appendChild(input);
this.input = input;
this.input.focus();
var _this = this;
this.input.onblur = function()...{
_this.readMode();
}
}
}
//-----------------------------------------------------------------------
//DataRow----------------------------------------------------------------
var DataRow = Class.create();
DataRow.prototype = ...{
initialize:function(tr,dataGrid)...{
this.dom = tr;
this.dataGrid = dataGrid;
tr.dataRow = this;
var tds = tr.getElementsByTagName("td");
this.items = new Array();
this.selector = tds[0].getElementsByTagName("input")[0];
this.selector.dataRow = this;
for(var i = 1; i < tds.length ; i ++)...{
this.items.push(new DataItem(tds[i],this.dataGrid.cols.items[i],this));
}
},
dom:null,
dataGrid:null,
items:null,
getIndex:function()...{
for(var i = 0; i < this.dataGrid.rows.length; i ++)...{
if(this.dataGrid.rows[i] == this)return i;
}
},
remove:function()...{
this.dom.parentNode.removeChild(this.dom);
this.dataGrid.rows.splice(this.getIndex(),1);
}
}
//DataGrid--------------------------------------------------------------
var DataGrid = Class.create();
DataGrid.prototype = ...{
initialize:function(table)...{
this.dom = table;
table.dataGrid = this;
var trs = table.getElementsByTagName("tr");
this.cols.dom = trs[0];
this.cols.items = new Array();
this.cols.sort = ...{};
var tds = trs[0].getElementsByTagName("td");
this.selector = tds[0].getElementsByTagName("input")[0];
var _this = this;
this.selector.onclick = function()...{
for(var i = 0; i < _this.rows.length; i ++)...{
_this.rows[i].selector.checked = this.checked;
}
}
for(var i = 1; i < tds.length; i ++)...{
this.cols.items.push(tds[i].innerHTML);
this.cols.sort[tds[i].innerHTML] = -1;
}
this.rows = new Array();
for(var i = 1; i < trs.length; i ++)...{
this.rows.push(new DataRow(trs[i],this));
}
},
selector:null,
dom:null,
rows:null,
cols:...{
items:null,
sort:null,
dom:null
},
reBuild:function()...{
var tbody = this.dom.getElementsByTagName("tbody")[0];
this.dom.removeChild(tbody);
tbody = document.createElement("tbody");
tbody.appendChild(this.cols.dom);
for(var i = 0; i < this.rows.length; i ++)...{
tbody.appendChild(this.rows[i].dom);
}
this.dom.appendChild(tbody);
},
insertRow:function(args)...{
if(typeof arguments[1] != "undefined")...{
var index = arguments[1];
if(index < 0)index = 0;
if(index > this.rows.length)index = this.rows.length;
}else...{
var index = this.rows.length;
}
var tr = document.createElement("tr");
var td = document.createElement("td");
var selector = document.createElement("input");
selector.type = "checkbox";
td.appendChild(selector);
tr.appendChild(td);
for(var i = 0; i < this.cols.items.length; i ++)...{
var td = document.createElement("td");
if(args[i])td.innerHTML = args[i];
tr.appendChild(td);
}
var tbody = this.dom.getElementsByTagName("tbody")[0];
if(index == this.rows.length)...{
tbody.appendChild(tr);
this.rows.push(new DataRow(tr,this));
}else...{
tbody.insertBefore(tr,this.rows[index].dom);
this.rows.splice(index,0,new DataRow(tr,this));
}
},
selectedRows:function()...{
var s = new Array();
for(var i = 0; i < this.rows.length; i ++)...{
if(this.rows[i].selector.checked)s.push(this.rows[i]);
}
return s;
},
deleteRows:function(args)...{
if(typeof args == "undefined" || args.length == 0)return;
var a = new Array();
a = a.concat(args).sort().reverse();
var str = a.join(",");
var reg = /(^|,)([^,]+)((,d+)+)?,2/g;
while(str.match(reg))...{
str=str.replace(reg,"$1$2$3");
}
a = str.replace(/,+/g,",").split(",");
for(var i = 0; i < a.length; i ++)...{
try...{
this.rows[a[i]].remove();
}catch(e)...{}
}
},
sort:function(index,order)...{//order,1:asc,-1:desc
this.rows.sort(function(x,y)...{
if(x.items[index].value > y.items[index].value)...{
return order;
}else...{
return -1 * order;
}
});
this.reBuild();
},
customSort:function(index,formula)...{
this.rows.sort(formula);
this.reBuild();
},
exchange:function(rowA,rowB)...{
var temp = rowA;
this.rows[rowB.getIndex()] = rowA;
this.rows[temp.getIndex()] = rowB;
this.reBuild();
}
}
</ script >
< style > ...
body {...}{font-size:9pt;}
#grid {...}{border:1px solid #cccccc;}
#grid tr td {...}{border:1px solid #cccccc;}
#grid .head {...}{color:#FFFFFF;background-color:#999999;cursor:pointer;text-align:center;}
#test {...}{margin:30px 0 0 0;}
#test input {...}{width:40px;height:15px;border:1px solid #cccccc;margin:0 0 0 3px;}
</ style >
< script type ="text/javascript" > ...
window.onload = function()...{
var t = new DataGrid(document.getElementById("grid"));
$("b1").onclick = function()...{t.insertRow([$("i1").value,$("i2").value,$("i3").value],$("i4").value);};
$("b2").onclick = function()...{t.deleteRows($("d1").value.split(","));};
$("b3").onclick = function()...{t.exchange(t.rows[$("e1").value],t.rows[$("e2").value]);};
$("b4").onclick = function()...{
var s = t.selectedRows();
for(var i = 0; i < s.length; i ++)...{
s[i].remove();
}
}
var cols = t.cols.dom.getElementsByTagName("td");
for(var i = 1;i < cols.length; i ++)...{
cols[i].onclick = function()...{
var n = 0;
var temp = this;
while(temp.previousSibling)...{
temp = temp.previousSibling;
n ++;
}
var sort = 1;
if(t.cols.sort[this.innerHTML])...{
t.cols.sort[this.innerHTML] = sort = -1 * t.cols.sort[this.innerHTML];
}else...{
t.cols.sort[this.innerHTML] = sort;
}
t.sort(n-1,sort);
};
}
}
</ script >
</ head >
< body >
< table cellpadding ="0" cellspacing ="2" id ="grid" >
< tbody >
< tr class ="head" >< td >< input type ="checkbox" /></ td >< td > A </ td >< td > B </ td >< td > C </ td ></ tr >
< tr >< td >< input type ="checkbox" /></ td >< td > 22222 </ td >< td > dddd </ td >< td > 22222 </ td ></ tr >
< tr >< td >< input type ="checkbox" /></ td >< td > 33333 </ td >< td > cccc </ td >< td > 33333 </ td ></ tr >
< tr >< td >< input type ="checkbox" /></ td >< td > 22222 </ td >< td > dddd </ td >< td > 22222 </ td ></ tr >
< tr >< td >< input type ="checkbox" /></ td >< td > 33333 </ td >< td > cccc </ td >< td > 33333 </ td ></ tr >
</ tbody >
</ table >
< div id ="test" >
(所有行数从0开始计算) < br />
编辑:双击单元格进行数据编辑。 < br />
插入行:数据 < input type ="text" id ="i1" value ="a" />< input type ="text" id ="i2" value ="b" />< input type ="text" id ="i3" value ="c" /> 插入位置 < input type ="text" id ="i4" value ="0" />< button id ="b1" > 插入 </ button >< br />
删除指定行数据(多行用,隔开) < input type ="text" id ="d1" value ="0,1" />< button id ="b2" > 删除 </ button >< br />
删除选定行 < button id ="b4" > 删除 </ button >< br />
交换:将第 < input type ="text" id ="e1" value ="0" /> 行与第 < input type ="text" id ="e2" value ="1" /> 行交换 < button id ="b3" > 交换 </ button >< br />
排序:点击标头进行默认排序,提供自定义排序接口 < br />
灵活的编程支持,可扩展性强.(下一步实现:数据绑定,数据提取等)
</ div >
</ body >
</ html >