treeTable实现排序
阅读原文时间:2023年07月09日阅读:1

/*
*
* TreeTable 0.1 - Client-side TreeTable Viewer!
* @requires jQuery v1.3
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*
*/

(function($){  
    $.extend({  
        treetable: new function() {

            this.defaults = {  
                id\_col: 0,  
                parent\_col: 1,  
                handle\_col: 2,  
                order\_col: -1,  
                open\_img: "lib/plugin/treetable/images/minus.gif",  
                close\_img: "lib/plugin/treetable/images/plus.gif",  
                expanded: true//@author GaoBing  
            };

            //jquery的trim处理不了 产生的"空格"  
            function trim(str){  
                return str.replace(/(^\[\\s\\xA0\]\*)|(\[\\s\\xA0\]\*$)/g, "");  
            }

            this.construct = function(settings){

                if(this.size()!=1)return;//只处理一个表格

                if(this\[0\].tagName.toUpperCase()!="TBODY")return;//只应用于tbody

                var config = $.extend({}, $.treetable.defaults, settings);

                if(config.id\_col==null || config.parent\_col==null || config.handle\_col==null ) return;

                var $this = $(this);  
                var tr\_arr = new Array();  
                var tr\_sort = new Array();

                //构建行对象数组  
                $this.find("tr").each(function(){  
                    var id = $.trim($(this).find("td:eq("+config.id\_col+")").text());  
                    var parent = $.trim($(this).find("td:eq("+config.parent\_col+")").text());  
                    tr\_arr.push({'id':id,'parent':parent,'level':0,'node':'leaf','expanded':config.expanded,'obj':$(this)});  
                });  
                var len = tr\_arr.length;  
                var level = 0;

                /\*  
                检查tr\_arr中的每一行的父行是否再tr\_sort中,  
                如果有则插入到tr\_sort的父行后,从tr\_arr中删除  
                直到tr\_arr都为null,生成排好序的tr\_sort  
                \*/  
                while(len>0){  
                    for(var i=0;i<tr\_arr.length;i++){  
                        var o = tr\_arr\[i\];

                        if(o==null)continue;

                        if(o.parent==""){//根行直接压入tr\_sort  
                            tr\_sort.push(o);  
                            tr\_arr\[i\]=null;  
                            len=len-1;  
                        }else{  
                            if (tr\_sort.length > 0){  
                                for(var j=0;j<tr\_sort.length;j++){  
                                    if(tr\_sort\[j\].id==o.parent){  
                                        o.level = tr\_sort\[j\].level+1;//从父行累计生成层次level  
                                        tr\_sort\[j\].node='node';  
                                        tr\_sort.splice(j+1,0,o);//数组插入  
                                        tr\_arr\[i\]=null;  
                                        len=len-1;  
                                        break;  
                                    }  
                                }  
                            }else{  
                                for(var k=0;k<tr\_arr.length;k++){  
                                    var ok = tr\_arr\[k\];  
                                    if(ok == null) continue;  
                                    if (o.id != ok.parent && ok.parent != ""){  
                                        ok.level = tr\_arr\[k\].level+1;  
                                        tr\_sort.push(ok);  
                                        tr\_arr\[i\]=null;  
                                        len=len-1;  
                                    }else{  
                                        if (tr\_sort\[k\]){  
                                            o.level = tr\_sort\[k\].level+1;//从父行累计生成层次level  
                                            tr\_sort\[k\].node='node';  
                                            tr\_sort.splice(k+1,0,o);//数组插入  
                                            tr\_arr\[i\]=null;  
                                            len=len-1;  
                                            break;  
                                        }  
                                    }  
                                }  
                            }  
                        }  
                    }  
                    level=level+1;  
                }//while

                //展开事件动作函数  
                var fn\_click = function(){

                    var id = trim($(this).parent().parent().find("td:eq("+config.id\_col+")").text());//获取当前行ID  
                    var v = -1;  
                    for(var j=0;j<tr\_sort.length;j++){  
                        var o = tr\_sort\[j\];  
                        if(o.id==id){//在tr\_sort找到行对象

                            if(o.node=='leaf')return;

                            v = o.level;  
                            var img = o.obj.find("td:eq("+config.handle\_col+") img")\[0\];

                            if(!o.expanded){//通过图标判断是展开还是收起  
                                img.src=config.open\_img;  
                                o.expanded=true;  
                            }else{  
                                img.src=config.close\_img;  
                                o.expanded=false;  
                            }

                            var show = o.expanded;  
                            var f = false;//父行收起标志  
                            var tmp = 0;//父行的层次

                            for(var i=j+1;i<tr\_sort.length;i++){//根据level更新后续的子行  
                                o = tr\_sort\[i\];

                                var img = o.obj.find("td:eq("+config.handle\_col+") img")\[0\];

                                var t = !o.expanded;//判断是否是收起状态

                                if(o.level>v && show){//展开操作  
                                    if(!f&&!t){//父行未收起,且当前行是展开状态  
                                        o.obj.show();  
                                    }else if(!f&&t){//父行未收起,且当前行是收起状态  
                                        tmp = o.level;  
                                        f = true;  
                                        o.obj.show();  
                                    }else if(f&&o.level<=tmp){//同级的前一行是收起状态  
                                        if(!t){  
                                            f=false;  
                                        }else{  
                                            tmp = o.level;  
                                        }  
                                        o.obj.show();  
                                    }else{  
                                        ;  
                                    }

                                }else if(o.level>v && !show){//收起操作则隐藏所以子行  
                                    o.obj.hide();  
                                }else if(o.level<=v){//到达非子行,处理完毕  
                                    break;  
                                }  
                            }

                            break;  
                        }  
                    }  
                };

                //重新绘制表格,添加展开动作图标  
                for(var j=tr\_sort.length-1;j>-1;j--){//prepend插入tbody内需使用反序  
                    var o = tr\_sort\[j\];

                    var img = $("<img src='"+config.open\_img+"'>");  
                    img.click(fn\_click);

                    var tr=o.obj.find("td:eq("+config.handle\_col+")");

                    //避免重复添加图标  
                    var imgEle = tr.find("img");  
                    if(imgEle.length == 0){  
                        tr.prepend("&nbsp;");  
                        tr.prepend(img);  
                        var s = new Array((o.level+1)\*5).join("&nbsp;");//生成缩进空格  
                        tr.prepend(s);

                        $this.prepend(o.obj);  
                    }

                }//for

                /\*  
                 \* @author GaoBing  
                 \* 是否展开 当expanded为false时,父节点收缩  
                 \* \*/  
                if(tr\_sort.length > 0){  
                    for(var i=0;i<tr\_sort.length;i++){  
                        var o = tr\_sort\[i\];//行对象  
                        var img = o.obj.find("td:eq("+config.handle\_col+") img");//父节点图标元素  
                        if(o.expanded == false){//收缩  
                            //检查是否有父节点,如有父节点则隐藏本行节点  
                            if (o.parent != ""){  
                                o.obj.hide();//隐藏子节点  
                            }  
                            //检查是否有子节点,有子节点则替换图标  
                            for(var j=0;j<tr\_sort.length;j++){  
                                if (tr\_sort\[j\].parent != "" && tr\_sort\[j\].parent == o.id){//有子节点  
                                    $(img).attr("src",config.close\_img);//替换父节点图标  
                                }  
                            }  
                        }  
                    }  
                }

            }//construct  
        }//treetable

    });

    $.fn.extend({  
        treetable: $.treetable.construct  
    });

})(jQuery);

/\*\*  
 \* @author GaoBing  
 \* 功能:对树状表格进行排序 父节点在前 子节点在后  
\*\*/  
function treetable\_sort(tableId,parentColumn){

    var trs = new Array();

    //拿到所有行  
    $("#" + tableId + " tbody tr\[role='row'\]").each(function(index){  
        trs\[index\] = $(this).clone(true);  
    });

    //清空之前的行数据  
    $("#" + tableId + " tbody").empty();

    //递归  
    sort\_tr\_root(trs,tableId,parentColumn);

}

/\*根节点排序\*/  
function sort\_tr\_root(trs,tableId,parentColumn){  
    var rootArr = new Array();  
    for(var i=0;i<trs.length;i++){  
        if (null != trs\[i\]){  
            var trsData = trs\[i\].attr("data");  
            var trsDataObj = eval('(' + trsData + ')');  
            var trsId = trsDataObj\['id'\];  
            var trsParentId = trsDataObj\[ parentColumn \];  
            if (null == trsParentId || trsParentId == "" || undefined == trsParentId){//最外层的根  
                trs\[i\].attr("id",trsId);  
                $("#" + tableId + " tbody").append(trs\[i\]);  
                rootArr.push(trs\[i\]);  
                trs\[i\] = null;  
            }  
        }  
    }

    //子节点排序  
    var treeData = changeDataToMap(trs);  
    var result = createSearchMap(trs,parentColumn);  
    for(var i=0;i<rootArr.length;i++){  
        var rootData = rootArr\[i\].attr("data");  
        var rootDataObj = eval('(' + rootData + ')');  
        var rootId = rootDataObj\['id'\];  
        var rootParentId = rootDataObj\[ parentColumn \];  
        buildChild(tableId,treeData,result,rootId,rootParentId);  
    }

}

function createSearchMap(data,parentColumn){  
    //创建搜索键值对  
    var result = {};  
    for(var i=0;i<data.length;i++) {  
        if (null != data\[i\]){  
            var trsData = data\[i\].attr("data");  
            var trsDataObj = eval('(' + trsData + ')');  
            var trId = trsDataObj\['id'\];  
            var trParentId = trsDataObj\[parentColumn\];  
            if(trParentId){  
                if(!result\[trParentId\] && trParentId != null && trParentId != ""){  
                    result\[trParentId\] = \[\];  
                }  
                result\[trParentId\].push(trId);  
            }  
        }  
    }  
    return result;  
}

function changeDataToMap(trs){  
    var deepMap = new Array();  
    for(var i=0;i<trs.length;i++){  
        if (null != trs\[i\]){  
            var trsData = trs\[i\].attr("data");  
            var trsDataObj = eval('(' + trsData + ')');  
            var trId = trsDataObj\['id'\];  
            if(trId){  
                deepMap\[trId\] = trs\[i\];  
            }  
        }  
    }  
    return deepMap;  
}

function buildChild(tableId,treeData,result,id,parentId){  
    if (parentId){  
        var trObj = treeData\[id\];  
        trObj.attr("id",id);  
        $("#" + tableId + " tbody tr\[role=row\]\[id=" + parentId + "\]").after(trObj);  
    }  
    var childrenIds = result\[id\];  
    if(childrenIds){  
        for(var i=0;i<childrenIds.length;i++){  
            buildChild(tableId,treeData,result,childrenIds\[i\],id);  
        }  
    }  
}

/\*判断是否包含某个元素\*/  
Array.prototype.contains = function (element) { // 利用Array的原型prototype点出一个我想要封装的方法名contains  
    for (var i = 0; i < this.length; i++) {  
        if (this\[i\] == element) { // 如果数组中某个元素和你想要测试的元素对象element相等,则证明数组中包含这个元素,返回true  
            return true;  
        }  
    }  
}; 

/\*\*  
 \* @author GaoBing  
 \* 功能:表格树 供datatable调用接口  
\*\*/  
function initTreeTable(obj){

    //参数  
    var tableId = obj.tableId;//表格ID  
    var tbodyId = obj.tbodyId;//表格中tbodyID  
    var isExpanded = obj.isExpanded;//是否展开所有节点  
    var viewConfig = obj.viewConfig;//展示配置  
    var parentColumn = obj.parentColumn;//父列

    //排序 父节点排在子节点前面  
    treetable\_sort(tableId,parentColumn);

    //默认属性  
    $.treetable.defaults={  
        id\_col: viewConfig\[0\],//ID td列 {从0开始}  
        parent\_col: viewConfig\[1\],//父ID td列  
        handle\_col: viewConfig\[2\],//操作展开操作的 td列  
        open\_img: "lib/plugin/treetable/images/minus.gif",//展开时图标  
        close\_img: "lib/plugin/treetable/images/plus.gif",//收缩时图标  
        expanded: isExpanded//true为展开,false为收缩  
    };

    //生成树  
    $("#" + tbodyId).treetable();

    //隐藏数据列  
    $("#" + tbodyId + " tr").find("td:eq(" + viewConfig\[0\] + ")").hide();  
    $("#" + tbodyId + " tr").find("td:eq(" + viewConfig\[1\] + ")").hide();  
    $("#" + tableId + " tr:eq(0)").find("th:eq(" + viewConfig\[0\] + ")").hide();  
    $("#" + tableId + " tr:eq(0)").find("th:eq(" + viewConfig\[1\] + ")").hide();  
}