基於jQuery的TreeGrid組件

基於jQuery的TreeGrid組件

複製代碼
/**
 * @author 陳舉民
 * @version 1.0
 * @link http://chenjumin.iteye.com/blog/419522
 */
TreeGrid = function (_config) {
    _config = _config || {};

    var s = "";
    var rownum = 0;
    var __root;

    var __selectedData = null;
    var __selectedId = null;
    var __selectedIndex = null;

    var folderOpenIcon = (_config.folderOpenIcon || TreeGrid.FOLDER_OPEN_ICON);
    var folderCloseIcon = (_config.folderCloseIcon || TreeGrid.FOLDER_CLOSE_ICON);
    var defaultLeafIcon = (_config.defaultLeafIcon || TreeGrid.DEFAULT_LEAF_ICON);

    //顯示錶頭行
    drowHeader = function () {
        s += "<tr class='header' height='" + (_config.headerHeight || "25") + "'>";
        var cols = _config.columns;
        for (i = 0; i < cols.length; i++) {
            var col = cols[i];
            s += "<td align='" + (col.headerAlign || _config.headerAlign || "center") + "' width='" + (col.width || "") + "'>" + (col.headerText || "") + "</td>";
        }
        s += "</tr>";
    }

    //遞歸顯示數據行
    drowData = function () {
        var rows = _config.data;
        var cols = _config.columns;
        drowRowData(rows, cols, 1, "");
    }

    //局部變量i、j必須要用 var 來聲明,否則,後續的數據無法正常顯示
    drowRowData = function (_rows, _cols, _level, _pid) {
        var folderColumnIndex = (_config.folderColumnIndex || 0);

        for (var i = 0; i < _rows.length; i++) {
            var id = _pid + "_" + i; //行id
            var row = _rows[i];

            s += "<tr id='TR" + id + "' data-pid='" + ((_pid == "") ? "0" : ("TR" + _pid)) + "' data-open='Y' data-row=\"" + TreeGrid.json2str(row) + "\" data-rowIndex='" + rownum++ + "'>";
            for (var j = 0; j < _cols.length; j++) {
                var col = _cols[j];
                s += "<td align='" + (col.dataAlign || _config.dataAlign || "left") + "'";

                //層次縮進
                if (j == folderColumnIndex) {
                    s += " style='text-indent:" + (parseInt((_config.indentation || "20")) * (_level - 1)) + "px;'> ";
                } else {
                    s += ">";
                }

                //節點圖標
                if (j == folderColumnIndex) {
                    if (row.children) { //有下級數據
                        s += "<img data-folder='Y' data-trid='TR" + id + "' src='" + folderOpenIcon + "' class='image_hand'>";
                    } else {
                        s += "<img src='" + defaultLeafIcon + "' class='image_nohand'>";
                    }
                }

                //單元格內容
                if (col.handler) {
                    s += (eval(col.handler + ".call(new Object(), row, col)") || "") + "</td>";
                } else {
                    s += (row[col.dataField] || "") + "</td>";
                }
            }
            s += "</tr>";

            //遞歸顯示下級數據
            if (row.children) {
                drowRowData(row.children, _cols, _level + 1, id);
            }
        }
    }

    //主函數
    this.show = function () {
        this.id = _config.id || ("TreeGrid" + TreeGrid.COUNT++);

        s += "<table id='" + this.id + "' cellspacing=0 cellpadding=0 width='" + (_config.width || "100%") + "' class='TreeGrid'>";
        drowHeader();
        drowData();
        s += "</table>";

        __root = jQuery("#" + _config.renderTo);
        __root.append(s);

        //初始化動作
        init();
    }

    init = function () {
        //以新背景色標識鼠標所指行
        if ((_config.hoverRowBackground || "false") == "true") {
            __root.find("tr").hover(
                function () {
                    if (jQuery(this).attr("class") && jQuery(this).attr("class") == "header") return;
                    jQuery(this).addClass("row_hover");
                },
                function () {
                    jQuery(this).removeClass("row_hover");
                }
            );
        }

        //將單擊事件綁定到tr標籤
        __root.find("tr").bind("click", function () {
            __root.find("tr").removeClass("row_active");
            jQuery(this).addClass("row_active");

            //獲取當前行的數據
            __selectedData = jQuery(this).attr('data-row');
            __selectedId = jQuery(this).attr('id');
            __selectedIndex = jQuery(this).attr('data-rowIndex');

            //行記錄單擊後觸發的事件
            if (_config.itemClick) {
                eval(_config.itemClick + "(__selectedId, __selectedIndex, TreeGrid.str2json(__selectedData))");
            }
        });

        //展開、關閉下級節點
        __root.find("img[data-folder='Y']").bind("click", function () {
            var trid = jQuery(this).attr("data-trid");
            var isOpen = __root.find("#" + trid).attr("data-open");
            
            isOpen = (isOpen == "Y") ? "N" : "Y";
            __root.find("#" + trid).attr("data-open", isOpen);
            showHiddenNode(trid, isOpen);
        });
    }

    //顯示或隱藏子節點數據
    showHiddenNode = function (_trid, _open) {
        if (_open == "N") { //隱藏子節點
            __root.find("#" + _trid).find("img[data-folder='Y']").attr("src", folderCloseIcon);
            __root.find("tr[id^=" + _trid + "_]").css("display", "none");
        } else { //顯示子節點
            __root.find("#" + _trid).find("img[data-folder='Y']").attr("src", folderOpenIcon);
            showSubs(_trid);
        }
    }

    //遞歸檢查下一級節點是否需要顯示
    showSubs = function (_trid) {
        var isOpen = __root.find("#" + _trid).attr("data-open");
        if (isOpen == "Y") {
            var trs = __root.find("tr[data-pid=" + _trid + "]");
            trs.css("display", "");

            for (var i = 0; i < trs.length; i++) {
                showSubs(trs[i].id);
            }
        }
    }

    //展開或收起所有節點
    this.expandAll = function (isOpen) {
        var trs = __root.find("tr[data-pid='0']");
        for (var i = 0; i < trs.length; i++) {
            var trid = trs[i].id || trs[i].getAttribute("id");
            showHiddenNode(trid, isOpen);
        }
    }

    //取得當前選中的行記錄
    this.getSelectedItem = function () {
        return new TreeGridItem(__root, __selectedId, __selectedIndex, TreeGrid.str2json(__selectedData));
    }

};

//公共靜態變量
TreeGrid.FOLDER_OPEN_ICON = "images/folderOpen.gif";
TreeGrid.FOLDER_CLOSE_ICON = "images/folderClose.gif";
TreeGrid.DEFAULT_LEAF_ICON = "images/defaultLeaf.gif";
TreeGrid.COUNT = 1;

//將json對象轉換成字符串
TreeGrid.json2str = function(obj){
    var arr = [];

    var fmt = function(s){
        if(typeof s == 'object' && s != null){
            if(s.length){
                var _substr = "";
                for(var x=0;x<s.length;x++){
                    if(x>0) _substr += ", ";
                    _substr += TreeGrid.json2str(s[x]);
                }
                return "[" + _substr + "]";
            }else{
                return TreeGrid.json2str(s);
            }
        }
        return /^(string|number)$/.test(typeof s) ? "'" + s + "'" : s;
    }

    for(var i in obj){
        if(typeof obj[i] != 'object'){ //暫時不包括子數據
            arr.push(i + ":" + fmt(obj[i]));
        }
    }

    return '{' + arr.join(', ') + '}';
}

TreeGrid.str2json = function(s){
    var json = null;
    if(jQuery.browser.msie){
        json = eval("(" + s + ")");
    }else{
        json = new Function("return " + s)();
    }
    return json;
}

//數據行對象
function TreeGridItem (_root, _rowId, _rowIndex, _rowData){
    var __root = _root;
    
    this.id = _rowId;
    this.index = _rowIndex;
    this.data = _rowData;
    
    this.getParent = function(){
        var pid = jQuery("#" + this.id).attr("data-pid");
        if(pid!=""){
            var rowIndex = jQuery("#" + pid).attr("data-rowIndex");
            var data = jQuery("#" + pid).attr("data-row");
            return new TreeGridItem(_root, pid, rowIndex, TreeGrid.str2json(data));
        }
        return null;
    }
    
    this.getChildren = function(){
        var arr = [];
        var trs = jQuery(__root).find("tr[data-pid='" + this.id + "']");
        for(var i=0;i<trs.length;i++){
            var tr = trs[i];
            arr.push(new TreeGridItem(__root, tr.id, tr.rowIndex, TreeGrid.str2json(tr.data)));
        }
        return arr;
    }
};
複製代碼
複製代碼
body{
    font-size:11px;
}
.TreeGrid{
    border-collapse: collapse; 
    font-size: 11px;
    border: 1px solid #778899;
}

.TreeGrid .header{
    background-color: #87CEEB;
    font-size: 11px;
    font-weight: 600;
}

.TreeGrid td{
    border: 1px solid #E6E6FA;
    padding: 4px 3px 2px 3px;
}

.TreeGrid a{
    text-decoration: underline;
    color: black;
}

.TreeGrid a:hover{
    color: blue;
}

.TreeGrid .image_hand{
    border: 0;
    cursor:hand;
    align:absmiddle;
}

.TreeGrid .image_nohand{
    border: 0;
    align:absmiddle;
}

.TreeGrid .row_hover{
    background-color: #E6E6FA;
}

.TreeGrid .row_active{
    background-color: #E0FFFF;
}
複製代碼
複製代碼
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <link href="css/treeGrid/TreeGrid.css" rel="stylesheet" type="text/css" />
    <script src="js/jquery.min.js" type="text/javascript"></script>
    <script src="js/TreeGrid.js" type="text/javascript"></script>
    
 <script src="js/index.js" type="text/javascript"></script>
</head><body> <div id="div1"> </div> <input type="button" value="關閉所有節點" onclick="expandAll('N')"> <input type="button" value="展開所有節點" onclick="expandAll('Y')"> <input type="button" value="取得當前行的數據" onclick="selectedItem()"><br> 當前選中的行: <input type="text" id="currentRow" size="110" /></body></html>
複製代碼

index.js代碼如下:

         $(document).ready(function(){
        		var config = {
		            id: "tg1",
		            width: "800",
		            renderTo: "div1",
		            headerAlign: "left",
		            headerHeight: "30",
		            dataAlign: "left",
		            indentation: "20",
		            folderOpenIcon: "images/folderOpen.gif",
		            folderCloseIcon: "images/folderClose.gif",
		            defaultLeafIcon: "images/defaultLeaf.gif",
		            hoverRowBackground: "false",
		            folderColumnIndex: "1",
		            itemClick: "itemClickEvent",
		            columns: [
		            { headerText: "", headerAlign: "center", dataAlign: "center", width: "20", handler: "customCheckBox" },
		             //   {headerText: "", headerAlign: "center", dataAlign: "center", width: "20" },
						{ headerText: "名稱", dataField: "name", headerAlign: "center", handler: "customOrgName" },
						{ headerText: "拼音碼", dataField: "code", headerAlign: "center", dataAlign: "center", width: "100" },
						{ headerText: "負責人", dataField: "assignee", headerAlign: "center", dataAlign: "center", width: "100" }
					],
		            data: [
						{ name: "城區分公司", code: "CQ", assignee: "", children: [
							{ name: "城區卡品分銷中心" },
							{ name: "先鋒服務廳", children: [
								{ name: "chlid1" },
								{ name: "chlid2" },
								{ name: "chlid3", children: [
									{ name: "chlid3-1" },
									{ name: "chlid3-2" },
									{ name: "chlid3-3" },
									{ name: "chlid3-4" }
								]
								}
							]
							},
							{ name: "半環服務廳" }
						]
						},
						{ name: "清新分公司", code: "QX", assignee: "", children: [] },
						{ name: "英德分公司", code: "YD", assignee: "", children: [] },
						{ name: "佛岡分公司", code: "FG", assignee: "", children: [] }
					]
		        };
		        
		       //創建一個組件對象
	        treeGrid = new TreeGrid(config);
	        treeGrid.show();   
        	});
        var treeGrid;

        /*
        單擊數據行後觸發該事件
        id:行的id
        index:行的索引。
        data:json格式的行數據對象。
        */
        function itemClickEvent(id, index, data) {
            jQuery("#currentRow").val(id + ", " + index + ", " + TreeGrid.json2str(data));
        }

        /*
        通過指定的方法來自定義欄數據
        */
        function customCheckBox(row, col) {
            return "<input type='checkbox'>";
        }

        function customOrgName(row, col) {
            var name = row[col.dataField] || "";
            return name;
        }

        function customLook(row, col) {
            return "<a href='' style='color:blue;'>查看</a>";
        }

        
        /*
        展開、關閉所有節點。
        isOpen=Y表示展開,isOpen=N表示關閉
        */
        function expandAll(isOpen) {
            treeGrid.expandAll(isOpen);
        }

        /*
        取得當前選中的行,方法返回TreeGridItem對象
        */
        function selectedItem() {
            var treeGridItem = treeGrid.getSelectedItem();
            if (treeGridItem != null) {
                //獲取數據行屬性值
                //alert(treeGridItem.id + ", " + treeGridItem.index + ", " + treeGridItem.data.name);

                //獲取父數據行
                var parent = treeGridItem.getParent();
                if (parent != null) {
                    //jQuery("#currentRow").val(parent.data.name);
                }

                //獲取子數據行集
                var children = treeGridItem.getChildren();
                if (children != null && children.length > 0) {
                    jQuery("#currentRow").val(children[0].data.name);
                }
            }
        }


一、TreeGrid組件相關的類

      1、TreeGrid(_config)

            _config:json格式的數據,組件所需要的數據都通過該參數提供。

 

      2、TreeGridItem(_root, _rowId, _rowIndex, _rowData)

            _root:顯示組件實例的目標容器對象。

            _rowId:選中行的id。

            _rowIndex:選中行的索引。

            _rowData:json格式的行數據。

 

二、_config參數詳解

       id:組件實例的id。

       width:組件實例的寬度。

       renderTo:用於顯示組件實例的容器對象的id。一般用div作爲容器。

       headerAlign:標題行的對齊方式。

       headerHeight:標題行的高度。

       dataAlign:數據行的對齊方式。

       indentation:層級縮進量。 

       folderColumnIndex:顯示圖標的數據列的索引,從0開始。

       folderOpenIcon:節點展開時的圖標。

       folderCloseIcon:節點關閉時的圖標。

       defaultLeafIcon:葉節點的圖標。

       hoverRowBackground:鼠標滑過數據行時,背景色是否改變。

       itemClick:單擊數據行後觸發的事件。事件方法包含三個參數,分別是:行的id、行的索引、行數據。

       expandLayer:初始展開層數,默認只展開第1層。

       columns:值爲數組,數組元素爲json對象。定義數據欄相關信息。

               數組元素的屬性:

                        headerText:欄的標題。

                        dataField:欄數據對應的字段名。

                        headerAlign:欄頭對齊方式。

                        dataAlign:欄數據對齊方式。

                        width:欄的寬度。

                        handler:通過指定的方法來自定義欄數據。

                        folderHidden:在文件夾行隱藏單元格值。

       data:組件的數據集。

 

三、TreeGrid的方法

      show:顯示填充數據後的組件對象。

      expandAll:展開、關閉所有節點。該方法有一個參數,參數值爲Y時表示展開,參數值爲N時表示關閉。

      getSelectedItem:獲取當前選中的數據行,返回TreeGridItem對象。

 

四、TreeGridItem組件

       1、組件屬性

              id:數據行的id。

              index:數據行的索引。

              data:json格式的行數據。

 

       2、組件方法

              getParent:獲取父數據行。方法返回TreeGridItem對象。

              getChildren:獲取子數據行集。方法返回一個數組,數組元素爲TreeGridItem對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章