From ef68436ac04da078ffdcacd7e1f785473a303d45 Mon Sep 17 00:00:00 2001 From: Giulio Cesare Solaroli Date: Sun, 02 Oct 2011 23:56:18 +0000 Subject: First version of the newly restructured repository --- (limited to 'frontend/beta/js/YUI-extensions/data/Tree.js') diff --git a/frontend/beta/js/YUI-extensions/data/Tree.js b/frontend/beta/js/YUI-extensions/data/Tree.js new file mode 100644 index 0000000..afa5b20 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/data/Tree.js @@ -0,0 +1,412 @@ +YAHOO.namespace('ext.data'); + +/** + * @class YAHOO.ext.data.Tree + * @extends YAHOO.ext.util.Observable + * The class represents a tree data structure and bubbles all the events for it's nodes. The nodes + * in the tree have most standard DOM functionality. + * @constructor + * @param {Node} root (optional) The root node + */ +YAHOO.ext.data.Tree = function(root){ + this.nodeHash = {}; + this.root = null; + if(root){ + this.setRootNode(root); + } + this.events = { + 'append' : true, + 'remove' : true, + 'move' : true, + 'insert' : true, + 'beforeappend' : true, + 'beforeremove' : true, + 'beforemove' : true, + 'beforeinsert' : true + }; +}; + +YAHOO.extendX(YAHOO.ext.data.Tree, YAHOO.ext.util.Observable, { + pathSeparator: '/', + + getRootNode : function(){ + return this.root; + }, + + setRootNode : function(node){ + this.root = node; + node.ownerTree = this; + node.isRoot = true; + return node; + }, + + getNodeById : function(id){ + return this.nodeHash[id]; + }, + + registerNode : function(node){ + this.nodeHash[node.id] = node; + }, + + unregisterNode : function(node){ + delete this.nodeHash[node.id]; + }, + + toString : function(){ + return '[Tree'+(this.id?' '+this.id:'')+']'; + } +}); + +/** + * @class YAHOO.ext.tree.Node + * @extends YAHOO.ext.util.Observable + * @cfg {String} text The text for this node + * @cfg {String} id The id for this node + * @constructor + * @param {Object} attributes The attributes/config for the node + */ +YAHOO.ext.data.Node = function(attributes){ + this.attributes = attributes || {}; + this.leaf = this.attributes.leaf; + this.id = this.attributes.id; + if(!this.id){ + this.id = YAHOO.util.Dom.generateId(null, 'ynode-'); + this.attributes.id = this.id; + } + + this.childNodes = []; + if(!this.childNodes.indexOf){ // indexOf is a must + this.childNodes.indexOf = function(o){ + for(var i = 0, len = this.length; i < len; i++){ + if(this[i] == o) return i; + } + return -1; + }; + } + this.parentNode = null; + this.firstChild = null; + this.lastChild = null; + this.previousSibling = null; + this.nextSibling = null; + + this.events = { + 'append' : true, + 'remove' : true, + 'move' : true, + 'insert' : true, + 'beforeappend' : true, + 'beforeremove' : true, + 'beforemove' : true, + 'beforeinsert' : true + }; +}; + +YAHOO.extendX(YAHOO.ext.data.Node, YAHOO.ext.util.Observable, { + fireEvent : function(evtName){ + // first do standard event for this node + if(YAHOO.ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){ + return false; + } + // then bubble it up to the tree if the event wasn't cancelled + if(this.ownerTree){ + if(this.ownerTree.fireEvent.apply(this.ownerTree, arguments) === false){ + return false; + } + } + return true; + }, + + isLeaf : function(){ + return this.leaf === true; + }, + + setFirstChild : function(node){ + this.firstChild = node; + }, + + setLastChild : function(node){ + this.lastChild = node; + }, + + isLast : function(){ + return (!this.parentNode ? true : this.parentNode.lastChild == this); + }, + + isFirst : function(){ + return (!this.parentNode ? true : this.parentNode.firstChild == this); + }, + + hasChildNodes : function(){ + return !this.isLeaf() && this.childNodes.length > 0; + }, + + appendChild : function(node){ + var multi = false; + if(node instanceof Array){ + multi = node; + }else if(arguments.length > 1){ + multi = arguments; + } + // if passed an array or multiple args do them one by one + if(multi){ + for(var i = 0, len = multi.length; i < len; i++) { + this.appendChild(multi[i]); + } + }else{ + if(this.fireEvent('beforeappend', this.ownerTree, this, node) === false){ + return false; + } + var index = this.childNodes.length; + var oldParent = node.parentNode; + // it's a move, make sure we move it cleanly + if(oldParent){ + if(node.fireEvent('beforemove', node.getOwnerTree(), node, oldParent, this, index) === false){ + return false; + } + oldParent.removeChild(node); + } + var index = this.childNodes.length; + if(index == 0){ + this.setFirstChild(node); + } + this.childNodes.push(node); + node.parentNode = this; + var ps = this.childNodes[index-1]; + if(ps){ + node.previousSibling = ps; + ps.nextSibling = node; + } + this.setLastChild(node); + node.setOwnerTree(this.getOwnerTree()); + this.fireEvent('append', this.ownerTree, this, node, index); + if(oldParent){ + node.fireEvent('move', this.ownerTree, node, oldParent, this, index); + } + return node; + } + }, + + removeChild : function(node){ + var index = this.childNodes.indexOf(node); + if(index == -1){ + return false; + } + if(this.fireEvent('beforeremove', this.ownerTree, this, node) === false){ + return false; + } + + // remove it from childNodes collection + this.childNodes.splice(index, 1); + + // update siblings + if(node.previousSibling){ + node.previousSibling.nextSibling = node.nextSibling; + } + if(node.nextSibling){ + node.nextSibling.previousSibling = node.previousSibling; + } + + // update child refs + if(this.firstChild == node){ + this.setFirstChild(node.nextSibling); + } + if(this.lastChild == node){ + this.setLastChild(node.previousSibling); + } + + node.setOwnerTree(null); + // clear any references from the node + node.parentNode = null; + node.previousSibling = null; + node.nextSibling = null; + this.fireEvent('remove', this.ownerTree, this, node); + return node; + }, + + insertBefore : function(node, refNode){ + if(!refNode){ // like standard Dom, refNode can be null for append + return this.appendChild(node); + } + // nothing to do + if(node == refNode){ + return false; + } + + if(this.fireEvent('beforeinsert', this.ownerTree, this, node, refNode) === false){ + return false; + } + var index = this.childNodes.indexOf(refNode); + var oldParent = node.parentNode; + var refIndex = index; + + // when moving internally, indexes will change after remove + if(oldParent == this && this.childNodes.indexOf(node) < index){ + refIndex--; + } + + // it's a move, make sure we move it cleanly + if(oldParent){ + if(node.fireEvent('beforemove', node.getOwnerTree(), node, oldParent, this, index, refNode) === false){ + return false; + } + oldParent.removeChild(node); + } + if(refIndex == 0){ + this.setFirstChild(node); + } + this.childNodes.splice(refIndex, 0, node); + node.parentNode = this; + var ps = this.childNodes[refIndex-1]; + if(ps){ + node.previousSibling = ps; + ps.nextSibling = node; + } + node.nextSibling = refNode; + node.setOwnerTree(this.getOwnerTree()); + this.fireEvent('insert', this.ownerTree, this, node, refNode); + if(oldParent){ + node.fireEvent('move', this.ownerTree, node, oldParent, this, refIndex, refNode); + } + return node; + }, + + item : function(index){ + return this.childNodes[index]; + }, + + replaceChild : function(newChild, oldChild){ + this.insertBefore(newChild, oldChild); + this.removeChild(oldChild); + return oldChild; + }, + + indexOf : function(child){ + return this.childNodes.indexOf(child); + }, + + getOwnerTree : function(){ + // if it doesn't have one, look for one + if(!this.ownerTree){ + var p = this; + while(p){ + if(p.ownerTree){ + this.ownerTree = p.ownerTree; + break; + } + p = p.parentNode; + } + } + return this.ownerTree; + }, + + setOwnerTree : function(tree){ + // if it's move, we need to update everyone + if(tree != this.ownerTree){ + if(this.ownerTree){ + this.ownerTree.unregisterNode(this); + } + this.ownerTree = tree; + var cs = this.childNodes; + for(var i = 0, len = cs.length; i < len; i++) { + cs[i].setOwnerTree(tree); + } + if(tree){ + tree.registerNode(this); + } + } + }, + + getPath : function(attr){ + attr = attr || 'id'; + var p = this.parentNode; + var b = [this.attributes[attr]]; + while(p){ + b.unshift(p.attributes[attr]); + p = p.parentNode; + } + var sep = this.getOwnerTree().pathSeparator; + return sep + b.join(sep); + }, + + bubble : function(fn, scope, args){ + var p = this; + while(p){ + if(fn.call(scope || p, args || p) === false){ + break; + } + p = p.parentNode; + } + }, + + cascade : function(fn, scope, args){ + if(fn.call(scope || this, args || this) !== false){ + var cs = this.childNodes; + for(var i = 0, len = cs.length; i < len; i++) { + cs[i].cascade(fn, scope, args); + } + } + }, + + eachChild : function(fn, scope, args){ + var cs = this.childNodes; + for(var i = 0, len = cs.length; i < len; i++) { + if(fn.call(scope || this, args || cs[i]) === false){ + break; + } + } + }, + + findChild : function(attribute, value){ + var cs = this.childNodes; + for(var i = 0, len = cs.length; i < len; i++) { + if(cs[i].attributes[attribute] == value){ + return cs[i]; + } + } + return null; + }, + + /** + * Sorts this nodes children using the supplied sort function + * @param {Function} fn + * @param {Object} scope + */ + sort : function(fn, scope){ + var cs = this.childNodes; + var len = cs.length; + if(len > 0){ + var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn; + cs.sort(sortFn); + for(var i = 0; i < len; i++){ + var n = cs[i]; + n.previousSibling = cs[i-1]; + n.nextSibling = cs[i+1]; + if(i == 0){ + this.setFirstChild(n); + } + if(i == len-1){ + this.setLastChild(n); + } + } + } + }, + + contains : function(node){ + return node.isAncestor(this); + }, + + isAncestor : function(node){ + var p = this.parentNode; + while(p){ + if(p == node){ + return true; + } + p = p.parentNode; + } + return false; + }, + + toString : function(){ + return '[Node'+(this.id?' '+this.id:'')+']'; + } +}); -- cgit v0.9.0.2