summaryrefslogtreecommitdiff
path: root/frontend/beta/js/YUI-extensions/tree/TreeFilter.js
Side-by-side diff
Diffstat (limited to 'frontend/beta/js/YUI-extensions/tree/TreeFilter.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/beta/js/YUI-extensions/tree/TreeFilter.js105
1 files changed, 105 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI-extensions/tree/TreeFilter.js b/frontend/beta/js/YUI-extensions/tree/TreeFilter.js
new file mode 100644
index 0000000..9eeb274
--- a/dev/null
+++ b/frontend/beta/js/YUI-extensions/tree/TreeFilter.js
@@ -0,0 +1,105 @@
+/**
+ * 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 = {};
+ }
+};