写了个类似TreeGrid的控件
程序员文章站
2022-05-15 09:54:59
...
最近公司要求写个类似TreeGrid的控件,先上效果图:
其实就是传入一个tree数据集合,将需要合并的数据进行合并展示。合并的列可能是一列也可能是多列。
提前申明 需要依赖jquery
调用代码:
initQueryGrid:function(){
//获取表格展示的列
function getColumn() {
var arr = [
{display: "序号", width: 60, type: "sysOrderNum", name: null, textAlign: "center"},
{display: "分类", width: 180, type: "treeLevel", name: "type", textAlign: "center"},
{display: "流程模板名称", width: 129, type: "content", name: "workflowSubject", textAlign: "left"},
{display: "对应表单", width: 139, type: "content", name: "formSubject", textAlign: "left"},
{display: "所属人", width: '*', type: "content", name: "memberName", textAlign: "left"},
{display: "流程归属部门", width: 179, type: "content", name: "workflowDepartmentName", textAlign: "left"}
];
return arr;
}
var grid = new GoTreeGrid({
parent: "queryGrid",
width: (document.body.clientWidth-228)*0.98,
managerName: "test",
managerMethod: "test",
colModel: getColumn()
});
grid.addTreeRows(returnVal);
},
组件代码如下:
//GoTreeGrid对象
function GoTreeGrid(options) {
this.parent = options["parent"];
this.managerName = options["managerName"];
this.managerMethod = options["managerMethod"];
//放置后台列名称,主要是用于从后台返回数据中获取相应字段的值
this.colNames = [];
this.alignCols = [];
this.colTypes = [];
//每列的列宽
this.colWidths = [];
this.rowIndex = 0;
this.colIndex = 0;
this.levelColWid = 100;
this.tableId = __uid();
//当前所有列对应的宽度 包含分类列
this.curColWid = 0;
this.contentCols = [];
if (options["width"] && (options["width"] + "").indexOf("%") < 0) {
this.pWidth = parseFloat(options["width"]);
} else {
//如果为空则设置为100%
if(options["width"]==null){
options["width"]='100%';
}
$('<table class="goTreeGrid" id="test_header" style="width: '+options["width"]+'%"><tbody><tr><td>#</td></tr></tbody></table>').appendTo($("#" + this.parent));
this.pWidth = $("#test_header").get(0).offsetWidth;
$("#test_header").remove();
alert( this.pWidth)
}
//初始化标头数组
this.columns = this.initTreeLevels(options["colModel"]);
this.starsCols = [];
this._createGridHeader();
this._createGridBody();
////表格的头进行合并操作后,会有像素差,所有需要进行修正
if (_isIE8) {
this._initColspanWidth();
}
}
/**
* 动态追加5列 层级作为分类使用
* @param colModels
* @returns {Array}
*/
GoTreeGrid.prototype.initTreeLevels = function (colModels) {
var newColumns = [];
this.conStartColNum = 0;
for (var num = 0; num < colModels.length; num++) {
newColumns.push(colModels[num]);
if (colModels[num]["type"] == "treeLevel") {
this.levelColWid = colModels[num]["width"];
this.addNewColspan(newColumns, 5);
this.conStartColNum = num + 5;
}
}
return newColumns;
}
GoTreeGrid.prototype.addNewColspan = function (newColumns, nums) {
for (var num = 0; num < nums; num++) {
newColumns.push({display: "#cspan", width: 0, type: "colspanCol", name: null, textAlign: "center"})
}
}
/*
* 表格的头进行合并操作后,会有像素差,所有需要进行修正
* */
GoTreeGrid.prototype._initColspanWidth = function () {
var gridObj = this;
$(".header td").each(function () {
var colSpan = $(this).prop("colspan");
if (colSpan != null && colSpan > 1) {
var colIndex = $(this).attr("colIndex");
var oldWidth = gridObj.colWidths[colIndex - 1];
$($(this).parent().prev().find("th").get(colIndex - 1)).css("width", parseFloat(oldWidth) + parseFloat((colSpan - 2)));
}
})
}
//创建grid表格头
GoTreeGrid.prototype._createGridHeader = function () {
var gridObj = this;
var htmls = [], headerLabel = [], headerLabels = []
htmls.push('<table class="goTreeGrid" style="table-layout: fixed;width:' + this.pWidth + 'px;" id="' + this.tableId + '_header" cellpadding="0" cellspacing="0" ><tbody>');
htmls.push('<tr style="height: auto;">');
$.each(this.columns, function (index, item) {
if (item["type"] === "content") {
gridObj.contentCols.push(item);
}
//获取每列的列宽
var colWidth = gridObj.getColWidth(item["width"], index);
//缓存起每列的列宽信息
gridObj.colWidths.push(colWidth);
gridObj.colNames.push(item["name"]);
if (item["type"] == "colspanCol") {
htmls.push('<th class="colspanCol" colIndex="' + (index + 1) + '" style="height: 0px; width: ' + colWidth + 'px;"></th>');
} else {
htmls.push('<th colIndex="' + (index + 1) + '" style="height: 0px; width: ' + colWidth + 'px;"></th>');
}
});
htmls.push('</tr>');
htmls.push('<tr class="header">');
$.each(this.columns, function (index, item) {
gridObj.colIndex = ++gridObj.colIndex;
var textStr = item["textAlign"] ? "style='text-align:" + item["textAlign"] + "'" : "";
//将字体的摆放位置缓存起来
gridObj.alignCols.push(textStr);
//将每列的数据类型存放起来
gridObj.colTypes.push(item["type"] || "field");
if (item["display"] === "#cspan") {
htmls.push('<td colIndex="' + (index + 1) + '" class="_cspan_col" ' + textStr + '><div>' + item["display"] + '</div></td>');
} else {
htmls.push('<td colIndex="' + (index + 1) + '" ' + textStr + '><div>' + item["display"] + '</div></td>');
}
});
htmls.push('</tr>');
htmls.push('</tbody></table>');
$(htmls.join("")).appendTo($("#" + this.parent));
////如果传入的列中包含*号的列 则需要重新计算
if (this.starsCols.length > 0) {
this._initStartsColWidth();
}
this._initHeaderLabel();
}
/*
* 初始化表格头的label 因为可能存在列头的合并操作
* */
GoTreeGrid.prototype._initHeaderLabel = function () {
$("._cspan_col").each(function () {
var prevObj = $(this).prev();
var colSpan = prevObj.attr("colspan") || 1;
prevObj.attr("colSpan", ++colSpan);
$(this).remove();
});
}
/*
* 因为有列宽设置了* 则需要重新计算*号对应的列 需要将剩余的宽度都分给相应的*号列
* */
GoTreeGrid.prototype._initStartsColWidth = function () {
//只有有剩余列宽才需要重新计算
var gridObj = this;
var syWid = parseFloat(this.pWidth) - this.curColWid;
if (syWid > 0) {
var colSyWid = syWid / this.starsCols.length;
var newWidth = (100 + colSyWid);
$.each(this.starsCols, function (index, colIndex) {
$($("#" + gridObj.tableId + '_header').find("th").get(colIndex)).css("width", newWidth + "px");
gridObj.colWidths[colIndex] = newWidth;
newWidth = null;
})
}
}
//获取列宽
GoTreeGrid.prototype.getColWidth = function (width, colIndex) {
if (width == parseFloat(width)) {
this.curColWid = this.curColWid + parseFloat(width) + 1;
return width;
} else {
this.starsCols.push(colIndex);
this.curColWid = this.curColWid + parseFloat(100);
return 100;
}
}
GoTreeGrid.prototype._createGridBody = function () {
var gridObj = this;
var htmls = [];
var headerHt = $($("#" + this.tableId + '_header').find("tr").get(0));
htmls.push('<table style="table-layout: fixed;width:' + this.pWidth + 'px;" class="goTreeGridBody" id="' + this.tableId + '_body" cellpadding="0" cellspacing="0" ><tbody>');
htmls.push('<tr style="height: auto;">' + headerHt.html() + '</tr>');
htmls.push('</tbody></table>');
$(htmls.join("")).appendTo($("#" + this.parent));
//如果传入的列中包含*号的列 则需要重新计算
if (this.starsCols.length > 0) {
this._initStartsColWidth();
}
}
//添加一行数据
GoTreeGrid.prototype.addRow = function (rowsData) {
var htmls = [];
this._addRow(htmls, [rowsData], 0);
$(htmls.join()).appendTo($("#" + this.tableId + '_body'))
}
GoTreeGrid.prototype.getEmptyRow = function (rowsData) {
var htmls = [];
for (var num = 0; num < this.colNames.length; num++) {
htmls.push(" ");
}
return htmls.join("");
}
GoTreeGrid.prototype.addEmptyRow = function (rowSize) {
var htmls = [];
var rowIds = [];
for (var num = 0; num < rowSize; num++) {
rowIds.push(this._addRow(htmls, [this.getEmptyRow()], 0));
}
$(htmls.join("")).appendTo($("#" + this.tableId + '_body'));
return rowIds;
}
/*
* 添加行数据
* */
GoTreeGrid.prototype._addRow = function (htmls, rowsDataAry, rowIndex) {
this.rowIndex = ++this.rowIndex;
var odd = this.rowIndex % 2 == 1 ? "even" : "odd";
var rowId = __uid();
var gridObj = this;
htmls.push('<tr class="dataTr ' + odd + '" id="' + rowId + '" rowIndex="' + this.rowIndex + '">');
$.each(rowsDataAry[rowIndex], function (index, item) {
//获取当前列的 字体摆放样式
var colStyle = gridObj.alignCols[index];
//获取当前列的类型
var curColType = gridObj.colTypes[index];
if (curColType == "sysOrderNum") {
htmls.push('<td id="' + rowId + '_' + index + '" ' + colStyle + '><div>' + gridObj.rowIndex + '</div></td>');
} else {
htmls.push('<td id="' + rowId + '_' + index + '" ' + colStyle + '><div>' + item + '</div></td>');
}
});
htmls.push('</tr>');
gridObj = null;
htmls = null;
return rowId;
}
//添加多行数据
GoTreeGrid.prototype.addRows = function (rowsDataAry) {
var htmls = [];
for (var num = 0; num < rowsDataAry.length; num++) {
this._addRow(htmls, rowsDataAry, num);
}
$(htmls.join()).appendTo($("#" + this.tableId + '_body'))
}
/*
* 根据colNum来进行列分组操作
* */
function rowSpanToPre(trObjs, startNum, colIndex, index) {
if (startNum - 2 - index >= 0) {
var theLastTrId = $(trObjs[startNum - 1 - index]).attr("id");
var theLastTd = $("#" + theLastTrId + "_" + colIndex);
var preTrId = $(trObjs[startNum - 2 - index]).attr("id");
var preTd = $("#" + preTrId + "_" + colIndex);
if (theLastTd.html() != null && theLastTd.html() == preTd.html()) {
preTd.attr("rowspan", parseFloat(parseFloat(theLastTd.attr("rowspan") || 1) + parseFloat(preTd.attr("rowspan") || 1)));
theLastTd.remove();
}
}
}
/*
* 对行内内容进行分组
* */
GoTreeGrid.prototype.groupBy = function (colIndex) {
var trObjs = $("#" + this.tableId + '_body .dataTr');
var startNum = trObjs.length;
var index = 0;
for (var num = startNum; num >= 0; num--) {
rowSpanToPre(trObjs, startNum, colIndex, index);
index = index + 1;
}
};
/*
* 添加数据进body
* */
GoTreeGrid.prototype._addRowToBody = function (para) {
//加载数据
this.populate(para);
};
/*
ajax数据加载
* */
GoTreeGrid.prototype.ajaxgridLoad = function (para) {
//加载数据
this.populate(para);
};
GoTreeGrid.prototype.populate = function (tempMap, backFun) { // get latest data
if (this.loading) {
return true;
}
var pageSize = ($.ctx && $.ctx._pageSize) ? $.ctx._pageSize : 20;
var fp = {
page: 1,
size: pageSize
};
var gridObj = this;
this.loading = true;
callBackendMethod(this.managerName, this.managerMethod, tempMap, {
success: function (returnVal) {
//gridObj.addRows(returnVal);
if (backFun != null) {
backFun();
} else {
gridObj.addTreeRows(returnVal);
}
}
});
};
GoTreeGrid.prototype._getNodeMaxSize = function (jsonObj) {
return jsonObj["allCount"];
};
GoTreeGrid.prototype.getMaxRecordSize = function (itemObj, sonFields, jsonObj) {
var sonList = itemObj[sonFields];
var obj = this;
if (sonList != null && sonList.length > 0) {
if (sonList.length > jsonObj["maxRecordSize"]) {
jsonObj["maxRecordSize"] = sonList.length;
}
$.each(sonList, function (index, item) {
obj.getMaxRecordSize(item, sonFields, jsonObj);
});
}
};
GoTreeGrid.prototype._addSonTreeRows = function (treeObj, sonFields, rowIds, parentNode) {
var marRowSize = this._getNodeMaxSize(treeObj, sonFields, treeObj);
var startNum = parentNode["startNum"];
for (var num1 = startNum; num1 < startNum + marRowSize; num1++) {
$("#" + rowIds[num1] + "_" + treeObj["level"]).html(treeObj["name"]);
++parentNode["startNum"];
var obj = this;
treeObj["startNum"] = 0;
var sonList = treeObj[sonFields];
if (sonList != null && sonList.length > 0) {
$.each(sonList, function (index, item) {
if (item.type == "category") {
obj._addSonTreeRows(item, sonFields, rowIds, treeObj);
} else {
//如果是模板界面 则需要加载模板字段信息
for (var cols = 0; cols < obj.contentCols.length; cols++) {
obj.setCellValue(rowIds[startNum] + "_" + obj.getContentColIndex(cols), obj.getContent(item, cols));
}
}
treeObj["startNum"] = ++treeObj["startNum"];
});
}
}
};
GoTreeGrid.prototype._addTreeRows = function (treeObj, sonFields) {
treeObj["startNum"] = 0;
treeObj["maxRecordSize"] = 1;
var marRowSize = this._getNodeMaxSize(treeObj, sonFields, treeObj);
var rowIds = this.addEmptyRow(3);
for (var num1 = 0; num1 < rowIds.length; num1++) {
$("#" + rowIds[num1] + "_" + treeObj["level"]).html(treeObj["name"]);
}
var obj = this;
var sonList = treeObj[sonFields];
if (sonList != null && sonList.length > 0) {
$.each(sonList, function (index, item) {
if (item.type == "category") {
obj._addSonTreeRows(item, sonFields, rowIds, treeObj);
} else {
//如果是模板界面 则需要加载模板字段信息
for (var cols = 0; cols < obj.contentCols.length; cols++) {
obj.setCellValue(rowIds[treeObj["startNum"]] + "_" + obj.getContentColIndex(cols), obj.getContent(item, cols));
}
}
});
}
};
/*
* 根据序号获取当前对象对应字段的值
* */
GoTreeGrid.prototype.getContent = function (itemobj, cols) {
var field = this.contentCols[cols];
return itemobj[field["name"]];
};
GoTreeGrid.prototype.getContentColIndex = function (cols) {
return parseFloat(this.conStartColNum) + cols + 1;
};
/*
* 设置cell的value
* */
GoTreeGrid.prototype.setCellValue = function (cellId, cellContent) {
if (cellContent == null || cellContent == "null") {
cellContent = "";
}
$("#" + cellId).html(cellContent);
};
/**
* 获取当前行数据 从json对象中获取
* @param jsonObj
*/
GoTreeGrid.prototype.getRowData = function (jsonObj) {
};
GoTreeGrid.prototype.getMaxLevel = function (itemObj, sonFields) {
if (this.datas[itemObj["level"]] == null) {
this.datas[itemObj["level"]] = [];
}
this.datas[itemObj["level"]].push(itemObj);
var obj = this;
var sonList = itemObj[sonFields];
if (sonList != null && sonList.length > 0) {
var sonLevel = itemObj["level"] + 1;
if (sonLevel > obj.level) {
obj.level = sonLevel;
}
$.each(sonList, function (index, item) {
item["level"] = sonLevel;
obj.getMaxLevel(item,sonFields);
});
}
};
/**
* 清空所有数据 并将表格信息还原
* @param jsonObj
*/
GoTreeGrid.prototype.clearAll = function () {
var index = 0;
//只有body的行数大于1 才需要进行移除操作
if ($("#" + this.tableId + "_body tr").length > 1) {
$("#" + this.tableId + "_body tr").each(function (els) {
if (index != 0) {
$(this).remove();
}
index++;
})
}
//重新定义列表头信息
this._initThAgain(this.typeLevel - 1, 0);
};
GoTreeGrid.prototype.addTreeRows = function (treeRecords) {
this.clearAll();
var obj = this;
obj.typeLevel = 1;
this.datas = {};
this.level = 0;
//循环计算出最大的层级
$.each(treeRecords, function (index, itemObj) {
treeRecords[index]["level"] = 1;
obj.getMaxLevel(treeRecords[index], "childWorkflowPropertyList");
});
//如果层级大于3 是需要进行特殊显示处理。 类别的层级为最大层级减1
if (obj.level > 1) {
obj.typeLevel = obj.level - 1;
obj._initThAgain(this.typeLevel - 1, obj.levelColWid);
}
$.each(treeRecords, function (index, itemObj) {
obj._addTreeRows(treeRecords[index], "childWorkflowPropertyList");
});
//对分类信息进行分组操作。
for (var num = 1; num <= obj.typeLevel; num++) {
obj.groupBy(num);
}
};
/**
* 重新定义表格头的信息
* @private
*/
GoTreeGrid.prototype._initThAgain = function (colspanCols, colspanWidth) {
//调整colspan信息
var colSpanCols = $("#" + this.tableId + "_header").find(".colspanCol");
for (var num = 0; num < colspanCols; num++) {
//如果传入的宽度 不等于本身宽度 则需要进行修改
var elOldWid = $(colSpanCols.get(num)).css("width");
if (elOldWid != colspanWidth) {
$(colSpanCols.get(num)).css("width", colspanWidth);
//计算this.curColWid的目的是 为了重新计算*号列的列宽
this.curColWid = this.curColWid + parseFloat(colspanWidth);
}
}
//重新计算*号对应的列宽
this._initStartsColWidth();
var headerHt = $($("#" + this.tableId + '_header').find("tr").get(0));
//移除以前的标头信息 再追加最新th信息
$($("#" + this.tableId + "_body").find("tr").get(0)).remove();
$('<tr style="height: auto;">' + headerHt.html() + '</tr>').appendTo($("#" + this.tableId + "_body tbody"));
};