nexus site path corrected
[portal.git] / ecomp-portal-FE / client / bower_components / jqTree / lib / node.js
1 var $, Node, Position;
2
3 $ = jQuery;
4
5 Position = {
6   getName: function(position) {
7     return Position.strings[position - 1];
8   },
9   nameToIndex: function(name) {
10     var i, j, ref;
11     for (i = j = 1, ref = Position.strings.length; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) {
12       if (Position.strings[i - 1] === name) {
13         return i;
14       }
15     }
16     return 0;
17   }
18 };
19
20 Position.BEFORE = 1;
21
22 Position.AFTER = 2;
23
24 Position.INSIDE = 3;
25
26 Position.NONE = 4;
27
28 Position.strings = ['before', 'after', 'inside', 'none'];
29
30 Node = (function() {
31   function Node(o, is_root, node_class) {
32     if (is_root == null) {
33       is_root = false;
34     }
35     if (node_class == null) {
36       node_class = Node;
37     }
38     this.name = '';
39     this.setData(o);
40     this.children = [];
41     this.parent = null;
42     if (is_root) {
43       this.id_mapping = {};
44       this.tree = this;
45       this.node_class = node_class;
46     }
47   }
48
49   Node.prototype.setData = function(o) {
50
51     /*
52     Set the data of this node.
53     
54     setData(string): set the name of the node
55     setdata(object): set attributes of the node
56     
57     Examples:
58         setdata('node1')
59     
60         setData({ name: 'node1', id: 1});
61     
62         setData({ name: 'node2', id: 2, color: 'green'});
63     
64     * This is an internal function; it is not in the docs
65     * Does not remove existing node values
66      */
67     var key, setName, value;
68     setName = (function(_this) {
69       return function(name) {
70         if (name !== null) {
71           return _this.name = name;
72         }
73       };
74     })(this);
75     if (typeof o !== 'object') {
76       setName(o);
77     } else {
78       for (key in o) {
79         value = o[key];
80         if (key === 'label') {
81           setName(value);
82         } else if (key !== 'children') {
83           this[key] = value;
84         }
85       }
86     }
87     return null;
88   };
89
90   Node.prototype.initFromData = function(data) {
91     var addChildren, addNode;
92     addNode = (function(_this) {
93       return function(node_data) {
94         _this.setData(node_data);
95         if (node_data.children) {
96           return addChildren(node_data.children);
97         }
98       };
99     })(this);
100     addChildren = (function(_this) {
101       return function(children_data) {
102         var child, j, len, node;
103         for (j = 0, len = children_data.length; j < len; j++) {
104           child = children_data[j];
105           node = new _this.tree.node_class('');
106           node.initFromData(child);
107           _this.addChild(node);
108         }
109         return null;
110       };
111     })(this);
112     addNode(data);
113     return null;
114   };
115
116
117   /*
118   Create tree from data.
119   
120   Structure of data is:
121   [
122       {
123           label: 'node1',
124           children: [
125               { label: 'child1' },
126               { label: 'child2' }
127           ]
128       },
129       {
130           label: 'node2'
131       }
132   ]
133    */
134
135   Node.prototype.loadFromData = function(data) {
136     var j, len, node, o;
137     this.removeChildren();
138     for (j = 0, len = data.length; j < len; j++) {
139       o = data[j];
140       node = new this.tree.node_class(o);
141       this.addChild(node);
142       if (typeof o === 'object' && o.children) {
143         node.loadFromData(o.children);
144       }
145     }
146     return null;
147   };
148
149
150   /*
151   Add child.
152   
153   tree.addChild(
154       new Node('child1')
155   );
156    */
157
158   Node.prototype.addChild = function(node) {
159     this.children.push(node);
160     return node._setParent(this);
161   };
162
163
164   /*
165   Add child at position. Index starts at 0.
166   
167   tree.addChildAtPosition(
168       new Node('abc'),
169       1
170   );
171    */
172
173   Node.prototype.addChildAtPosition = function(node, index) {
174     this.children.splice(index, 0, node);
175     return node._setParent(this);
176   };
177
178   Node.prototype._setParent = function(parent) {
179     this.parent = parent;
180     this.tree = parent.tree;
181     return this.tree.addNodeToIndex(this);
182   };
183
184
185   /*
186   Remove child. This also removes the children of the node.
187   
188   tree.removeChild(tree.children[0]);
189    */
190
191   Node.prototype.removeChild = function(node) {
192     node.removeChildren();
193     return this._removeChild(node);
194   };
195
196   Node.prototype._removeChild = function(node) {
197     this.children.splice(this.getChildIndex(node), 1);
198     return this.tree.removeNodeFromIndex(node);
199   };
200
201
202   /*
203   Get child index.
204   
205   var index = getChildIndex(node);
206    */
207
208   Node.prototype.getChildIndex = function(node) {
209     return $.inArray(node, this.children);
210   };
211
212
213   /*
214   Does the tree have children?
215   
216   if (tree.hasChildren()) {
217       //
218   }
219    */
220
221   Node.prototype.hasChildren = function() {
222     return this.children.length !== 0;
223   };
224
225   Node.prototype.isFolder = function() {
226     return this.hasChildren() || this.load_on_demand;
227   };
228
229
230   /*
231   Iterate over all the nodes in the tree.
232   
233   Calls callback with (node, level).
234   
235   The callback must return true to continue the iteration on current node.
236   
237   tree.iterate(
238       function(node, level) {
239          console.log(node.name);
240   
241          // stop iteration after level 2
242          return (level <= 2);
243       }
244   );
245    */
246
247   Node.prototype.iterate = function(callback) {
248     var _iterate;
249     _iterate = function(node, level) {
250       var child, j, len, ref, result;
251       if (node.children) {
252         ref = node.children;
253         for (j = 0, len = ref.length; j < len; j++) {
254           child = ref[j];
255           result = callback(child, level);
256           if (result && child.hasChildren()) {
257             _iterate(child, level + 1);
258           }
259         }
260         return null;
261       }
262     };
263     _iterate(this, 0);
264     return null;
265   };
266
267
268   /*
269   Move node relative to another node.
270   
271   Argument position: Position.BEFORE, Position.AFTER or Position.Inside
272   
273   // move node1 after node2
274   tree.moveNode(node1, node2, Position.AFTER);
275    */
276
277   Node.prototype.moveNode = function(moved_node, target_node, position) {
278     if (moved_node.isParentOf(target_node)) {
279       return;
280     }
281     moved_node.parent._removeChild(moved_node);
282     if (position === Position.AFTER) {
283       return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node) + 1);
284     } else if (position === Position.BEFORE) {
285       return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node));
286     } else if (position === Position.INSIDE) {
287       return target_node.addChildAtPosition(moved_node, 0);
288     }
289   };
290
291
292   /*
293   Get the tree as data.
294    */
295
296   Node.prototype.getData = function(include_parent) {
297     var getDataFromNodes;
298     if (include_parent == null) {
299       include_parent = false;
300     }
301     getDataFromNodes = function(nodes) {
302       var data, j, k, len, node, tmp_node, v;
303       data = [];
304       for (j = 0, len = nodes.length; j < len; j++) {
305         node = nodes[j];
306         tmp_node = {};
307         for (k in node) {
308           v = node[k];
309           if ((k !== 'parent' && k !== 'children' && k !== 'element' && k !== 'tree') && Object.prototype.hasOwnProperty.call(node, k)) {
310             tmp_node[k] = v;
311           }
312         }
313         if (node.hasChildren()) {
314           tmp_node.children = getDataFromNodes(node.children);
315         }
316         data.push(tmp_node);
317       }
318       return data;
319     };
320     if (include_parent) {
321       return getDataFromNodes([this]);
322     } else {
323       return getDataFromNodes(this.children);
324     }
325   };
326
327   Node.prototype.getNodeByName = function(name) {
328     return this.getNodeByCallback(function(node) {
329       return node.name === name;
330     });
331   };
332
333   Node.prototype.getNodeByCallback = function(callback) {
334     var result;
335     result = null;
336     this.iterate(function(node) {
337       if (callback(node)) {
338         result = node;
339         return false;
340       } else {
341         return true;
342       }
343     });
344     return result;
345   };
346
347   Node.prototype.addAfter = function(node_info) {
348     var child_index, node;
349     if (!this.parent) {
350       return null;
351     } else {
352       node = new this.tree.node_class(node_info);
353       child_index = this.parent.getChildIndex(this);
354       this.parent.addChildAtPosition(node, child_index + 1);
355       if (typeof node_info === 'object' && node_info.children && node_info.children.length) {
356         node.loadFromData(node_info.children);
357       }
358       return node;
359     }
360   };
361
362   Node.prototype.addBefore = function(node_info) {
363     var child_index, node;
364     if (!this.parent) {
365       return null;
366     } else {
367       node = new this.tree.node_class(node_info);
368       child_index = this.parent.getChildIndex(this);
369       this.parent.addChildAtPosition(node, child_index);
370       if (typeof node_info === 'object' && node_info.children && node_info.children.length) {
371         node.loadFromData(node_info.children);
372       }
373       return node;
374     }
375   };
376
377   Node.prototype.addParent = function(node_info) {
378     var child, j, len, new_parent, original_parent, ref;
379     if (!this.parent) {
380       return null;
381     } else {
382       new_parent = new this.tree.node_class(node_info);
383       new_parent._setParent(this.tree);
384       original_parent = this.parent;
385       ref = original_parent.children;
386       for (j = 0, len = ref.length; j < len; j++) {
387         child = ref[j];
388         new_parent.addChild(child);
389       }
390       original_parent.children = [];
391       original_parent.addChild(new_parent);
392       return new_parent;
393     }
394   };
395
396   Node.prototype.remove = function() {
397     if (this.parent) {
398       this.parent.removeChild(this);
399       return this.parent = null;
400     }
401   };
402
403   Node.prototype.append = function(node_info) {
404     var node;
405     node = new this.tree.node_class(node_info);
406     this.addChild(node);
407     if (typeof node_info === 'object' && node_info.children && node_info.children.length) {
408       node.loadFromData(node_info.children);
409     }
410     return node;
411   };
412
413   Node.prototype.prepend = function(node_info) {
414     var node;
415     node = new this.tree.node_class(node_info);
416     this.addChildAtPosition(node, 0);
417     if (typeof node_info === 'object' && node_info.children && node_info.children.length) {
418       node.loadFromData(node_info.children);
419     }
420     return node;
421   };
422
423   Node.prototype.isParentOf = function(node) {
424     var parent;
425     parent = node.parent;
426     while (parent) {
427       if (parent === this) {
428         return true;
429       }
430       parent = parent.parent;
431     }
432     return false;
433   };
434
435   Node.prototype.getLevel = function() {
436     var level, node;
437     level = 0;
438     node = this;
439     while (node.parent) {
440       level += 1;
441       node = node.parent;
442     }
443     return level;
444   };
445
446   Node.prototype.getNodeById = function(node_id) {
447     return this.id_mapping[node_id];
448   };
449
450   Node.prototype.addNodeToIndex = function(node) {
451     if (node.id != null) {
452       return this.id_mapping[node.id] = node;
453     }
454   };
455
456   Node.prototype.removeNodeFromIndex = function(node) {
457     if (node.id != null) {
458       return delete this.id_mapping[node.id];
459     }
460   };
461
462   Node.prototype.removeChildren = function() {
463     this.iterate((function(_this) {
464       return function(child) {
465         _this.tree.removeNodeFromIndex(child);
466         return true;
467       };
468     })(this));
469     return this.children = [];
470   };
471
472   Node.prototype.getPreviousSibling = function() {
473     var previous_index;
474     if (!this.parent) {
475       return null;
476     } else {
477       previous_index = this.parent.getChildIndex(this) - 1;
478       if (previous_index >= 0) {
479         return this.parent.children[previous_index];
480       } else {
481         return null;
482       }
483     }
484   };
485
486   Node.prototype.getNextSibling = function() {
487     var next_index;
488     if (!this.parent) {
489       return null;
490     } else {
491       next_index = this.parent.getChildIndex(this) + 1;
492       if (next_index < this.parent.children.length) {
493         return this.parent.children[next_index];
494       } else {
495         return null;
496       }
497     }
498   };
499
500   Node.prototype.getNodesByProperty = function(key, value) {
501     return this.filter(function(node) {
502       return node[key] === value;
503     });
504   };
505
506   Node.prototype.filter = function(f) {
507     var result;
508     result = [];
509     this.iterate(function(node) {
510       if (f(node)) {
511         result.push(node);
512       }
513       return true;
514     });
515     return result;
516   };
517
518   Node.prototype.getNextNode = function(include_children) {
519     var next_sibling;
520     if (include_children == null) {
521       include_children = true;
522     }
523     if (include_children && this.hasChildren() && this.is_open) {
524       return this.children[0];
525     } else {
526       if (!this.parent) {
527         return null;
528       } else {
529         next_sibling = this.getNextSibling();
530         if (next_sibling) {
531           return next_sibling;
532         } else {
533           return this.parent.getNextNode(false);
534         }
535       }
536     }
537   };
538
539   Node.prototype.getPreviousNode = function() {
540     var previous_sibling;
541     if (!this.parent) {
542       return null;
543     } else {
544       previous_sibling = this.getPreviousSibling();
545       if (previous_sibling) {
546         if (!previous_sibling.hasChildren() || !previous_sibling.is_open) {
547           return previous_sibling;
548         } else {
549           return previous_sibling.getLastChild();
550         }
551       } else {
552         return this.getParent();
553       }
554     }
555   };
556
557   Node.prototype.getParent = function() {
558     if (!this.parent) {
559       return null;
560     } else if (!this.parent.parent) {
561       return null;
562     } else {
563       return this.parent;
564     }
565   };
566
567   Node.prototype.getLastChild = function() {
568     var last_child;
569     if (!this.hasChildren()) {
570       return null;
571     } else {
572       last_child = this.children[this.children.length - 1];
573       if (!last_child.hasChildren() || !last_child.is_open) {
574         return last_child;
575       } else {
576         return last_child.getLastChild();
577       }
578     }
579   };
580
581   return Node;
582
583 })();
584
585 module.exports = {
586   Node: Node,
587   Position: Position
588 };