利用ztree实现树搜索

来源:互联网 发布:1元cn域名注册 编辑:程序博客网 时间:2024/06/08 18:39
最近工作中需要利用ztree实现树搜索功能,在网上看了一下别人的轮子觉得都有点不适合需求,所以根据自己的实际情况进行了改进,经过几次优化,觉得效果还能用: 
/**
* 搜索功能3.0
* @type {Element}
*/
var node = document.querySelector('#client_name');
var cpLock = false;
var bower = myBrowser()  //判断浏览器类型,在此省略

//实现延迟搜索,如果上次的输入还没有被执行,那么就取消上一次的执行
var timeoutId = null;
function searchNodeLazy(keyword) {
    if (timeoutId) {
        clearTimeout(timeoutId);
    }
    timeoutId = setTimeout(function(){
        search_keyword(keyword);
    }, 500);
}

//实现模糊搜索
function search_keyword(keyword) {
    if(keyword === ""){
        return;
    }

    var zTree = $.fn.zTree.getZTreeObj("ztree");
    var allNodes = zTree.transformToArray(zTree.getNodes());
    zTree.hideNodes(allNodes);    //当开始搜索时,先将所有节点隐藏

    var nodeList = zTree.getNodesByParamFuzzy('role_name', keyword, 0);    //通过关键字模糊搜索
    var arr = new Array();
    for(var i=0; i<nodeList.length; i++){
        arr = $.merge(arr,nodeList[i].getPath());    //找出所有符合要求的叶子节点的路径
    }
    zTree.showNodes($.unique(arr));    //显示所有要求的节点及其路径节点
    zTree.expandAll(true);    //展开路径
}

//监听搜索框compositionstart、compositionend事件
node.addEventListener('compositionstart', function(){
    cpLock = true;
})
node.addEventListener('compositionend', function(){
    cpLock = false;
    if(!cpLock){
        if (bower=="Chrome" || bower=="Safari") {
            dis_name.val($(this).val());
            searchNodeLazy(dis_name.val());
        }
    };
});
node.addEventListener('input', function(){
    if(!cpLock){
        dis_name.val($(this).val());
        searchNodeLazy(dis_name.val());
    }
});
效果:大约有46000个测试数据,执行一次搜索话费的时间在1s到1.5s之间,基本上可以满足实际需求
    
缺点:1、由于没有查询按钮,我们只能通过compositionstart、compositionend事件来判断用户是否输入完成,这有时会造成连续搜索,致使网页卡顿,即使我们设计了一定的延迟搜索,也不能完全解决这个问题。
         2、这个搜索只适用于单选场景。

在某些情况下,我们选择全部节点后,又需要排除某些节点,这是我们需要另一种搜索方案。
/**
* 搜索功能2.0
* @type {Element}
*/
var node = document.querySelector('#client_name');
var cpLock = false;
var bower = myBrowser()

//根据传过来的子节点,搜索到最终的父节点(根节点下的)
function getRootParent(node) {
    if (node.level < 2) {
        return node;
    } else {
        var rootParent = getRootParent(node.getParentNode());
    }
    return rootParent;
}

//实现延迟搜索,如果上次的输入还没有被执行,那么就取消上一次的执行
var timeoutId = null;
function searchNodeLazy(keyword) {
    if (timeoutId) {
        clearTimeout(timeoutId);
    }
    timeoutId = setTimeout(function(){
        search_keyword(keyword);
    }, 500);
}

//实现高亮搜索
function search_keyword(keyword) {
    if(keyword === ""){
        return;
    }
    var zTree = $.fn.zTree.getZTreeObj("ztree");
    var allNodes = zTree.transformToArray(zTree.getNodes());

    //关闭上一次查询展开的高亮节点
    for(var i=0; i < allNodes.length; i++){
        if(allNodes[i].highlight == true) {
            allNodes[i].highlight = false;
            zTree.expandNode(getRootParent(allNodes[i]), false, true, false);  //关闭展开的节点
        }
        zTree.updateNode(allNodes[i]);
    }

   //实现模糊搜索
    var nodeList = zTree.getNodesByParamFuzzy('role_name', keyword, 0);
    var arr = new Array();
    for(var i=0; i<nodeList.length; i++){
        nodeList[i].highlight = true;    // 设置高亮
        arr = $.merge(arr,nodeList[i].getPath());    //找到高亮节点的路径
    }
    var searchNodes = $.unique(arr);
    for(var i = 0; i < searchNodes.length; i++){
        zTree.expandNode(zTree.getNodes()[0],true);    //展开时必须先展开根节点,其余节点才能展开(可能是ztree的BUG)
        zTree.expandNode(searchNodes[i],true);
        zTree.updateNode(searchNodes[i]);
    }
}

node.addEventListener('compositionstart', function(){
    cpLock = true;
})
node.addEventListener('compositionend', function(){
    cpLock = false;
    if(!cpLock){
        if (bower=="Chrome" || bower=="Safari") {
            dis_name.val($(this).val());
            searchNodeLazy(dis_name.val());
        }
    };
});
node.addEventListener('input', function(){
    if(!cpLock){
        dis_name.val($(this).val());
        searchNodeLazy(dis_name.val());
    }
});
这个搜索和上个不同之处在于,搜索之后将不会隐藏不包含关键字的内容,只是将含有关键字的节点设置为高亮并且将其路径展开而已。