Javascript Slickgrid树视图搜索

Javascript Slickgrid树视图搜索,javascript,jquery,slickgrid,Javascript,Jquery,Slickgrid,我目前正在使用slickgrid实现一个treeview 我的代码基本上就是基于此 我试图做的是得到一个搜索过滤器,类似于示例中的一个,但它对分支和父级都有效。例如,如果一棵树看起来像这样: -Parent 1 -branch 1 -sub_branch 1 -branch 2 -Parent 2 -branch 1 -branch 2 我搜索数字“1”,它应该显示: -Parent 1 -branch 1 -sub_branch 1 -branch 2 -

我目前正在使用slickgrid实现一个treeview

我的代码基本上就是基于此

我试图做的是得到一个搜索过滤器,类似于示例中的一个,但它对分支和父级都有效。例如,如果一棵树看起来像这样:

-Parent 1
  -branch 1
   -sub_branch 1
  -branch 2
-Parent 2
  -branch 1
  -branch 2
我搜索数字“1”,它应该显示:

-Parent 1
  -branch 1
   -sub_branch 1
  -branch 2
-Parent 2
  -branch 1
与此相反:

-Parent 1

对不起,我没有任何代码要显示,我什么地方都没有。有什么想法吗?谢谢

就我个人而言,我使用了分组示例,并且我还帮助它进行了多列(嵌套)分组,使用该示例,它可以完全满足您的需要。。。所以不要用你说的那个,我认为它主要是为了缩进,你应该用这个

该示例不包括搜索,但很容易添加,就像在我的项目中一样。是的,父母群体永远不会消失。 在多重分组的示例中,选择50k行,然后单击“按持续时间分组,然后按工作驱动,然后按百分比分组”,您将看到一个漂亮的3列分组:)
复制它,添加搜索栏,它应该可以工作。

更新:

我不得不在一年多前的这个星期改进我写的代码,经过大量测试,这就是我最终得到的结果。这种方法比旧方法快得多,而且我的意思是很多!使用5个节点和5100行的节点深度进行测试此数据准备大约需要1.3s,但如果不需要不区分大小写的搜索,删除toLowerCase将花费一半的时间,大约600ms。准备好SearchString后,搜索将立即进行

这是我们准备数据的setData函数

var self = this,
    searchProperty = "name";

//if it's a tree grid, we need to manipulate the data for us to search it
if (self.options.treeGrid) {

    //createing index prop for faster get
    createParentIndex(items);

    for (var i = 0; i < items.length; i++) {
        items[i]._searchArr = [items[i][searchProperty]];
        var item = items[i];

        if (item.parent != null) {
            var parent = items[item.parentIdx];

            while (parent) {
                parent._searchArr.push.apply(
                    parent._searchArr, uniq_fast(item._searchArr)
                    );

                item = parent;
                parent = items[item.parentIdx];
            }
        }
    }

    //constructing strings to search
    //for case insensitive (.toLowerCase()) this loop is twice as slow (1152ms instead of 560ms for 5100rows) .toLowerCase();
    for (var i = 0; i < items.length; i++) {
        items[i]._search = items[i]._searchArr.join("/").toLowerCase(); 
        items[i]._searchArr = null;
    }

    //now all we need to do in our filter is to check indexOf _search property
}
所以,这个问题很久以前就被提出了,但是如果有人正在寻找答案,请使用上面的代码。虽然速度很快,但对代码的任何改进都将是值得赞赏的

编辑结束

旧答案(这很慢):

首先,您必须创建一个用于dataView的筛选函数。只要您键入某个内容,dataView就会调用您的函数。将为dataView中的每一行调用该函数,并将该行作为参数传递。返回false表示该行应隐藏,返回true表示可见

查看,filter函数如下所示

function myFilter(item, args) {
  if (item["percentComplete"] < percentCompleteThreshold) {
    return false;
  }

  if (searchString != "" && item["title"].indexOf(searchString) == -1) {
    return false;
  }

  if (item.parent != null) {
    var parent = data[item.parent];

    while (parent) {
      if (parent._collapsed || (parent["percentComplete"] < percentCompleteThreshold) || (searchString != "" && parent["title"].indexOf(searchString) == -1)) {
        return false;
      }

      parent = data[parent.parent];
    }
  }

  return true;
}
第二,是递归函数的时候了。如果你不熟悉它们的工作原理,这是一个棘手的部分

//returns true if a child was found that passed the realFilter
function checkParentForChildren(parent, allItems, args) { 
    var foundChild = false;
    for (var i = 0; i < allItems.length; i++) {
        if (allItems[i].parent == parent.id) {
            if (realFilter(allItems[i], args) == false && foundChild == false) //if the child do not pass realFilter && no child have been found yet for this row 
                foundChild = checkParentForChildren(allItems[i], allItems, args);
            else
                return true;
        }
    }
    return foundChild;
}
//如果找到通过realFilter的子级,则返回true
函数checkParentForChildren(父项、所有项、参数){
var foundChild=false;
对于(变量i=0;i
最后,实现了原始的滤波函数。 这是由slickgrid调用的函数,应该注册到dataView

//registration of the filter
dataView.setFilter(filter);

//the base filter function
function filter(item, args) {
    var allRows = args.grid.getData().getItems();
    var columnFilters = args.columnFilters;
    var grid = args.grid;
    var checkForChildren = false;

    for (var i = 0; i < allRows.length; i++) {
        if (allRows[i].parent == item.id) {
            checkForChildren = true;
            break;
        }
    }

    for (var columnId in columnFilters) {
        if (columnId !== undefined && columnFilters[columnId] !== "") {
            var c = grid.getColumns()[grid.getColumnIndex(columnId)];
            var searchString = columnFilters[columnId].toLowerCase().trim();

            if (c != undefined) {
                if (item[c.field] == null || item[c.field] == undefined) {
                    return false;
                }
                else { 
                    var returnValue = true;

                    if (checkForChildren) {
                        returnValue = checkParentForChildren(item, allRows, args);
                        if(!returnValue)
                            returnValue = realFilter(item, args);
                    }
                    else
                        returnValue = realFilter(item, args);

                    if (item.parent != null && returnValue == true) {
                        var dataViewData = args.grid.getData().getItems();
                        var parent = dataViewData[item.parent];

                        while (parent) {
                            if (parent._collapsed) {
                                parent._collapsed = false;
                            }
                            parent = dataViewData[parent.parent];
                        }
                    }

                    return returnValue;
                }
            }
        }
    }

    if (item.parent != null) {
        var dataViewData = args.grid.getData().getItems();
        var parent = dataViewData[item.parent];

        while (parent) {
            if (parent._collapsed) {
                return false;
            }

            parent = dataViewData[parent.parent];
        }
    }
    return true;
}
//过滤器的注册
setFilter(filter);
//基本过滤函数
函数筛选器(项,参数){
var allRows=args.grid.getData().getItems();
var columnFilters=args.columnFilters;
var grid=args.grid;
var checkForChildren=false;
对于(var i=0;i
我目前正在做这件事,所以我还没有真正费心去改进代码。据我所知,它正在工作,但您可能需要调整过滤器realFilter中的一些内容,以使其按预期工作。我今天写了这篇文章,所以它没有在开发阶段进行更多的测试

注: 如果要使用其他输入进行搜索,只需在该字段上使用$.keyup(),然后将数据传递到标题过滤器。这样你就可以得到艾尔
function realFilter(item, args) {
    var columnFilters = args.columnFilters;
    var grid = args.grid;
    var returnValue = false;

    for (var columnId in columnFilters) {
        if (columnId !== undefined && columnFilters[columnId] !== "") {
            returnValue = true;
            var c = grid.getColumns()[grid.getColumnIndex(columnId)];

            if (item[c.field].toString().toLowerCase().indexOf(
                columnFilters[columnId].toString().toLowerCase()) == -1) { //if true, don't show this post
                returnValue = false;
            }
        }
    }
    return returnValue;
}
//returns true if a child was found that passed the realFilter
function checkParentForChildren(parent, allItems, args) { 
    var foundChild = false;
    for (var i = 0; i < allItems.length; i++) {
        if (allItems[i].parent == parent.id) {
            if (realFilter(allItems[i], args) == false && foundChild == false) //if the child do not pass realFilter && no child have been found yet for this row 
                foundChild = checkParentForChildren(allItems[i], allItems, args);
            else
                return true;
        }
    }
    return foundChild;
}
//registration of the filter
dataView.setFilter(filter);

//the base filter function
function filter(item, args) {
    var allRows = args.grid.getData().getItems();
    var columnFilters = args.columnFilters;
    var grid = args.grid;
    var checkForChildren = false;

    for (var i = 0; i < allRows.length; i++) {
        if (allRows[i].parent == item.id) {
            checkForChildren = true;
            break;
        }
    }

    for (var columnId in columnFilters) {
        if (columnId !== undefined && columnFilters[columnId] !== "") {
            var c = grid.getColumns()[grid.getColumnIndex(columnId)];
            var searchString = columnFilters[columnId].toLowerCase().trim();

            if (c != undefined) {
                if (item[c.field] == null || item[c.field] == undefined) {
                    return false;
                }
                else { 
                    var returnValue = true;

                    if (checkForChildren) {
                        returnValue = checkParentForChildren(item, allRows, args);
                        if(!returnValue)
                            returnValue = realFilter(item, args);
                    }
                    else
                        returnValue = realFilter(item, args);

                    if (item.parent != null && returnValue == true) {
                        var dataViewData = args.grid.getData().getItems();
                        var parent = dataViewData[item.parent];

                        while (parent) {
                            if (parent._collapsed) {
                                parent._collapsed = false;
                            }
                            parent = dataViewData[parent.parent];
                        }
                    }

                    return returnValue;
                }
            }
        }
    }

    if (item.parent != null) {
        var dataViewData = args.grid.getData().getItems();
        var parent = dataViewData[item.parent];

        while (parent) {
            if (parent._collapsed) {
                return false;
            }

            parent = dataViewData[parent.parent];
        }
    }
    return true;
}