ExtJS - 突出显示树类型的匹配节点

时间:2015-02-27 20:30:23

标签: javascript extjs

我正在使用Sencha的其中一位成员创建的树过滤器插件。这是他对插件的小提琴:http://jsfiddle.net/slemmon/fSJwF/2/

正如您在小提琴中看到的那样,当typeAhead结果是父节点时,它的所有子节点都会被展开。所以我想强调所有匹配的结果,因为我经常会得到许多包含匹配的typeAhead搜索词的父节点,并且它们有数百个子节点,这使得很难找到匹配的父节点。

复制从小提琴中粘贴一个片段,因为SO正在抛出“链接到jsfiddle必须伴随代码”错误...

filter: function (value, property, re) {
            var me = this
                , tree = me.tree
                , matches = []                                          // array of nodes matching the search criteria
                , root = tree.getRootNode()                                // root node of the tree
                , property = property || 'text'                          // property is optional - will be set to the 'text' propert of the  treeStore record by default
                , re = re || new RegExp(value, "ig")                     // the regExp could be modified to allow for case-sensitive, starts  with, etc.
                , visibleNodes = []                                      // array of nodes matching the search criteria + each parent non-leaf  node up to root
                , viewNode;

            if (Ext.isEmpty(value)) {                                    // if the search field is empty
                me.clearFilter();
                return;
            }

            tree.expandAll();                                            // expand all nodes for the the following iterative routines

            // iterate over all nodes in the tree in order to evalute them against the search criteria
            root.cascadeBy(function (node) {
                if (node.get(property).match(re)) {                         // if the node matches the search criteria and is a leaf (could be  modified to searh non-leaf nodes)
                    matches.push(node)                                  // add the node to the matches array
                }
            });

            if (me.allowParentFolders === false) {                         // if me.allowParentFolders is false (default) then remove any  non-leaf nodes from the regex match
                Ext.each(matches, function (match) {
                    if (!match.isLeaf()) { Ext.Array.remove(matches, match); }
                });
            }

            Ext.each(matches, function (item, i, arr) {                 // loop through all matching leaf nodes
                root.cascadeBy(function (node) {                         // find each parent node containing the node from the matches array
                    if (node.contains(item) == true) {
                        visibleNodes.push(node)                          // if it's an ancestor of the evaluated node add it to the visibleNodes  array
                    }
                });
                if (me.allowParentFolders === true &&  !item.isLeaf()) {    // if me.allowParentFolders is true and the item is  a non-leaf item
                    item.cascadeBy(function (node) {                    // iterate over its children and set them as visible
                        visibleNodes.push(node)
                    });
                }
                visibleNodes.push(item)                                  // also add the evaluated node itself to the visibleNodes array
            });

            root.cascadeBy(function (node) {                            // finally loop to hide/show each node
                viewNode = Ext.fly(tree.getView().getNode(node));       // get the dom element assocaited with each node
                if (viewNode) {                                          // the first one is undefined ? escape it with a conditional
                    viewNode.setVisibilityMode(Ext.Element.DISPLAY);     // set the visibility mode of the dom node to display (vs offsets)
                    viewNode.setVisible(Ext.Array.contains(visibleNodes, node));
                }
            });
        }

感谢。

1 个答案:

答案 0 :(得分:3)

解决该问题的方法之一是将附加类附加到匹配的元素并按照您希望的方式设置样式。

在下面的来源中,我添加了匹配的'到每个匹配的项目。小提琴链接是http://jsfiddle.net/0o0wtr7j/

Ext.define('TreeFilter', {
extend: 'Ext.AbstractPlugin'
    , alias: 'plugin.treefilter'

    , collapseOnClear: true                                             // collapse all nodes when clearing/resetting the filter
    , allowParentFolders: false                                         // allow nodes not designated as 'leaf' (and their child items) to  be matched by the filter

    , init: function (tree) {
        var me = this;
        me.tree = tree;

        tree.filter = Ext.Function.bind(me.filter, me);
        tree.clearFilter = Ext.Function.bind(me.clearFilter, me);
    }

    , filter: function (value, property, re) {
        var me = this
            , tree = me.tree
            , matches = []                                          // array of nodes matching the search criteria
            , root = tree.getRootNode()                                // root node of the tree
            , property = property || 'text'                          // property is optional - will be set to the 'text' propert of the  treeStore record by default
            , re = re || new RegExp(value, "ig")                     // the regExp could be modified to allow for case-sensitive, starts  with, etc.
            , visibleNodes = []                                      // array of nodes matching the search criteria + each parent non-leaf  node up to root
        , matchedClass = 'matched'
        , viewNode;

        if (Ext.isEmpty(value)) {                                    // if the search field is empty
            me.clearFilter();
            return;
        }

        tree.expandAll();                                            // expand all nodes for the the following iterative routines

        // iterate over all nodes in the tree in order to evalute them against the search criteria
        root.cascadeBy(function (node) {
            if (node.get(property).match(re)) {                         // if the node matches the search criteria and is a leaf (could be  modified to searh non-leaf nodes)
                node.set('cls', matchedClass);
                matches.push(node)                                  // add the node to the matches array
            } else {
                node.set('cls', '');
            }
        });

        if (me.allowParentFolders === false) {                         // if me.allowParentFolders is false (default) then remove any  non-leaf nodes from the regex match
            Ext.each(matches, function (match) {
                if (!match.isLeaf()) { Ext.Array.remove(matches, match); }
            });
        }

        Ext.each(matches, function (item, i, arr) {                 // loop through all matching leaf nodes
            root.cascadeBy(function (node) {                         // find each parent node containing the node from the matches array
                if (node.contains(item) == true) {
                    visibleNodes.push(node)                          // if it's an ancestor of the evaluated node add it to the visibleNodes  array
                }
            });
            if (me.allowParentFolders === true &&  !item.isLeaf()) {    // if me.allowParentFolders is true and the item is  a non-leaf item
                item.cascadeBy(function (node) {                    // iterate over its children and set them as visible
                    visibleNodes.push(node)
                });
            }
            visibleNodes.push(item)                                  // also add the evaluated node itself to the visibleNodes array
        });

        root.cascadeBy(function (node) {                            // finally loop to hide/show each node
            viewNode = Ext.fly(tree.getView().getNode(node));       // get the dom element assocaited with each node
            if (viewNode) {                                          // the first one is undefined ? escape it with a conditional
                viewNode.setVisibilityMode(Ext.Element.DISPLAY);     // set the visibility mode of the dom node to display (vs offsets)
                viewNode.setVisible(Ext.Array.contains(visibleNodes, node));
            }
        });
    }

    , clearFilter: function () {
        var me = this
            , tree = this.tree
            , root = tree.getRootNode();

        if (me.collapseOnClear) { tree.collapseAll(); }             // collapse the tree nodes
        root.cascadeBy(function (node) {                            // final loop to hide/show each node
            node.set('cls', '');
            viewNode = Ext.fly(tree.getView().getNode(node));       // get the dom element assocaited with each node
            if (viewNode) {                                          // the first one is undefined ? escape it with a conditional and show  all nodes
                viewNode.show();
            }
        });
    }});