基础DOM结构
什么叫“完整的基础DOM结构”,这里“基础”的意思是指这个结构不依赖具体数据,不依赖Datagrid的view属性,只要存在Datagrid实例就会存在这样的基础DOM结构;而“完整”的意思是指在冻结列,冻结行,标题,footer,分页这些功能块都存在时候的DOM结构。要搞清楚Datagrid的工作原理,这个DOM结构必须要烂熟于胸的,我们直接来看这个“基础完整DOM结构”是什么样子的:
增加"datagrid-cell-check"样式类
if(col.checkBox) {
cc.push("class=\"datagrid-cell-check ");
}
//如果是普通列,增加"datagrid-cell-check"样式类
else {
cc.push("class=\"datagrid-cell " + col.cellClass);
}
cc.push("\">");
/**
* ck列光设置class是不够的,当突然还得append一个input进去才是真正的checkBox。此处未设置input的id,只设置了name属性。
* 我们注意到formatter属性对datagird自带的ck列同样不起作用。
*/
if(col.checkBox) {
cc.push("Box\" name=\"" + field + "\" value=\"" + (value != undefined ? value : "") + "\"/>");
}
//普通列
else {
/**
* 如果单元格有formatter,则将formatter后生成的DOM放到td>div里面
* 换句话说,td>div就是如来佛祖的五指山,而formatter只是孙猴子而已,猴子再怎么变化翻跟头,始终在佛祖手里。
*/
if(col.formatter) {
cc.push(col.formatter(value,rowIndex));
}
//操,这是最简单的简况了,将值直接放到td>div里面。
else {
cc.push(value);
}
}
cc.push("
");
cc.push("function updateTableRow(frozen) {
var fields = $(target).datagrid("getColumnFields",frozen);
//这个地方查找grid的数据主体表格(可能包含冻结列对应的主体表格和普通列对应的主体表格)
//getTr这个函数,我在博客上介绍过,请参考:http://www.easyui.info/archives/396.html
var tr = opts.finder.getTr(target,"body",(frozen ? 1 : 2));
var checked = tr.find("div.datagrid-cell-check input[type=checkbox]").is(":checked");
//这里调用了renderRow方法来重新获取当前行的html字符串
tr.html(this.renderRow.call(this,rows[rowIndex]));
tr.attr("style",style || "");
//更新的时候保留checkbox状态(包含两层信息:一是有ck列;二是ck列被之前就被选中)
if(checked) {
tr.find("div.datagrid-cell-check input[type=checkbox]")._propAttr("checked",true);
}
};
//更新冻结列对应的行
updateTableRow.call(this,true);
//更新普通列对应的行
updateTableRow.call(this,false);
//重新布局表格面板
$(target).datagrid("fixRowHeight",rowIndex);
},insertRow: function(target,row) {
var state = $.data(target,"datagrid");
//options
var opts = state.options;
//document of datagrid
var dc = state.dc;
var data = state.data;
//兼容无效的rowIndex,默认设置为在最后一行追加
if(rowIndex == undefined || rowIndex == null) {
rowIndex = data.rows.length;
}
//为啥不跟上面的条件并到一起,真是蛋疼
if(rowIndex > data.rows.length) {
rowIndex = data.rows.length;
}
/**
- 下移rows
- @param {boolean} frozen 是否为frozen部分
- @return {undefined} 无返回值
/
function moveDownRows(frozen) {
//1:冻结列部分;2:普通列部分
var whichBody = frozen ? 1 : 2;
for(var i = data.rows.length - 1; i >= rowIndex; i--) {
var tr = opts.finder.getTr(target,whichBody);
//注意这地方设置了tr的"datagrid-row-index"和"id"属性
tr.attr("datagrid-row-index",i + 1);
tr.attr("id",state.rowIdPrefix + "-" + whichBody + "-" + (i + 1));
//计算行号
if(frozen && opts.rownumbers) {
//因rowIndex从0开始,以及须插入位置以下的tr要统一下移,所以新行号为i+2
var rownumber = i + 2;
//有分页的话,行号还要加上分页数据
if(opts.pagination) {
rownumber += (opts.pageNumber - 1) opts.pageSize;
}
tr.find("div.datagrid-cell-rownumber").html(rownumber);
}
}
};
/** - 插入了,要插两个地方的哦(如果你是男人,你可以淫荡地笑一下)
- @param {boolean} frozen 是否是frozen部分
- @return {undefined} 未返回值
*/
function doInsert(frozen) {
var whichBody = frozen ? 1 : 2;
//这行代码,不知道是干嘛的,怕插入得太快而早早缴械,所以才故意拖延时间的么?
var columnFields = $(target).datagrid("getColumnFields",frozen);
//构造新插入行的id属性
var trId = state.rowIdPrefix + "-" + whichBody + "-" + rowIndex;
var tr = "<tr id=\"" + trId + "\" class=\"datagrid-row\" datagrid-row-index=\"" + rowIndex + "\"></tr>";
if(rowIndex >= data.rows.length) {
//如果已经有记录,则插入tr即可
if(data.rows.length) {
//嗯哼,getTr的这个用法不多哦,未传入行索引,第三个参数为"last",随便的意淫一下就知道是获取最后一行了
//然后再在最后一行后插入一行,注意了,这里用的后入式
opts.finder.getTr(target,"","last",whichBody).after(tr);
}
//如果表格尚无记录,则要生成表格,同时插入tr
else {
var cc = frozen ? dc.body1 : dc.body2;
cc.html("<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">" + tr + "</table>");
}
}
//在rowIndex + 1前准确无误地插入,注意了,这里是前入式。
else {
opts.finder.getTr(target,rowIndex + 1,whichBody).before(tr);
}
};
//下移frozen部分
moveDownRows.call(this,true);
//下移普通列部分
moveDownRows.call(this,false);
//插入frozen区
doInsert.call(this,true);
//插入普通区
doInsert.call(this,false);
//总数加1
data.total += 1;
//维护data.rows数组,这地方是插入一个数组元素了
data.rows.splice(rowIndex,row);
//刷新,其中包含了重新布局grid面板等复杂得一笔的操作
//插入本是件很简单愉快的事情,可是你得为其后果负上沉重的代价
this.refreshRow.call(this,/** - 删除行接口
- @param {DOM object} target datagrid实例的宿主table对应的DOM对象
- @param {number} rowIndex 行索引
- @return {undefined} 未返回值
*/
deleteRow: function(target,rowIndex) {
var state = $.data(target,"datagrid");
var opts = state.options;
var data = state.data;
function moveUpRows(frozen) {
var whichBody = frozen ? 1 : 2;
for(var i = rowIndex + 1; i < data.rows.length; i++) {
var tr = opts.finder.getTr(target,whichBody);
//"datagrid-row-index"和"id"<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>减一
tr.attr("datagrid-row-index",i - 1);
tr.attr("id",state.rowIdPrefix + "-" + whichBody + "-" + (i - 1));
if(frozen && opts.rownumbers) {
var rownumber = i;
if(opts.pagination) {
rownumber += (opts.pageNumber - 1) * opts.pageSize;
}
tr.find("div.datagrid-cell-rownumber").html(rownumber);
}
}
};
//移除行
opts.finder.getTr(target,rowIndex).remove();
//上移frozen区
moveUpRows.call(this,true);
//上移普通区
moveUpRows.call(this,false);
//记录数减一
data.total -= 1;
//维护data.rows数据
data.rows.splice(rowIndex,1);
},/**
- 默认的onBeforeRender事件 为空
- @param {DOM object} target datagrid实例的宿主table对应的DOM对象
- @param {array} rows 要插入的数据
- @return {undefined} 默认未返回值
*/
onBeforeRender: function(target,rows) {},/** - 默认的onAfterRender 隐藏footer里的行号和check
- @param {DOM object} target datagrid实例的宿主table对应的DOM对象
- @return {undefined} 未返回值
*/
onAfterRender: function(target) {
var opts = $.data(target,"datagrid").options;
if(opts.showFooter) {
var footer = $(target).datagrid("getPanel").find("div.datagrid-footer");
footer.find("div.datagrid-cell-rownumber,div.datagrid-cell-check").css("visibility","hidden");
}
}
};