author | Giulio Cesare Solaroli <giulio.cesare@solaroli.it> | 2011-10-03 16:04:12 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@solaroli.it> | 2011-10-03 16:04:12 (UTC) |
commit | 541bb378ddece2eab135a8066a16994e94436dea (patch) (unidiff) | |
tree | ff160ea3e26f7fe07fcfd401387c5a0232ca715e /frontend/beta/js/YUI-extensions/tree | |
parent | 1bf431fd3d45cbdf4afa3e12afefe5d24f4d3bc7 (diff) | |
parent | ecad5e895831337216544e81f1a467e0c68c4a6a (diff) | |
download | clipperz-541bb378ddece2eab135a8066a16994e94436dea.zip clipperz-541bb378ddece2eab135a8066a16994e94436dea.tar.gz clipperz-541bb378ddece2eab135a8066a16994e94436dea.tar.bz2 |
Merge pull request #1 from gcsolaroli/master
First version of the restructured repository
Diffstat (limited to 'frontend/beta/js/YUI-extensions/tree') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/beta/js/YUI-extensions/tree/AsyncTreeNode.js | 58 | ||||
-rw-r--r-- | frontend/beta/js/YUI-extensions/tree/TreeDragZone.js | 43 | ||||
-rw-r--r-- | frontend/beta/js/YUI-extensions/tree/TreeDropZone.js | 228 | ||||
-rw-r--r-- | frontend/beta/js/YUI-extensions/tree/TreeFilter.js | 105 | ||||
-rw-r--r-- | frontend/beta/js/YUI-extensions/tree/TreeLoader.js | 107 | ||||
-rw-r--r-- | frontend/beta/js/YUI-extensions/tree/TreeNode.js | 300 | ||||
-rw-r--r-- | frontend/beta/js/YUI-extensions/tree/TreeNodeUI.js | 452 | ||||
-rw-r--r-- | frontend/beta/js/YUI-extensions/tree/TreePanel.js | 213 | ||||
-rw-r--r-- | frontend/beta/js/YUI-extensions/tree/TreeSelectionModel.js | 195 | ||||
-rw-r--r-- | frontend/beta/js/YUI-extensions/tree/TreeSorter.js | 49 |
10 files changed, 1750 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI-extensions/tree/AsyncTreeNode.js b/frontend/beta/js/YUI-extensions/tree/AsyncTreeNode.js new file mode 100644 index 0000000..5d48b00 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/tree/AsyncTreeNode.js | |||
@@ -0,0 +1,58 @@ | |||
1 | YAHOO.ext.tree.AsyncTreeNode = function(config){ | ||
2 | this.loaded = false; | ||
3 | this.loading = false; | ||
4 | YAHOO.ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments); | ||
5 | this.events['beforeload'] = true; | ||
6 | this.events['load'] = true; | ||
7 | }; | ||
8 | YAHOO.extendX(YAHOO.ext.tree.AsyncTreeNode, YAHOO.ext.tree.TreeNode, { | ||
9 | expand : function(deep, anim, callback){ | ||
10 | if(this.loading){ // if an async load is already running, waiting til it's done | ||
11 | var timer; | ||
12 | var f = function(){ | ||
13 | if(!this.loading){ // done loading | ||
14 | clearInterval(timer); | ||
15 | this.expand(deep, anim, callback); | ||
16 | } | ||
17 | }.createDelegate(this); | ||
18 | timer = setInterval(f, 200); | ||
19 | } | ||
20 | if(!this.loaded){ | ||
21 | if(this.fireEvent('beforeload', this) === false){ | ||
22 | return; | ||
23 | } | ||
24 | this.loading = true; | ||
25 | this.ui.beforeLoad(this); | ||
26 | var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader(); | ||
27 | if(loader){ | ||
28 | loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback])); | ||
29 | return; | ||
30 | } | ||
31 | } | ||
32 | YAHOO.ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback); | ||
33 | }, | ||
34 | |||
35 | isLoading : function(){ | ||
36 | return this.loading; | ||
37 | }, | ||
38 | |||
39 | loadComplete : function(deep, anim, callback){ | ||
40 | this.loading = false; | ||
41 | this.loaded = true; | ||
42 | this.ui.afterLoad(this); | ||
43 | this.fireEvent('load', this); | ||
44 | this.expand(deep, anim, callback); | ||
45 | }, | ||
46 | |||
47 | isLoaded : function(){ | ||
48 | return this.loaded; | ||
49 | }, | ||
50 | |||
51 | hasChildNodes : function(){ | ||
52 | if(!this.isLeaf() && !this.loaded){ | ||
53 | return true; | ||
54 | }else{ | ||
55 | return YAHOO.ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this); | ||
56 | } | ||
57 | } | ||
58 | }); | ||
diff --git a/frontend/beta/js/YUI-extensions/tree/TreeDragZone.js b/frontend/beta/js/YUI-extensions/tree/TreeDragZone.js new file mode 100644 index 0000000..9b77b3c --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/tree/TreeDragZone.js | |||
@@ -0,0 +1,43 @@ | |||
1 | YAHOO.ext.tree.TreeDragZone = function(tree, config){ | ||
2 | YAHOO.ext.tree.TreeDragZone.superclass.constructor.call(this, tree.getEl(), config); | ||
3 | this.tree = tree; | ||
4 | }; | ||
5 | |||
6 | YAHOO.extendX(YAHOO.ext.tree.TreeDragZone, YAHOO.ext.dd.DragZone, { | ||
7 | ddGroup : 'TreeDD', | ||
8 | |||
9 | onBeforeDrag : function(data, e){ | ||
10 | var n = data.node; | ||
11 | return n && n.draggable && !n.disabled; | ||
12 | }, | ||
13 | |||
14 | onInitDrag : function(e){ | ||
15 | var data = this.dragData; | ||
16 | this.tree.getSelectionModel().select(data.node); | ||
17 | this.proxy.update(''); | ||
18 | data.node.ui.appendDDGhost(this.proxy.ghost.dom); | ||
19 | this.tree.fireEvent('startdrag', this.tree, data.node, e); | ||
20 | }, | ||
21 | |||
22 | getRepairXY : function(e, data){ | ||
23 | return data.node.ui.getDDRepairXY(); | ||
24 | }, | ||
25 | |||
26 | onEndDrag : function(data, e){ | ||
27 | this.tree.fireEvent('enddrag', this.tree, data.node, e); | ||
28 | }, | ||
29 | |||
30 | onValidDrop : function(dd, e, id){ | ||
31 | this.tree.fireEvent('dragdrop', this.tree, this.dragData.node, dd, e); | ||
32 | this.hideProxy(); | ||
33 | }, | ||
34 | |||
35 | beforeInvalidDrop : function(e, id){ | ||
36 | if(YAHOO.util.Anim){ | ||
37 | // this scrolls the original position back into view | ||
38 | var sm = this.tree.getSelectionModel(); | ||
39 | sm.clearSelections(); | ||
40 | sm.select(this.dragData.node); | ||
41 | } | ||
42 | } | ||
43 | }); | ||
diff --git a/frontend/beta/js/YUI-extensions/tree/TreeDropZone.js b/frontend/beta/js/YUI-extensions/tree/TreeDropZone.js new file mode 100644 index 0000000..91c24e1 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/tree/TreeDropZone.js | |||
@@ -0,0 +1,228 @@ | |||
1 | YAHOO.ext.tree.TreeDropZone = function(tree, config){ | ||
2 | this.allowParentInsert = false; | ||
3 | this.allowContainerDrop = false; | ||
4 | this.appendOnly = false; | ||
5 | YAHOO.ext.tree.TreeDropZone.superclass.constructor.call(this, tree.container, config); | ||
6 | this.tree = tree; | ||
7 | this.lastInsertClass = 'ytree-no-status'; | ||
8 | this.dragOverData = {}; | ||
9 | }; | ||
10 | |||
11 | YAHOO.extendX(YAHOO.ext.tree.TreeDropZone, YAHOO.ext.dd.DropZone, { | ||
12 | ddGroup : 'TreeDD', | ||
13 | |||
14 | expandDelay : 1000, | ||
15 | |||
16 | expandNode : function(node){ | ||
17 | if(node.hasChildNodes() && !node.isExpanded()){ | ||
18 | node.expand(false, null, this.triggerCacheRefresh.createDelegate(this)); | ||
19 | } | ||
20 | }, | ||
21 | |||
22 | queueExpand : function(node){ | ||
23 | this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]); | ||
24 | }, | ||
25 | |||
26 | cancelExpand : function(){ | ||
27 | if(this.expandProcId){ | ||
28 | clearTimeout(this.expandProcId); | ||
29 | this.expandProcId = false; | ||
30 | } | ||
31 | }, | ||
32 | |||
33 | isValidDropPoint : function(n, pt, dd, e, data){ | ||
34 | if(!n || !data){ return false; } | ||
35 | var targetNode = n.node; | ||
36 | var dropNode = data.node; | ||
37 | // default drop rules | ||
38 | if(!(targetNode && targetNode.isTarget && pt)){ | ||
39 | return false; | ||
40 | } | ||
41 | if(pt == 'append' && targetNode.allowChildren === false){ | ||
42 | return false; | ||
43 | } | ||
44 | if((pt == 'above' || pt == 'below') && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){ | ||
45 | return false; | ||
46 | } | ||
47 | if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){ | ||
48 | return false; | ||
49 | } | ||
50 | // reuse the object | ||
51 | var overEvent = this.dragOverData; | ||
52 | overEvent.tree = this.tree; | ||
53 | overEvent.target = targetNode; | ||
54 | overEvent.data = data; | ||
55 | overEvent.point = pt; | ||
56 | overEvent.source = dd; | ||
57 | overEvent.rawEvent = e; | ||
58 | overEvent.dropNode = dropNode; | ||
59 | overEvent.cancel = false; | ||
60 | var result = this.tree.fireEvent('nodedragover', overEvent); | ||
61 | return overEvent.cancel === false && result !== false; | ||
62 | }, | ||
63 | |||
64 | getDropPoint : function(e, n, dd){ | ||
65 | var tn = n.node; | ||
66 | if(tn.isRoot){ | ||
67 | return tn.allowChildren !== false ? 'ap-pend' : false; // always append for root | ||
68 | } | ||
69 | var dragEl = n.ddel; | ||
70 | var t = YAHOO.util.Dom.getY(dragEl), b = t + dragEl.offsetHeight; | ||
71 | var y = YAHOO.util.Event.getPageY(e); | ||
72 | var noAppend = tn.allowChildren === false || tn.isLeaf(); | ||
73 | if(this.appendOnly || tn.parentNode.allowChildren === false){ | ||
74 | return noAppend ? false : 'append'; | ||
75 | } | ||
76 | var noBelow = false; | ||
77 | if(!this.allowParentInsert){ | ||
78 | noBelow = tn.hasChildNodes() && tn.isExpanded(); | ||
79 | } | ||
80 | var q = (b - t) / (noAppend ? 2 : 3); | ||
81 | if(y >= t && y < t + q){ | ||
82 | return 'above'; | ||
83 | }else if(!noBelow && (noAppend || y >= b-q && y <= b)){ | ||
84 | return 'below'; | ||
85 | }else{ | ||
86 | return 'append'; | ||
87 | } | ||
88 | return false; | ||
89 | }, | ||
90 | |||
91 | onNodeEnter : function(n, dd, e, data){ | ||
92 | this.cancelExpand(); | ||
93 | }, | ||
94 | |||
95 | onNodeOver : function(n, dd, e, data){ | ||
96 | var pt = this.getDropPoint(e, n, dd); | ||
97 | var node = n.node; | ||
98 | |||
99 | // auto node expand check | ||
100 | if(!this.expandProcId && pt == 'append' && node.hasChildNodes() && !n.node.isExpanded()){ | ||
101 | this.queueExpand(node); | ||
102 | }else if(pt != 'append'){ | ||
103 | this.cancelExpand(); | ||
104 | } | ||
105 | |||
106 | // set the insert point style on the target node | ||
107 | var returnCls = this.dropNotAllowed; | ||
108 | if(this.isValidDropPoint(n, pt, dd, e, data)){ | ||
109 | if(pt){ | ||
110 | var el = n.ddel; | ||
111 | var cls, returnCls; | ||
112 | if(pt == 'above'){ | ||
113 | returnCls = n.node.isFirst() ? 'ytree-drop-ok-above' : 'ytree-drop-ok-between'; | ||
114 | cls = 'ytree-drag-insert-above'; | ||
115 | }else if(pt == 'below'){ | ||
116 | returnCls = n.node.isLast() ? 'ytree-drop-ok-below' : 'ytree-drop-ok-between'; | ||
117 | cls = 'ytree-drag-insert-below'; | ||
118 | }else{ | ||
119 | returnCls = 'ytree-drop-ok-append'; | ||
120 | cls = 'ytree-drag-append'; | ||
121 | } | ||
122 | if(this.lastInsertClass != cls){ | ||
123 | YAHOO.util.Dom.replaceClass(el, this.lastInsertClass, cls); | ||
124 | this.lastInsertClass = cls; | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | return returnCls; | ||
129 | }, | ||
130 | |||
131 | onNodeOut : function(n, dd, e, data){ | ||
132 | this.cancelExpand(); | ||
133 | this.removeDropIndicators(n); | ||
134 | }, | ||
135 | |||
136 | onNodeDrop : function(n, dd, e, data){ | ||
137 | var point = this.getDropPoint(e, n, dd); | ||
138 | var targetNode = n.node; | ||
139 | targetNode.ui.startDrop(); | ||
140 | if(!this.isValidDropPoint(n, point, dd, e, data)){ | ||
141 | targetNode.ui.endDrop(); | ||
142 | return false; | ||
143 | } | ||
144 | // first try to find the drop node | ||
145 | var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null); | ||
146 | var dropEvent = { | ||
147 | tree : this.tree, | ||
148 | target: targetNode, | ||
149 | data: data, | ||
150 | point: point, | ||
151 | source: dd, | ||
152 | rawEvent: e, | ||
153 | dropNode: dropNode, | ||
154 | cancel: dropNode ? false : true | ||
155 | }; | ||
156 | var retval = this.tree.fireEvent('beforenodedrop', dropEvent); | ||
157 | if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){ | ||
158 | targetNode.ui.endDrop(); | ||
159 | return false; | ||
160 | } | ||
161 | if(point == 'append' && !targetNode.isExpanded()){ | ||
162 | targetNode.expand(false, null, function(){ | ||
163 | this.completeDrop(dropEvent); | ||
164 | }.createDelegate(this)); | ||
165 | }else{ | ||
166 | this.completeDrop(dropEvent); | ||
167 | } | ||
168 | return true; | ||
169 | }, | ||
170 | |||
171 | completeDrop : function(de){ | ||
172 | var ns = de.dropNode, p = de.point, t = de.target; | ||
173 | if(!(ns instanceof Array)){ | ||
174 | ns = [ns]; | ||
175 | } | ||
176 | var n; | ||
177 | for(var i = 0, len = ns.length; i < len; i++){ | ||
178 | n = ns[i]; | ||
179 | if(p == 'above'){ | ||
180 | t.parentNode.insertBefore(n, t); | ||
181 | }else if(p == 'below'){ | ||
182 | t.parentNode.insertBefore(n, t.nextSibling); | ||
183 | }else{ | ||
184 | t.appendChild(n); | ||
185 | } | ||
186 | } | ||
187 | n.select(); // select and highlight the last insert | ||
188 | if(this.tree.hlDrop){ | ||
189 | n.ui.highlight(); | ||
190 | } | ||
191 | t.ui.endDrop(); | ||
192 | this.tree.fireEvent('nodedrop', de); | ||
193 | }, | ||
194 | |||
195 | afterNodeMoved : function(dd, data, e, targetNode, dropNode){ | ||
196 | if(this.tree.hlDrop){ | ||
197 | dropNode.select(); | ||
198 | dropNode.ui.highlight(); | ||
199 | } | ||
200 | this.tree.fireEvent('nodedrop', this.tree, targetNode, data, dd, e); | ||
201 | }, | ||
202 | |||
203 | getTree : function(){ | ||
204 | return this.tree; | ||
205 | }, | ||
206 | |||
207 | removeDropIndicators : function(n){ | ||
208 | if(n && n.ddel){ | ||
209 | var el = n.ddel; | ||
210 | YAHOO.util.Dom.removeClass(el, 'ytree-drag-insert-above'); | ||
211 | YAHOO.util.Dom.removeClass(el, 'ytree-drag-insert-below'); | ||
212 | YAHOO.util.Dom.removeClass(el, 'ytree-drag-append'); | ||
213 | this.lastInsertClass = '_noclass'; | ||
214 | } | ||
215 | }, | ||
216 | |||
217 | beforeDragDrop : function(target, e, id){ | ||
218 | this.cancelExpand(); | ||
219 | return true; | ||
220 | }, | ||
221 | |||
222 | afterRepair : function(data){ | ||
223 | if(data){ | ||
224 | data.node.ui.highlight(); | ||
225 | } | ||
226 | this.hideProxy(); | ||
227 | } | ||
228 | }); | ||
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 @@ | |||
1 | /** | ||
2 | * This doesn't update the indent (lines) or expand collapse icons of the nodes | ||
3 | */ | ||
4 | YAHOO.ext.tree.TreeFilter = function(tree, config){ | ||
5 | this.tree = tree; | ||
6 | this.filtered = {}; | ||
7 | YAHOO.ext.util.Config.apply(this, config, { | ||
8 | clearBlank:false, | ||
9 | reverse:false, | ||
10 | autoClear:false, | ||
11 | remove:false | ||
12 | }); | ||
13 | }; | ||
14 | |||
15 | YAHOO.ext.tree.TreeFilter.prototype = { | ||
16 | /** | ||
17 | * Filter the data by a specific attribute. | ||
18 | * @param {String/RegExp} value Either string that the attribute value | ||
19 | * should start with or a RegExp to test against the attribute | ||
20 | * @param {String} attr (optional) The attribute passed in your node's attributes collection. Defaults to "text". | ||
21 | * @param {TreeNode} startNode (optional) The node to start the filter at. | ||
22 | */ | ||
23 | filter : function(value, attr, startNode){ | ||
24 | attr = attr || 'text'; | ||
25 | var f; | ||
26 | if(typeof value == 'string'){ | ||
27 | var vlen = value.length; | ||
28 | // auto clear empty filter | ||
29 | if(vlen == 0 && this.clearBlank){ | ||
30 | this.clearFilter(); | ||
31 | return; | ||
32 | } | ||
33 | value = value.toLowerCase(); | ||
34 | f = function(n){ | ||
35 | return n.attributes[attr].substr(0, vlen).toLowerCase() == value; | ||
36 | } | ||
37 | }else if(value.exec){ // regex? | ||
38 | f = function(n){ | ||
39 | return value.test(n.attributes[attr]); | ||
40 | } | ||
41 | }else{ | ||
42 | throw 'Illegal filter type, must be string or regex'; | ||
43 | } | ||
44 | this.filterBy(f, null, startNode); | ||
45 | }, | ||
46 | |||
47 | /** | ||
48 | * Filter by a function. The passed function will be called with each | ||
49 | * node in the tree (or from the startNode). If the function returns true, the node is kept | ||
50 | * otherwise it is filtered. If a node is filtered, it's children are also filtered. | ||
51 | * @param {Function} fn The filter function | ||
52 | * @param {Object} scope (optional) The scope of the function (defaults to the current node) | ||
53 | */ | ||
54 | filterBy : function(fn, scope, startNode){ | ||
55 | startNode = startNode || this.tree.root; | ||
56 | if(this.autoClear){ | ||
57 | this.clearFilter(); | ||
58 | } | ||
59 | var af = this.filtered, rv = this.reverse; | ||
60 | var f = function(n){ | ||
61 | if(n == startNode){ | ||
62 | return true; | ||
63 | } | ||
64 | if(af[n.id]){ | ||
65 | return false; | ||
66 | } | ||
67 | var m = fn.call(scope || n, n); | ||
68 | if(!m || rv){ | ||
69 | af[n.id] = n; | ||
70 | n.ui.hide(); | ||
71 | return false; | ||
72 | } | ||
73 | return true; | ||
74 | } | ||
75 | startNode.cascade(f); | ||
76 | if(this.remove){ | ||
77 | for(var id in af){ | ||
78 | if(typeof id != 'function'){ | ||
79 | var n = af[id]; | ||
80 | if(n && n.parentNode){ | ||
81 | n.parentNode.removeChild(n); | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | }, | ||
87 | |||
88 | /** | ||
89 | * Clears the current filter. Note: with the "remove" option | ||
90 | * set a filter cannot be cleared. | ||
91 | */ | ||
92 | clear : function(){ | ||
93 | var t = this.tree; | ||
94 | var af = this.filtered; | ||
95 | for(var id in af){ | ||
96 | if(typeof id != 'function'){ | ||
97 | var n = af[id]; | ||
98 | if(n){ | ||
99 | n.ui.show(); | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | this.filtered = {}; | ||
104 | } | ||
105 | }; | ||
diff --git a/frontend/beta/js/YUI-extensions/tree/TreeLoader.js b/frontend/beta/js/YUI-extensions/tree/TreeLoader.js new file mode 100644 index 0000000..34989bd --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/tree/TreeLoader.js | |||
@@ -0,0 +1,107 @@ | |||
1 | YAHOO.ext.tree.TreeLoader = function(config){ | ||
2 | this.baseParams = {}; | ||
3 | this.requestMethod = 'POST'; | ||
4 | YAHOO.ext.util.Config.apply(this, config); | ||
5 | |||
6 | this.events = { | ||
7 | 'beforeload' : true, | ||
8 | 'load' : true, | ||
9 | 'loadexception' : true | ||
10 | }; | ||
11 | }; | ||
12 | |||
13 | YAHOO.extendX(YAHOO.ext.tree.TreeLoader, YAHOO.ext.util.Observable, { | ||
14 | load : function(node, callback){ | ||
15 | if(node.attributes.children){ // preloaded json children | ||
16 | var cs = node.attributes.children; | ||
17 | for(var i = 0, len = cs.length; i < len; i++){ | ||
18 | node.appendChild(this.createNode(cs[i])); | ||
19 | } | ||
20 | if(typeof callback == 'function'){ | ||
21 | callback(); | ||
22 | } | ||
23 | }else if(this.dataUrl){ | ||
24 | this.requestData(node, callback); | ||
25 | } | ||
26 | }, | ||
27 | |||
28 | getParams: function(node){ | ||
29 | var buf = [], bp = this.baseParams; | ||
30 | for(var key in bp){ | ||
31 | if(typeof bp[key] != 'function'){ | ||
32 | buf.push(encodeURIComponent(key), '=', encodeURIComponent(bp[key]), '&'); | ||
33 | } | ||
34 | } | ||
35 | buf.push('node=', encodeURIComponent(node.id)); | ||
36 | return buf.join(''); | ||
37 | }, | ||
38 | |||
39 | requestData : function(node, callback){ | ||
40 | if(this.fireEvent('beforeload', this, node, callback) !== false){ | ||
41 | var params = this.getParams(node); | ||
42 | var cb = { | ||
43 | success: this.handleResponse, | ||
44 | failure: this.handleFailure, | ||
45 | scope: this, | ||
46 | argument: {callback: callback, node: node} | ||
47 | }; | ||
48 | this.transId = YAHOO.util.Connect.asyncRequest(this.requestMethod, this.dataUrl, cb, params); | ||
49 | }else{ | ||
50 | // if the load is cancelled, make sure we notify | ||
51 | // the node that we are done | ||
52 | if(typeof callback == 'function'){ | ||
53 | callback(); | ||
54 | } | ||
55 | } | ||
56 | }, | ||
57 | |||
58 | isLoading : function(){ | ||
59 | return this.transId ? true : false; | ||
60 | }, | ||
61 | |||
62 | abort : function(){ | ||
63 | if(this.isLoading()){ | ||
64 | YAHOO.util.Connect.abort(this.transId); | ||
65 | } | ||
66 | }, | ||
67 | |||
68 | createNode : function(attr){ | ||
69 | if(this.applyLoader !== false){ | ||
70 | attr.loader = this; | ||
71 | } | ||
72 | return(attr.leaf ? | ||
73 | new YAHOO.ext.tree.TreeNode(attr) : | ||
74 | new YAHOO.ext.tree.AsyncTreeNode(attr)); | ||
75 | }, | ||
76 | |||
77 | processResponse : function(response, node, callback){ | ||
78 | var json = response.responseText; | ||
79 | try { | ||
80 | var o = eval('('+json+')'); | ||
81 | for(var i = 0, len = o.length; i < len; i++){ | ||
82 | node.appendChild(this.createNode(o[i])); | ||
83 | } | ||
84 | if(typeof callback == 'function'){ | ||
85 | callback(); | ||
86 | } | ||
87 | }catch(e){ | ||
88 | this.handleFailure(response); | ||
89 | } | ||
90 | }, | ||
91 | |||
92 | handleResponse : function(response){ | ||
93 | this.transId = false; | ||
94 | var a = response.argument; | ||
95 | this.processResponse(response, a.node, a.callback); | ||
96 | this.fireEvent('load', this, a.node, response); | ||
97 | }, | ||
98 | |||
99 | handleFailure : function(response){ | ||
100 | this.transId = false; | ||
101 | var a = response.argument; | ||
102 | this.fireEvent('loadexception', this, a.node, response); | ||
103 | if(typeof a.callback == 'function'){ | ||
104 | a.callback(); | ||
105 | } | ||
106 | } | ||
107 | }); | ||
diff --git a/frontend/beta/js/YUI-extensions/tree/TreeNode.js b/frontend/beta/js/YUI-extensions/tree/TreeNode.js new file mode 100644 index 0000000..c676481 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/tree/TreeNode.js | |||
@@ -0,0 +1,300 @@ | |||
1 | /** | ||
2 | * @class YAHOO.ext.tree.TreeNode | ||
3 | * @extends YAHOO.ext.data.Node | ||
4 | * @cfg {Boolean} leaf true if this node is a leaf and does not have or cannot have children | ||
5 | * @cfg {Boolean} expanded true to start the node expanded | ||
6 | * @cfg {Boolean} draggable false to make this node undraggable if DD is on (default to true) | ||
7 | * @cfg {Boolean} isTarget false if this node cannot be drop on | ||
8 | * @cfg {Boolean} disabled true to start the node disabled | ||
9 | * @constructor | ||
10 | * @param {Object} attributes The attributes/config for the node | ||
11 | */ | ||
12 | YAHOO.ext.tree.TreeNode = function(attributes){ | ||
13 | attributes = attributes || {}; | ||
14 | if(typeof attributes == 'string'){ | ||
15 | attributes = {text: attributes}; | ||
16 | } | ||
17 | this.el = null; | ||
18 | this.childrenRendered = false; | ||
19 | this.rendered = false; | ||
20 | YAHOO.ext.tree.TreeNode.superclass.constructor.call(this, attributes); | ||
21 | this.expanded = attributes.expanded === true; | ||
22 | this.isTarget = attributes.isTarget !== false; | ||
23 | this.draggable = attributes.draggable !== false && attributes.allowDrag !== false; | ||
24 | this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false; | ||
25 | this.text = attributes.text; | ||
26 | this.disabled = attributes.disabled === true; | ||
27 | |||
28 | YAHOO.ext.util.Config.apply(this.events, { | ||
29 | 'textchange' : true, | ||
30 | 'beforeexpand' : true, | ||
31 | 'beforecollapse' : true, | ||
32 | 'expand' : true, | ||
33 | 'disabledchange' : true, | ||
34 | 'collapse' : true, | ||
35 | 'beforeclick':true, | ||
36 | 'click':true, | ||
37 | 'dblclick':true, | ||
38 | 'contentmenu':true, | ||
39 | 'beforechildrenrendered':true | ||
40 | }); | ||
41 | |||
42 | var uiClass = this.attributes.uiProvider || YAHOO.ext.tree.TreeNodeUI; | ||
43 | this.ui = new uiClass(this); | ||
44 | }; | ||
45 | YAHOO.extendX(YAHOO.ext.tree.TreeNode, YAHOO.ext.data.Node, { | ||
46 | isExpanded : function(){ | ||
47 | return this.expanded; | ||
48 | }, | ||
49 | |||
50 | getUI : function(){ | ||
51 | return this.ui; | ||
52 | }, | ||
53 | |||
54 | setFirstChild : function(node){ | ||
55 | var of = this.firstChild; | ||
56 | YAHOO.ext.tree.TreeNode.superclass.setFirstChild.call(this, node); | ||
57 | if(this.childrenRendered && of && node != of){ | ||
58 | of.renderIndent(true, true); | ||
59 | } | ||
60 | if(this.rendered){ | ||
61 | this.renderIndent(true, true); | ||
62 | } | ||
63 | }, | ||
64 | |||
65 | setLastChild : function(node){ | ||
66 | var ol = this.lastChild; | ||
67 | YAHOO.ext.tree.TreeNode.superclass.setLastChild.call(this, node); | ||
68 | if(this.childrenRendered && ol && node != ol){ | ||
69 | ol.renderIndent(true, true); | ||
70 | } | ||
71 | if(this.rendered){ | ||
72 | this.renderIndent(true, true); | ||
73 | } | ||
74 | }, | ||
75 | |||
76 | // these methods are overridden to provide lazy rendering support | ||
77 | appendChild : function(){ | ||
78 | var node = YAHOO.ext.tree.TreeNode.superclass.appendChild.apply(this, arguments); | ||
79 | if(node && this.childrenRendered){ | ||
80 | node.render(); | ||
81 | } | ||
82 | this.ui.updateExpandIcon(); | ||
83 | return node; | ||
84 | }, | ||
85 | |||
86 | removeChild : function(node){ | ||
87 | this.ownerTree.getSelectionModel().unselect(node); | ||
88 | YAHOO.ext.tree.TreeNode.superclass.removeChild.apply(this, arguments); | ||
89 | // if it's been rendered remove dom node | ||
90 | if(this.childrenRendered){ | ||
91 | node.ui.remove(); | ||
92 | } | ||
93 | if(this.childNodes.length < 1){ | ||
94 | this.collapse(false, false); | ||
95 | }else{ | ||
96 | this.ui.updateExpandIcon(); | ||
97 | } | ||
98 | return node; | ||
99 | }, | ||
100 | |||
101 | insertBefore : function(node, refNode){ | ||
102 | var newNode = YAHOO.ext.tree.TreeNode.superclass.insertBefore.apply(this, arguments); | ||
103 | if(newNode && refNode && this.childrenRendered){ | ||
104 | node.render(); | ||
105 | } | ||
106 | this.ui.updateExpandIcon(); | ||
107 | return newNode; | ||
108 | }, | ||
109 | |||
110 | setText : function(text){ | ||
111 | var oldText = this.text; | ||
112 | this.text = text; | ||
113 | this.attributes.text = text; | ||
114 | if(this.rendered){ // event without subscribing | ||
115 | this.ui.onTextChange(this, text, oldText); | ||
116 | } | ||
117 | this.fireEvent('textchange', this, text, oldText); | ||
118 | }, | ||
119 | |||
120 | select : function(){ | ||
121 | this.getOwnerTree().getSelectionModel().select(this); | ||
122 | }, | ||
123 | |||
124 | unselect : function(){ | ||
125 | this.getOwnerTree().getSelectionModel().unselect(this); | ||
126 | }, | ||
127 | |||
128 | isSelected : function(){ | ||
129 | return this.getOwnerTree().getSelectionModel().isSelected(node); | ||
130 | }, | ||
131 | |||
132 | expand : function(deep, anim, callback){ | ||
133 | if(!this.expanded){ | ||
134 | if(this.fireEvent('beforeexpand', this, deep, anim) === false){ | ||
135 | return; | ||
136 | } | ||
137 | if(!this.childrenRendered){ | ||
138 | this.renderChildren(); | ||
139 | } | ||
140 | this.expanded = true; | ||
141 | if((this.getOwnerTree().animate && anim !== false) || anim){ | ||
142 | this.ui.animExpand(function(){ | ||
143 | this.fireEvent('expand', this); | ||
144 | if(typeof callback == 'function'){ | ||
145 | callback(this); | ||
146 | } | ||
147 | if(deep === true){ | ||
148 | this.expandChildNodes(true); | ||
149 | } | ||
150 | }.createDelegate(this)); | ||
151 | return; | ||
152 | }else{ | ||
153 | this.ui.expand(); | ||
154 | this.fireEvent('expand', this); | ||
155 | if(typeof callback == 'function'){ | ||
156 | callback(this); | ||
157 | } | ||
158 | } | ||
159 | }else{ | ||
160 | if(typeof callback == 'function'){ | ||
161 | callback(this); | ||
162 | } | ||
163 | } | ||
164 | if(deep === true){ | ||
165 | this.expandChildNodes(true); | ||
166 | } | ||
167 | }, | ||
168 | |||
169 | collapse : function(deep, anim){ | ||
170 | if(this.expanded && (!this.isRoot || (this.isRoot && this.getOwnerTree().rootVisible))){ | ||
171 | if(this.fireEvent('beforecollapse', this, deep, anim) === false){ | ||
172 | return; | ||
173 | } | ||
174 | this.expanded = false; | ||
175 | if((this.getOwnerTree().animate && anim !== false) || anim){ | ||
176 | this.ui.animCollapse(function(){ | ||
177 | this.fireEvent('collapse', this); | ||
178 | if(deep === true){ | ||
179 | this.collapseChildNodes(true); | ||
180 | } | ||
181 | }.createDelegate(this)); | ||
182 | return; | ||
183 | }else{ | ||
184 | this.ui.collapse(); | ||
185 | this.fireEvent('collapse', this); | ||
186 | } | ||
187 | } | ||
188 | if(deep === true){ | ||
189 | var cs = this.childNodes; | ||
190 | for(var i = 0, len = cs.length; i < len; i++) { | ||
191 | cs[i].collapse(true) | ||
192 | } | ||
193 | } | ||
194 | }, | ||
195 | |||
196 | delayedExpand : function(delay){ | ||
197 | if(!this.expandProcId){ | ||
198 | this.expandProcId = this.expand.defer(delay, this); | ||
199 | } | ||
200 | }, | ||
201 | |||
202 | cancelExpand : function(){ | ||
203 | if(this.expandProcId){ | ||
204 | clearTimeout(this.expandProcId); | ||
205 | } | ||
206 | this.expandProcId = false; | ||
207 | }, | ||
208 | |||
209 | toggle : function(){ | ||
210 | if(this.expanded){ | ||
211 | this.collapse(); | ||
212 | }else{ | ||
213 | this.expand(); | ||
214 | } | ||
215 | }, | ||
216 | |||
217 | ensureVisible : function(){ | ||
218 | if(this.parentNode){ | ||
219 | this.parentNode.bubble(function(){ | ||
220 | this.expand(false, false); | ||
221 | }); | ||
222 | } | ||
223 | }, | ||
224 | |||
225 | expandChildNodes : function(deep){ | ||
226 | var cs = this.childNodes; | ||
227 | for(var i = 0, len = cs.length; i < len; i++) { | ||
228 | cs[i].expand(deep); | ||
229 | } | ||
230 | }, | ||
231 | |||
232 | collapseChildNodes : function(deep){ | ||
233 | var cs = this.childNodes; | ||
234 | for(var i = 0, len = cs.length; i < len; i++) { | ||
235 | cs[i].expand(deep); | ||
236 | } | ||
237 | }, | ||
238 | |||
239 | disable : function(){ | ||
240 | this.disabled = true; | ||
241 | this.unselect(); | ||
242 | if(this.rendered && this.ui.onDisableChange){ // event without subscribing | ||
243 | this.ui.onDisableChange(this, true); | ||
244 | } | ||
245 | this.fireEvent('disabledchange', this, true); | ||
246 | }, | ||
247 | |||
248 | enable : function(){ | ||
249 | this.disabled = false; | ||
250 | if(this.rendered && this.ui.onDisableChange){ // event without subscribing | ||
251 | this.ui.onDisableChange(this, false); | ||
252 | } | ||
253 | this.fireEvent('disabledchange', this, false); | ||
254 | }, | ||
255 | |||
256 | renderChildren : function(suppressEvent){ | ||
257 | if(suppressEvent !== false){ | ||
258 | this.fireEvent('beforechildrenrendered', this); | ||
259 | } | ||
260 | var cs = this.childNodes; | ||
261 | for(var i = 0, len = cs.length; i < len; i++){ | ||
262 | cs[i].render(true); | ||
263 | } | ||
264 | this.childrenRendered = true; | ||
265 | }, | ||
266 | |||
267 | sort : function(fn, scope){ | ||
268 | YAHOO.ext.tree.TreeNode.superclass.sort.apply(this, arguments); | ||
269 | if(this.childrenRendered){ | ||
270 | var cs = this.childNodes; | ||
271 | for(var i = 0, len = cs.length; i < len; i++){ | ||
272 | cs[i].render(true); | ||
273 | } | ||
274 | } | ||
275 | }, | ||
276 | |||
277 | render : function(bulkRender){ | ||
278 | this.ui.render(bulkRender); | ||
279 | if(!this.rendered){ | ||
280 | this.rendered = true; | ||
281 | if(this.expanded){ | ||
282 | this.expanded = false; | ||
283 | this.expand(false, false); | ||
284 | } | ||
285 | } | ||
286 | }, | ||
287 | |||
288 | renderIndent : function(deep, refresh){ | ||
289 | if(refresh){ | ||
290 | this.ui.childIndent = null; | ||
291 | } | ||
292 | this.ui.renderIndent(); | ||
293 | if(deep === true && this.childrenRendered){ | ||
294 | var cs = this.childNodes; | ||
295 | for(var i = 0, len = cs.length; i < len; i++){ | ||
296 | cs[i].renderIndent(true, refresh); | ||
297 | } | ||
298 | } | ||
299 | } | ||
300 | }); | ||
diff --git a/frontend/beta/js/YUI-extensions/tree/TreeNodeUI.js b/frontend/beta/js/YUI-extensions/tree/TreeNodeUI.js new file mode 100644 index 0000000..80927f4 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/tree/TreeNodeUI.js | |||
@@ -0,0 +1,452 @@ | |||
1 | /** | ||
2 | * The TreeNode UI implementation is separate from the | ||
3 | * tree implementation. Unless you are customizing the tree UI, | ||
4 | * you should never have to use this directly. | ||
5 | */ | ||
6 | YAHOO.ext.tree.TreeNodeUI = function(node){ | ||
7 | this.node = node; | ||
8 | this.rendered = false; | ||
9 | this.animating = false; | ||
10 | }; | ||
11 | |||
12 | YAHOO.ext.tree.TreeNodeUI.prototype = { | ||
13 | emptyIcon : Ext.BLANK_IMAGE_URL, | ||
14 | |||
15 | removeChild : function(node){ | ||
16 | if(this.rendered){ | ||
17 | this.ctNode.removeChild(node.ui.getEl()); | ||
18 | } | ||
19 | }, | ||
20 | |||
21 | beforeLoad : function(){ | ||
22 | YAHOO.util.Dom.addClass(this.elNode, 'ytree-node-loading'); | ||
23 | }, | ||
24 | |||
25 | afterLoad : function(){ | ||
26 | YAHOO.util.Dom.removeClass(this.elNode, 'ytree-node-loading'); | ||
27 | }, | ||
28 | |||
29 | onTextChange : function(node, text, oldText){ | ||
30 | if(this.rendered){ | ||
31 | this.textNode.innerHTML = text; | ||
32 | } | ||
33 | }, | ||
34 | |||
35 | onDisableChange : function(node, state){ | ||
36 | this.disabled = state; | ||
37 | if(state){ | ||
38 | YAHOO.util.Dom.addClass(this.elNode, 'ytree-node-disabled'); | ||
39 | }else{ | ||
40 | YAHOO.util.Dom.removeClass(this.elNode, 'ytree-node-disabled'); | ||
41 | } | ||
42 | }, | ||
43 | |||
44 | onSelectedChange : function(state){ | ||
45 | if(state){ | ||
46 | this.focus(); | ||
47 | YAHOO.util.Dom.addClass(this.elNode, 'ytree-selected'); | ||
48 | }else{ | ||
49 | this.blur(); | ||
50 | YAHOO.util.Dom.removeClass(this.elNode, 'ytree-selected'); | ||
51 | } | ||
52 | }, | ||
53 | |||
54 | onMove : function(tree, node, oldParent, newParent, index, refNode){ | ||
55 | this.childIndent = null; | ||
56 | if(this.rendered){ | ||
57 | var targetNode = newParent.ui.getContainer(); | ||
58 | if(!targetNode){//target not rendered | ||
59 | this.holder = document.createElement('div'); | ||
60 | this.holder.appendChild(this.wrap); | ||
61 | return; | ||
62 | } | ||
63 | var insertBefore = refNode ? refNode.ui.getEl() : null; | ||
64 | if(insertBefore){ | ||
65 | targetNode.insertBefore(this.wrap, insertBefore); | ||
66 | }else{ | ||
67 | targetNode.appendChild(this.wrap); | ||
68 | } | ||
69 | this.node.renderIndent(true); | ||
70 | } | ||
71 | }, | ||
72 | |||
73 | remove : function(){ | ||
74 | if(this.rendered){ | ||
75 | this.holder = document.createElement('div'); | ||
76 | this.holder.appendChild(this.wrap); | ||
77 | } | ||
78 | }, | ||
79 | |||
80 | fireEvent : function(){ | ||
81 | this.node.fireEvent.apply(this.node, arguments); | ||
82 | }, | ||
83 | |||
84 | initEvents : function(){ | ||
85 | this.node.on('move', this.onMove, this, true); | ||
86 | //this.node.on('hiddenchange', this.onHiddenChange, this, true); | ||
87 | |||
88 | // these were optimized out but a custom UI could use them | ||
89 | //this.node.on('remove', this.onChildRemoved, this, true); | ||
90 | //this.node.on('selectedstatechange', this.onSelectedChange, this, true); | ||
91 | //this.node.on('disabledchange', this.onDisableChange, this, true); | ||
92 | //this.node.on('textchange', this.onTextChange, this, true); | ||
93 | |||
94 | var E = YAHOO.util.Event; | ||
95 | var a = this.anchor; | ||
96 | |||
97 | var el = YAHOO.ext.Element.fly(a); | ||
98 | |||
99 | if(YAHOO.ext.util.Browser.isOpera){ // opera render bug ignores the CSS | ||
100 | el.setStyle('text-decoration', 'none'); | ||
101 | } | ||
102 | |||
103 | el.mon('click', this.onClick, this, true); | ||
104 | el.mon('dblclick', this.onDblClick, this, true); | ||
105 | el.mon('contextmenu', this.onContextMenu, this, true); | ||
106 | |||
107 | //el.on('focus', function(){ | ||
108 | // this.node.getOwnerTree().getSelectionModel().select(this.node); | ||
109 | //}, this, true); | ||
110 | |||
111 | var icon = YAHOO.ext.Element.fly(this.iconNode); | ||
112 | icon.mon('click', this.onClick, this, true); | ||
113 | icon.mon('dblclick', this.onDblClick, this, true); | ||
114 | icon.mon('contextmenu', this.onContextMenu, this, true); | ||
115 | E.on(this.ecNode, 'click', this.ecClick, this, true); | ||
116 | |||
117 | if(this.node.disabled){ | ||
118 | YAHOO.util.Dom.addClass(this.elNode, 'ytree-node-disabled'); | ||
119 | } | ||
120 | if(this.node.hidden){ | ||
121 | YAHOO.util.Dom.addClass(this.elNode, 'ytree-node-disabled'); | ||
122 | } | ||
123 | var dd = this.node.ownerTree.enableDD || this.node.ownerTree.enableDrag || this.node.ownerTree.enableDrop; | ||
124 | if(dd && (!this.node.isRoot || this.node.ownerTree.rootVisible)){ | ||
125 | YAHOO.ext.dd.Registry.register(this.elNode, { | ||
126 | node: this.node, | ||
127 | handles: [this.iconNode, this.textNode], | ||
128 | isHandle: false | ||
129 | }); | ||
130 | } | ||
131 | }, | ||
132 | |||
133 | hide : function(){ | ||
134 | if(this.rendered){ | ||
135 | this.wrap.style.display = 'none'; | ||
136 | } | ||
137 | }, | ||
138 | |||
139 | show : function(){ | ||
140 | if(this.rendered){ | ||
141 | this.wrap.style.display = ''; | ||
142 | } | ||
143 | }, | ||
144 | |||
145 | onContextMenu : function(e){ | ||
146 | e.preventDefault(); | ||
147 | this.focus(); | ||
148 | this.fireEvent('contextmenu', this.node, e); | ||
149 | }, | ||
150 | |||
151 | onClick : function(e){ | ||
152 | if(this.dropping){ | ||
153 | return; | ||
154 | } | ||
155 | if(this.fireEvent('beforeclick', this.node, e) !== false){ | ||
156 | if(!this.disabled && this.node.attributes.href){ | ||
157 | this.focus(); | ||
158 | this.fireEvent('click', this.node, e); | ||
159 | return; | ||
160 | } | ||
161 | e.preventDefault(); | ||
162 | if(this.disabled){ | ||
163 | return; | ||
164 | } | ||
165 | this.focus(); | ||
166 | this.fireEvent('click', this.node, e); | ||
167 | }else{ | ||
168 | e.stopEvent(); | ||
169 | } | ||
170 | }, | ||
171 | |||
172 | onDblClick : function(e){ | ||
173 | e.preventDefault(); | ||
174 | if(this.disabled){ | ||
175 | return; | ||
176 | } | ||
177 | if(!this.animating && this.node.hasChildNodes()){ | ||
178 | this.node.toggle(); | ||
179 | } | ||
180 | this.fireEvent('dblclick', this.node, e); | ||
181 | }, | ||
182 | |||
183 | ecClick : function(e){ | ||
184 | if(!this.animating && this.node.hasChildNodes()){ | ||
185 | this.node.toggle(); | ||
186 | } | ||
187 | }, | ||
188 | |||
189 | startDrop : function(){ | ||
190 | this.dropping = true; | ||
191 | }, | ||
192 | |||
193 | // delayed drop so the click event doesn't get fired on a drop | ||
194 | endDrop : function(){ | ||
195 | setTimeout(function(){ | ||
196 | this.dropping = false; | ||
197 | }.createDelegate(this), 50); | ||
198 | }, | ||
199 | |||
200 | expand : function(){ | ||
201 | this.updateExpandIcon(); | ||
202 | this.ctNode.style.display = ''; | ||
203 | }, | ||
204 | |||
205 | focus : function(){ | ||
206 | try{ | ||
207 | this.anchor.focus(); | ||
208 | }catch(e){} | ||
209 | }, | ||
210 | |||
211 | blur : function(){ | ||
212 | try{ | ||
213 | this.anchor.blur(); | ||
214 | }catch(e){} | ||
215 | }, | ||
216 | |||
217 | animExpand : function(callback){ | ||
218 | if(this.animating && this.anim){ | ||
219 | this.anim.stop(); | ||
220 | } | ||
221 | this.animating = true; | ||
222 | this.updateExpandIcon(); | ||
223 | var ct = this.ctNode; | ||
224 | var cs = ct.style; | ||
225 | cs.position = 'absolute'; | ||
226 | cs.visibility = 'hidden'; | ||
227 | cs.display = ''; | ||
228 | var h = ct.clientHeight; | ||
229 | cs.overflow = 'hidden'; | ||
230 | cs.height = '1px'; | ||
231 | cs.position = ''; | ||
232 | cs.visibility = ''; | ||
233 | var anim = new YAHOO.util.Anim(ct, { | ||
234 | height: {to: h} | ||
235 | }, this.node.ownerTree.duration || .25, YAHOO.util.Easing.easeOut); | ||
236 | anim.onComplete.subscribe(function(){ | ||
237 | cs.overflow = ''; | ||
238 | cs.height = ''; | ||
239 | this.animating = false; | ||
240 | this.anim = null; | ||
241 | if(typeof callback == 'function'){ | ||
242 | callback(); | ||
243 | } | ||
244 | }, this, true); | ||
245 | this.anim = anim; | ||
246 | anim.animate(); | ||
247 | }, | ||
248 | |||
249 | highlight : function(){ | ||
250 | var tree = this.node.getOwnerTree(); | ||
251 | var hlColor = tree.hlColor || 'C3DAF9'; | ||
252 | var hlBaseColor = tree.hlBaseColor || 'FFFFFF'; | ||
253 | var anim = new YAHOO.util.ColorAnim(this.wrap, { | ||
254 | backgroundColor: {from: hlColor, to: hlBaseColor} | ||
255 | }, .75, YAHOO.util.Easing.easeNone); | ||
256 | anim.onComplete.subscribe(function(){ | ||
257 | YAHOO.util.Dom.setStyle(this.wrap, 'background-color', ''); | ||
258 | }, this, true); | ||
259 | anim.animate(); | ||
260 | }, | ||
261 | |||
262 | collapse : function(){ | ||
263 | this.updateExpandIcon(); | ||
264 | this.ctNode.style.display = 'none'; | ||
265 | }, | ||
266 | |||
267 | animCollapse : function(callback){ | ||
268 | if(this.animating && this.anim){ | ||
269 | this.anim.stop(); | ||
270 | } | ||
271 | this.animating = true; | ||
272 | this.updateExpandIcon(); | ||
273 | var ct = this.ctNode; | ||
274 | var cs = ct.style; | ||
275 | cs.height = ct.offsetHeight +'px'; | ||
276 | cs.overflow = 'hidden'; | ||
277 | var anim = new YAHOO.util.Anim(ct, { | ||
278 | height: {to: 1} | ||
279 | }, this.node.ownerTree.duration || .25, YAHOO.util.Easing.easeOut); | ||
280 | anim.onComplete.subscribe(function(){ | ||
281 | cs.display = 'none'; | ||
282 | cs.overflow = ''; | ||
283 | cs.height = ''; | ||
284 | this.animating = false; | ||
285 | this.anim = null; | ||
286 | if(typeof callback == 'function'){ | ||
287 | callback(); | ||
288 | } | ||
289 | }, this, true); | ||
290 | this.anim = anim; | ||
291 | anim.animate(); | ||
292 | }, | ||
293 | |||
294 | getContainer : function(){ | ||
295 | return this.ctNode; | ||
296 | }, | ||
297 | |||
298 | getEl : function(){ | ||
299 | return this.wrap; | ||
300 | }, | ||
301 | |||
302 | appendDDGhost : function(ghostNode){ | ||
303 | ghostNode.appendChild(this.elNode.cloneNode(true)); | ||
304 | }, | ||
305 | |||
306 | getDDRepairXY : function(){ | ||
307 | return YAHOO.util.Dom.getXY(this.iconNode); | ||
308 | }, | ||
309 | |||
310 | onRender : function(){ | ||
311 | this.render(); | ||
312 | }, | ||
313 | |||
314 | render : function(bulkRender){ | ||
315 | var n = this.node; | ||
316 | var targetNode = n.parentNode ? | ||
317 | n.parentNode.ui.getContainer() : n.ownerTree.container.dom; | ||
318 | if(!this.rendered){ | ||
319 | this.rendered = true; | ||
320 | var a = n.attributes; | ||
321 | |||
322 | // add some indent caching, this helps performance when rendering a large tree | ||
323 | this.indentMarkup = ''; | ||
324 | if(n.parentNode){ | ||
325 | this.indentMarkup = n.parentNode.ui.getChildIndent(); | ||
326 | } | ||
327 | |||
328 | var buf = ['<li class="ytree-node"><div class="ytree-node-el ', n.attributes.cls,'">', | ||
329 | '<span class="ytree-node-indent">',this.indentMarkup,'</span>', | ||
330 | '<img src="', this.emptyIcon, '" class="ytree-ec-icon">', | ||
331 | '<img src="', a.icon || this.emptyIcon, '" class="ytree-node-icon',(a.icon ? ' ytree-node-inline-icon' : ''),'" unselectable="on">', | ||
332 | '<a href="',a.href ? a.href : '#','" tabIndex="1" ', | ||
333 | a.hrefTarget ? ' target="'+a.hrefTarget+'"' : '','><span unselectable="on">',n.text,'</span></a></div>', | ||
334 | '<ul class="ytree-node-ct" style="display:none;"></ul>', | ||
335 | '</li>']; | ||
336 | |||
337 | if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){ | ||
338 | this.wrap = YAHOO.ext.DomHelper.insertHtml('beforeBegin', | ||
339 | n.nextSibling.ui.getEl(), buf.join('')); | ||
340 | }else{ | ||
341 | this.wrap = YAHOO.ext.DomHelper.insertHtml('beforeEnd', targetNode, buf.join('')); | ||
342 | } | ||
343 | this.elNode = this.wrap.childNodes[0]; | ||
344 | this.ctNode = this.wrap.childNodes[1]; | ||
345 | var cs = this.elNode.childNodes; | ||
346 | this.indentNode = cs[0]; | ||
347 | this.ecNode = cs[1]; | ||
348 | this.iconNode = cs[2]; | ||
349 | this.anchor = cs[3]; | ||
350 | this.textNode = cs[3].firstChild; | ||
351 | if(a.qtip){ | ||
352 | if(this.textNode.setAttributeNS){ | ||
353 | this.textNode.setAttributeNS('y', 'qtip', a.qtip); | ||
354 | if(a.qtipTitle){ | ||
355 | this.textNode.setAttributeNS('y', 'qtitle', a.qtipTitle); | ||
356 | } | ||
357 | }else{ | ||
358 | this.textNode.setAttribute('y:qtip', a.qtip); | ||
359 | if(a.qtipTitle){ | ||
360 | this.textNode.setAttribute('y:qtitle', a.qtipTitle); | ||
361 | } | ||
362 | } | ||
363 | } | ||
364 | this.initEvents(); | ||
365 | //this.renderIndent(); cached above now instead call updateExpandIcon | ||
366 | this.updateExpandIcon(); | ||
367 | }else{ | ||
368 | if(bulkRender === true) { | ||
369 | targetNode.appendChild(this.wrap); | ||
370 | } | ||
371 | } | ||
372 | }, | ||
373 | |||
374 | getAnchor : function(){ | ||
375 | return this.anchor; | ||
376 | }, | ||
377 | |||
378 | getTextEl : function(){ | ||
379 | return this.textNode; | ||
380 | }, | ||
381 | |||
382 | getIconEl : function(){ | ||
383 | return this.iconNode; | ||
384 | }, | ||
385 | |||
386 | updateExpandIcon : function(){ | ||
387 | if(this.rendered){ | ||
388 | var n = this.node; | ||
389 | var cls = n.isLast() ? "ytree-elbow-end" : "ytree-elbow"; | ||
390 | var hasChild = n.hasChildNodes(); | ||
391 | if(hasChild){ | ||
392 | cls += n.expanded ? '-minus' : '-plus'; | ||
393 | var c1 = n.expanded ? 'ytree-node-collapsed' : 'ytree-node-expanded'; | ||
394 | var c2 = n.expanded ? 'ytree-node-expanded' : 'ytree-node-collapsed'; | ||
395 | YAHOO.util.Dom.removeClass(this.elNode, 'ytree-node-leaf'); | ||
396 | YAHOO.util.Dom.replaceClass(this.elNode, c1, c2); | ||
397 | }else{ | ||
398 | YAHOO.util.Dom.replaceClass(this.elNode, 'ytree-node-expanded', 'ytree-node-leaf'); | ||
399 | } | ||
400 | this.ecNode.className = 'ytree-ec-icon '+cls; | ||
401 | } | ||
402 | }, | ||
403 | |||
404 | getChildIndent : function(){ | ||
405 | if(!this.childIndent){ | ||
406 | var buf = []; | ||
407 | var p = this.node; | ||
408 | while(p){ | ||
409 | if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){ | ||
410 | if(!p.isLast()) { | ||
411 | buf.unshift('<img src="'+this.emptyIcon+'" class="ytree-elbow-line">'); | ||
412 | } else { | ||
413 | buf.unshift('<img src="'+this.emptyIcon+'" class="ytree-icon">'); | ||
414 | } | ||
415 | } | ||
416 | p = p.parentNode; | ||
417 | } | ||
418 | this.childIndent = buf.join(''); | ||
419 | } | ||
420 | return this.childIndent; | ||
421 | }, | ||
422 | |||
423 | renderIndent : function(){ | ||
424 | if(this.rendered){ | ||
425 | var indent = ''; | ||
426 | var p = this.node.parentNode; | ||
427 | if(p){ | ||
428 | indent = p.ui.getChildIndent(); | ||
429 | } | ||
430 | if(this.indentMarkup != indent){ // don't rerender if not required | ||
431 | this.indentNode.innerHTML = indent; | ||
432 | this.indentMarkup = indent; | ||
433 | } | ||
434 | this.updateExpandIcon(); | ||
435 | } | ||
436 | } | ||
437 | }; | ||
438 | |||
439 | YAHOO.ext.tree.RootTreeNodeUI = function(){ | ||
440 | YAHOO.ext.tree.RootTreeNodeUI.superclass.constructor.apply(this, arguments); | ||
441 | }; | ||
442 | YAHOO.extendX(YAHOO.ext.tree.RootTreeNodeUI, YAHOO.ext.tree.TreeNodeUI); | ||
443 | YAHOO.ext.tree.RootTreeNodeUI.prototype.render = function(){ | ||
444 | if(!this.rendered){ | ||
445 | var targetNode = this.node.ownerTree.container.dom; | ||
446 | this.node.expanded = true; | ||
447 | targetNode.innerHTML = '<div class="ytree-root-node"></div>'; | ||
448 | this.wrap = this.ctNode = targetNode.firstChild; | ||
449 | } | ||
450 | }; | ||
451 | YAHOO.ext.tree.RootTreeNodeUI.prototype.collapse = function(){ | ||
452 | }; | ||
diff --git a/frontend/beta/js/YUI-extensions/tree/TreePanel.js b/frontend/beta/js/YUI-extensions/tree/TreePanel.js new file mode 100644 index 0000000..202c0d0 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/tree/TreePanel.js | |||
@@ -0,0 +1,213 @@ | |||
1 | YAHOO.namespace('ext.tree'); | ||
2 | |||
3 | YAHOO.ext.tree.TreePanel = function(el, config){ | ||
4 | YAHOO.ext.tree.TreePanel.superclass.constructor.call(this); | ||
5 | this.el = getEl(el); | ||
6 | this.id = this.el.id; | ||
7 | YAHOO.ext.util.Config.apply(this, config || {}, { | ||
8 | rootVisible : true, | ||
9 | lines : true, | ||
10 | enableDD : false, | ||
11 | hlDrop : true/*, | ||
12 | hlColor: null, | ||
13 | ddGroup : 'TreeDD' | ||
14 | hlBaseColor : 'FFFFFF'*/ | ||
15 | |||
16 | }); | ||
17 | YAHOO.ext.util.Config.apply(this.events, { | ||
18 | 'beforeload' : true, | ||
19 | 'load' : true, | ||
20 | 'textchange' : true, | ||
21 | 'beforeexpand' : true, | ||
22 | 'beforecollapse' : true, | ||
23 | 'expand' : true, | ||
24 | 'collapse' : true, | ||
25 | 'disabledchange' : true, | ||
26 | 'beforeclick':true, | ||
27 | 'click':true, | ||
28 | 'dblclick':true, | ||
29 | 'contentmenu':true, | ||
30 | 'beforechildrenrendered':true, | ||
31 | /** | ||
32 | * @event startdrag | ||
33 | * Fires when a node starts being dragged | ||
34 | * @param {YAHOO.ext.tree.TreePanel} this | ||
35 | * @param {YAHOO.ext.tree.TreeNode} node | ||
36 | * @param {event} e The raw browser event | ||
37 | */ | ||
38 | 'startdrag' : true, | ||
39 | /** | ||
40 | * @event enddrag | ||
41 | * Fires when a drag operation is complete | ||
42 | * @param {YAHOO.ext.tree.TreePanel} this | ||
43 | * @param {YAHOO.ext.tree.TreeNode} node | ||
44 | * @param {event} e The raw browser event | ||
45 | */ | ||
46 | 'enddrag' : true, | ||
47 | /** | ||
48 | * @event dragdrop | ||
49 | * Fires when a dragged node is dropped on a valid DD target | ||
50 | * @param {YAHOO.ext.tree.TreePanel} this | ||
51 | * @param {YAHOO.ext.tree.TreeNode} node | ||
52 | * @param {DD} dd The dd it was dropped on | ||
53 | * @param {event} e The raw browser event | ||
54 | */ | ||
55 | 'dragdrop' : true, | ||
56 | /** | ||
57 | * @event beforenodedrop | ||
58 | * Fires when a DD object is dropped on a node in this tree for preprocessing. This event can cancel. | ||
59 | * @param {Object} dropEvent | ||
60 | */ | ||
61 | 'beforenodedrop' : true, | ||
62 | /** | ||
63 | * @event nodedrop | ||
64 | * Fires after a DD object is dropped on a node in this tree | ||
65 | * @param {Object} dropEvent | ||
66 | */ | ||
67 | 'nodedrop' : true, | ||
68 | /** | ||
69 | * @event nodedragover | ||
70 | * Fires when a tree node is being target | ||
71 | * @param {Object} dragOverEvent | ||
72 | */ | ||
73 | 'nodedragover' : true | ||
74 | }); | ||
75 | if(this.singleExpand){ | ||
76 | this.on('beforeexpand', this.restrictExpand, this, true); | ||
77 | } | ||
78 | // problem with safari and animation | ||
79 | // I am investigating | ||
80 | if(YAHOO.ext.util.Browser.isSafari){ | ||
81 | this.animate = false; | ||
82 | } | ||
83 | }; | ||
84 | YAHOO.extendX(YAHOO.ext.tree.TreePanel, YAHOO.ext.data.Tree, { | ||
85 | restrictExpand : function(node){ | ||
86 | var p = node.parentNode; | ||
87 | if(p){ | ||
88 | if(p.expandedChild && p.expandedChild.parentNode == p){ | ||
89 | p.expandedChild.collapse(); | ||
90 | } | ||
91 | p.expandedChild = node; | ||
92 | } | ||
93 | }, | ||
94 | |||
95 | setRootNode : function(node){ | ||
96 | YAHOO.ext.tree.TreePanel.superclass.setRootNode.call(this, node); | ||
97 | if(!this.rootVisible){ | ||
98 | node.ui = new YAHOO.ext.tree.RootTreeNodeUI(node); | ||
99 | } | ||
100 | return node; | ||
101 | }, | ||
102 | |||
103 | getEl : function(){ | ||
104 | return this.el; | ||
105 | }, | ||
106 | |||
107 | getLoader : function(){ | ||
108 | return this.loader; | ||
109 | }, | ||
110 | |||
111 | expandAll : function(){ | ||
112 | this.root.expand(true); | ||
113 | }, | ||
114 | |||
115 | collapseAll : function(){ | ||
116 | this.root.collapse(true); | ||
117 | }, | ||
118 | |||
119 | getSelectionModel : function(){ | ||
120 | if(!this.selModel){ | ||
121 | this.selModel = new YAHOO.ext.tree.DefaultSelectionModel(); | ||
122 | } | ||
123 | return this.selModel; | ||
124 | }, | ||
125 | |||
126 | expandPath : function(path, attr, callback){ | ||
127 | attr = attr || 'id'; | ||
128 | var keys = path.split(this.pathSeparator); | ||
129 | var curNode = this.root; | ||
130 | if(curNode.attributes[attr] != keys[1]){ // invalid root | ||
131 | if(callback){ | ||
132 | callback(false, null); | ||
133 | } | ||
134 | return; | ||
135 | } | ||
136 | var index = 1; | ||
137 | var f = function(){ | ||
138 | if(++index == keys.length){ | ||
139 | if(callback){ | ||
140 | callback(true, curNode); | ||
141 | } | ||
142 | return; | ||
143 | } | ||
144 | var c = curNode.findChild(attr, keys[index]); | ||
145 | if(!c){ | ||
146 | if(callback){ | ||
147 | callback(false, curNode); | ||
148 | } | ||
149 | return; | ||
150 | } | ||
151 | curNode = c; | ||
152 | c.expand(false, false, f); | ||
153 | } | ||
154 | curNode.expand(false, false, f); | ||
155 | }, | ||
156 | |||
157 | selectPath : function(path, attr, callback){ | ||
158 | attr = attr || 'id'; | ||
159 | var keys = path.split(this.pathSeparator); | ||
160 | var v = keys.pop(); | ||
161 | if(keys.length > 0){ | ||
162 | var f = function(success, node){ | ||
163 | if(success && node){ | ||
164 | var n = node.findChild(attr, v); | ||
165 | if(n){ | ||
166 | n.select(); | ||
167 | if(callback){ | ||
168 | callback(true, n); | ||
169 | } | ||
170 | } | ||
171 | }else{ | ||
172 | if(callback){ | ||
173 | callback(false, n); | ||
174 | } | ||
175 | } | ||
176 | }; | ||
177 | this.expandPath(keys.join(this.pathSeparator), attr, f); | ||
178 | }else{ | ||
179 | this.root.select(); | ||
180 | if(callback){ | ||
181 | callback(true, this.root); | ||
182 | } | ||
183 | } | ||
184 | }, | ||
185 | |||
186 | render : function(){ | ||
187 | this.container = this.el.createChild({tag:'ul', | ||
188 | cls:'ytree-root-ct ' + | ||
189 | (this.lines ? 'ytree-lines' : 'ytree-no-lines')}); | ||
190 | |||
191 | if(this.containerScroll){ | ||
192 | YAHOO.ext.dd.ScrollManager.register(this.el); | ||
193 | } | ||
194 | |||
195 | if((this.enableDD || this.enableDrop) && !this.dropZone){ | ||
196 | this.dropZone = new YAHOO.ext.tree.TreeDropZone(this, this.dropConfig || { | ||
197 | ddGroup: this.ddGroup || 'TreeDD' | ||
198 | }); | ||
199 | } | ||
200 | if((this.enableDD || this.enableDrag) && !this.dragZone){ | ||
201 | this.dragZone = new YAHOO.ext.tree.TreeDragZone(this, this.dragConfig || { | ||
202 | ddGroup: this.ddGroup || 'TreeDD', | ||
203 | scroll: this.ddScroll | ||
204 | }); | ||
205 | } | ||
206 | this.getSelectionModel().init(this); | ||
207 | this.root.render(); | ||
208 | if(!this.rootVisible){ | ||
209 | this.root.renderChildren(); | ||
210 | } | ||
211 | return this; | ||
212 | } | ||
213 | }); | ||
diff --git a/frontend/beta/js/YUI-extensions/tree/TreeSelectionModel.js b/frontend/beta/js/YUI-extensions/tree/TreeSelectionModel.js new file mode 100644 index 0000000..4fed88e --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/tree/TreeSelectionModel.js | |||
@@ -0,0 +1,195 @@ | |||
1 | YAHOO.ext.tree.DefaultSelectionModel = function(){ | ||
2 | this.selNode = null; | ||
3 | |||
4 | this.events = { | ||
5 | 'selectionchange' : true | ||
6 | }; | ||
7 | }; | ||
8 | |||
9 | YAHOO.extendX(YAHOO.ext.tree.DefaultSelectionModel, YAHOO.ext.util.Observable, { | ||
10 | init : function(tree){ | ||
11 | this.tree = tree; | ||
12 | tree.el.mon('keydown', this.onKeyDown, this, true); | ||
13 | tree.on('click', this.onNodeClick, this, true); | ||
14 | }, | ||
15 | |||
16 | onNodeClick : function(node, e){ | ||
17 | this.select(node); | ||
18 | }, | ||
19 | |||
20 | select : function(node){ | ||
21 | if(this.selNode && this.selNode != node){ | ||
22 | this.selNode.ui.onSelectedChange(false); | ||
23 | } | ||
24 | this.selNode = node; | ||
25 | node.ui.onSelectedChange(true); | ||
26 | this.fireEvent('selectionchange', this, node); | ||
27 | return node; | ||
28 | }, | ||
29 | |||
30 | unselect : function(node){ | ||
31 | if(this.selNode == node){ | ||
32 | this.clearSelections(); | ||
33 | } | ||
34 | }, | ||
35 | |||
36 | clearSelections : function(){ | ||
37 | var n = this.selNode; | ||
38 | if(n){ | ||
39 | n.ui.onSelectedChange(false); | ||
40 | this.selNode = null; | ||
41 | this.fireEvent('selectionchange', this, null); | ||
42 | } | ||
43 | return n; | ||
44 | }, | ||
45 | |||
46 | getSelectedNode : function(){ | ||
47 | return this.selNode; | ||
48 | }, | ||
49 | |||
50 | isSelected : function(node){ | ||
51 | return this.selNode == node; | ||
52 | }, | ||
53 | |||
54 | onKeyDown : function(e){ | ||
55 | var s = this.selNode || this.lastSelNode; | ||
56 | // undesirable, but required | ||
57 | var sm = this; | ||
58 | if(!s){ | ||
59 | return; | ||
60 | } | ||
61 | var k = e.getKey(); | ||
62 | //alert(k) | ||
63 | switch(k){ | ||
64 | case e.DOWN: | ||
65 | e.preventDefault(); | ||
66 | if(s.firstChild && s.isExpanded()){ | ||
67 | this.select(s.firstChild, e); | ||
68 | }else if(s.nextSibling){ | ||
69 | this.select(s.nextSibling, e); | ||
70 | }else if(s.parentNode){ | ||
71 | s.parentNode.bubble(function(){ | ||
72 | if(this.nextSibling){ | ||
73 | sm.select(this.nextSibling, e); | ||
74 | return false; | ||
75 | } | ||
76 | }); | ||
77 | } | ||
78 | break; | ||
79 | case e.UP: | ||
80 | e.preventDefault(); | ||
81 | var ps = s.previousSibling; | ||
82 | if(ps){ | ||
83 | if(!ps.isExpanded()){ | ||
84 | this.select(ps, e); | ||
85 | }else{ | ||
86 | var lc = ps.lastChild; | ||
87 | while(lc && lc.isExpanded()){ | ||
88 | lc = lc.lastChild; | ||
89 | } | ||
90 | this.select(lc, e); | ||
91 | } | ||
92 | }else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){ | ||
93 | this.select(s.parentNode, e); | ||
94 | } | ||
95 | break; | ||
96 | case e.RIGHT: | ||
97 | e.preventDefault(); | ||
98 | if(s.hasChildNodes()){ | ||
99 | if(!s.isExpanded()){ | ||
100 | s.expand(); | ||
101 | }else if(s.firstChild){ | ||
102 | this.select(s.firstChild, e); | ||
103 | } | ||
104 | } | ||
105 | break; | ||
106 | case e.LEFT: | ||
107 | e.preventDefault(); | ||
108 | if(s.hasChildNodes() && s.isExpanded()){ | ||
109 | s.collapse(); | ||
110 | }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){ | ||
111 | this.select(s.parentNode, e); | ||
112 | } | ||
113 | break; | ||
114 | }; | ||
115 | } | ||
116 | }); | ||
117 | |||
118 | YAHOO.ext.tree.MultiSelectionModel = function(){ | ||
119 | this.selNodes = []; | ||
120 | this.selMap = {}; | ||
121 | this.events = { | ||
122 | 'selectionchange' : true | ||
123 | }; | ||
124 | }; | ||
125 | |||
126 | YAHOO.extendX(YAHOO.ext.tree.MultiSelectionModel, YAHOO.ext.util.Observable, { | ||
127 | init : function(tree){ | ||
128 | this.tree = tree; | ||
129 | tree.el.mon('keydown', this.onKeyDown, this, true); | ||
130 | tree.on('click', this.onNodeClick, this, true); | ||
131 | }, | ||
132 | |||
133 | onNodeClick : function(node, e){ | ||
134 | this.select(node, e, e.ctrlKey); | ||
135 | }, | ||
136 | |||
137 | select : function(node, e, keepExisting){ | ||
138 | if(keepExisting !== true){ | ||
139 | this.clearSelections(true); | ||
140 | } | ||
141 | this.selNodes.push(node); | ||
142 | this.selMap[node.id] = node; | ||
143 | this.lastSelNode = node; | ||
144 | node.ui.onSelectedChange(true); | ||
145 | this.fireEvent('selectionchange', this, this.selNodes); | ||
146 | return node; | ||
147 | }, | ||
148 | |||
149 | unselect : function(node){ | ||
150 | if(this.selMap[node.id]){ | ||
151 | node.ui.onSelectedChange(false); | ||
152 | var sn = this.selNodes; | ||
153 | var index = -1; | ||
154 | if(sn.indexOf){ | ||
155 | index = sn.indexOf(node); | ||
156 | }else{ | ||
157 | for(var i = 0, len = sn.length; i < len; i++){ | ||
158 | if(sn[i] == node){ | ||
159 | index = i; | ||
160 | break; | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | if(index != -1){ | ||
165 | this.selNodes.splice(index, 1); | ||
166 | } | ||
167 | delete this.selMap[node.id]; | ||
168 | this.fireEvent('selectionchange', this, this.selNodes); | ||
169 | } | ||
170 | }, | ||
171 | |||
172 | clearSelections : function(suppressEvent){ | ||
173 | var sn = this.selNodes; | ||
174 | if(sn.length > 0){ | ||
175 | for(var i = 0, len = sn.length; i < len; i++){ | ||
176 | sn[i].ui.onSelectedChange(false); | ||
177 | } | ||
178 | this.selNodes = []; | ||
179 | this.selMap = {}; | ||
180 | if(suppressEvent !== true){ | ||
181 | this.fireEvent('selectionchange', this, this.selNodes); | ||
182 | } | ||
183 | } | ||
184 | }, | ||
185 | |||
186 | isSelected : function(node){ | ||
187 | return this.selMap[node.id] ? true : false; | ||
188 | }, | ||
189 | |||
190 | getSelectedNodes : function(){ | ||
191 | return this.selNodes; | ||
192 | }, | ||
193 | |||
194 | onKeyDown : YAHOO.ext.tree.DefaultSelectionModel.prototype.onKeyDown | ||
195 | }); | ||
diff --git a/frontend/beta/js/YUI-extensions/tree/TreeSorter.js b/frontend/beta/js/YUI-extensions/tree/TreeSorter.js new file mode 100644 index 0000000..9960703 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/tree/TreeSorter.js | |||
@@ -0,0 +1,49 @@ | |||
1 | YAHOO.ext.tree.TreeSorter = function(tree, config){ | ||
2 | YAHOO.ext.util.Config.apply(this, config); | ||
3 | tree.on('beforechildrenrendered', this.doSort, this, true); | ||
4 | tree.on('append', this.updateSort, this, true); | ||
5 | tree.on('insert', this.updateSort, this, true); | ||
6 | |||
7 | var dsc = this.dir && this.dir.toLowerCase() == 'desc'; | ||
8 | var p = this.property || 'text'; | ||
9 | var sortType = this.sortType; | ||
10 | var fs = this.folderSort; | ||
11 | var cs = this.caseSensitive === true; | ||
12 | |||
13 | this.sortFn = function(n1, n2){ | ||
14 | if(fs){ | ||
15 | if(n1.leaf && !n2.leaf){ | ||
16 | return 1; | ||
17 | } | ||
18 | if(!n1.leaf && n2.leaf){ | ||
19 | return -1; | ||
20 | } | ||
21 | } | ||
22 | var v1 = sortType ? sortType(n1) : (cs ? n1[p] : n1[p].toUpperCase()); | ||
23 | var v2 = sortType ? sortType(n2) : (cs ? n2[p] : n2[p].toUpperCase()); | ||
24 | if(v1 < v2){ | ||
25 | return dsc ? +1 : -1; | ||
26 | }else if(v1 > v2){ | ||
27 | return dsc ? -1 : +1; | ||
28 | }else{ | ||
29 | return 0; | ||
30 | } | ||
31 | }; | ||
32 | }; | ||
33 | |||
34 | YAHOO.ext.tree.TreeSorter.prototype = { | ||
35 | doSort : function(node){ | ||
36 | node.sort(this.sortFn); | ||
37 | }, | ||
38 | |||
39 | compareNodes : function(n1, n2){ | ||
40 | |||
41 | return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1); | ||
42 | }, | ||
43 | |||
44 | updateSort : function(tree, node){ | ||
45 | if(node.childrenRendered){ | ||
46 | this.doSort.defer(1, this, [node]); | ||
47 | } | ||
48 | } | ||
49 | }; | ||