我正在使用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));
}
});
}
感谢。
答案 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();
}
});
}});