/** * This doesn't update the indent (lines) or expand collapse icons of the nodes */ YAHOO.ext.tree.TreeFilter = function(tree, config){ this.tree = tree; this.filtered = {}; YAHOO.ext.util.Config.apply(this, config, { clearBlank:false, reverse:false, autoClear:false, remove:false }); }; YAHOO.ext.tree.TreeFilter.prototype = { /** * Filter the data by a specific attribute. * @param {String/RegExp} value Either string that the attribute value * should start with or a RegExp to test against the attribute * @param {String} attr (optional) The attribute passed in your node's attributes collection. Defaults to "text". * @param {TreeNode} startNode (optional) The node to start the filter at. */ filter : function(value, attr, startNode){ attr = attr || 'text'; var f; if(typeof value == 'string'){ var vlen = value.length; // auto clear empty filter if(vlen == 0 && this.clearBlank){ this.clearFilter(); return; } value = value.toLowerCase(); f = function(n){ return n.attributes[attr].substr(0, vlen).toLowerCase() == value; } }else if(value.exec){ // regex? f = function(n){ return value.test(n.attributes[attr]); } }else{ throw 'Illegal filter type, must be string or regex'; } this.filterBy(f, null, startNode); }, /** * Filter by a function. The passed function will be called with each * node in the tree (or from the startNode). If the function returns true, the node is kept * otherwise it is filtered. If a node is filtered, it's children are also filtered. * @param {Function} fn The filter function * @param {Object} scope (optional) The scope of the function (defaults to the current node) */ filterBy : function(fn, scope, startNode){ startNode = startNode || this.tree.root; if(this.autoClear){ this.clearFilter(); } var af = this.filtered, rv = this.reverse; var f = function(n){ if(n == startNode){ return true; } if(af[n.id]){ return false; } var m = fn.call(scope || n, n); if(!m || rv){ af[n.id] = n; n.ui.hide(); return false; } return true; } startNode.cascade(f); if(this.remove){ for(var id in af){ if(typeof id != 'function'){ var n = af[id]; if(n && n.parentNode){ n.parentNode.removeChild(n); } } } } }, /** * Clears the current filter. Note: with the "remove" option * set a filter cannot be cleared. */ clear : function(){ var t = this.tree; var af = this.filtered; for(var id in af){ if(typeof id != 'function'){ var n = af[id]; if(n){ n.ui.show(); } } } this.filtered = {}; } };