欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

写了个类似TreeGrid的控件

程序员文章站 2022-05-15 09:54:59
...

最近公司要求写个类似TreeGrid的控件,先上效果图:
写了个类似TreeGrid的控件

其实就是传入一个tree数据集合,将需要合并的数据进行合并展示。合并的列可能是一列也可能是多列。

写了个类似TreeGrid的控件

提前申明 需要依赖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"));
};
相关标签: 控件