0
|
1 // Generated by CoffeeScript 1.3.3
|
|
2
|
|
3 /*
|
|
4 Copyright 2012 Marco Braak
|
|
5
|
|
6 Licensed under the Apache License, Version 2.0 (the "License");
|
|
7 you may not use this file except in compliance with the License.
|
|
8 You may obtain a copy of the License at
|
|
9
|
|
10 http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
|
12 Unless required by applicable law or agreed to in writing, software
|
|
13 distributed under the License is distributed on an "AS IS" BASIS,
|
|
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15 See the License for the specific language governing permissions and
|
|
16 limitations under the License.
|
|
17 */
|
|
18
|
|
19
|
|
20 (function() {
|
|
21 var $, BorderDropHint, DragAndDropHandler, DragElement, FolderElement, GhostDropHint, JqTreeWidget, Json, MouseWidget, Node, NodeElement, Position, SaveStateHandler, SelectNodeHandler, SimpleWidget, Tree, html_escape, indexOf, toJson,
|
|
22 __slice = [].slice,
|
|
23 __hasProp = {}.hasOwnProperty,
|
|
24 __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
25
|
|
26 $ = this.jQuery;
|
|
27
|
|
28 SimpleWidget = (function() {
|
|
29
|
|
30 SimpleWidget.prototype.defaults = {};
|
|
31
|
|
32 function SimpleWidget(el, options) {
|
|
33 this.$el = $(el);
|
|
34 this.options = $.extend({}, this.defaults, options);
|
|
35 this._init();
|
|
36 }
|
|
37
|
|
38 SimpleWidget.prototype.destroy = function() {
|
|
39 return this._deinit();
|
|
40 };
|
|
41
|
|
42 SimpleWidget.prototype._init = function() {
|
|
43 return null;
|
|
44 };
|
|
45
|
|
46 SimpleWidget.prototype._deinit = function() {
|
|
47 return null;
|
|
48 };
|
|
49
|
|
50 SimpleWidget.register = function(widget_class, widget_name) {
|
|
51 var callFunction, createWidget, destroyWidget, getDataKey;
|
|
52 getDataKey = function() {
|
|
53 return "simple_widget_" + widget_name;
|
|
54 };
|
|
55 createWidget = function($el, options) {
|
|
56 var data_key;
|
|
57 data_key = getDataKey();
|
|
58 $el.each(function() {
|
|
59 var widget;
|
|
60 widget = new widget_class(this, options);
|
|
61 if (!$.data(this, data_key)) {
|
|
62 return $.data(this, data_key, widget);
|
|
63 }
|
|
64 });
|
|
65 return $el;
|
|
66 };
|
|
67 destroyWidget = function($el) {
|
|
68 var data_key;
|
|
69 data_key = getDataKey();
|
|
70 return $el.each(function() {
|
|
71 var widget;
|
|
72 widget = $.data(this, data_key);
|
|
73 if (widget && (widget instanceof SimpleWidget)) {
|
|
74 widget.destroy();
|
|
75 }
|
|
76 return $.removeData(this, data_key);
|
|
77 });
|
|
78 };
|
|
79 callFunction = function($el, function_name, args) {
|
|
80 var result;
|
|
81 result = null;
|
|
82 $el.each(function() {
|
|
83 var widget, widget_function;
|
|
84 widget = $.data(this, getDataKey());
|
|
85 if (widget && (widget instanceof SimpleWidget)) {
|
|
86 widget_function = widget[function_name];
|
|
87 if (widget_function && (typeof widget_function === 'function')) {
|
|
88 return result = widget_function.apply(widget, args);
|
|
89 }
|
|
90 }
|
|
91 });
|
|
92 return result;
|
|
93 };
|
|
94 return $.fn[widget_name] = function() {
|
|
95 var $el, args, argument1, function_name, options;
|
|
96 argument1 = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
|
97 $el = this;
|
|
98 if (argument1 === void 0 || typeof argument1 === 'object') {
|
|
99 options = argument1;
|
|
100 return createWidget($el, options);
|
|
101 } else if (typeof argument1 === 'string' && argument1[0] !== '_') {
|
|
102 function_name = argument1;
|
|
103 if (function_name === 'destroy') {
|
|
104 return destroyWidget($el);
|
|
105 } else {
|
|
106 return callFunction($el, function_name, args);
|
|
107 }
|
|
108 }
|
|
109 };
|
|
110 };
|
|
111
|
|
112 return SimpleWidget;
|
|
113
|
|
114 })();
|
|
115
|
|
116 this.SimpleWidget = SimpleWidget;
|
|
117
|
|
118 /*
|
|
119 This widget does the same a the mouse widget in jqueryui.
|
|
120 */
|
|
121
|
|
122
|
|
123 MouseWidget = (function(_super) {
|
|
124
|
|
125 __extends(MouseWidget, _super);
|
|
126
|
|
127 function MouseWidget() {
|
|
128 return MouseWidget.__super__.constructor.apply(this, arguments);
|
|
129 }
|
|
130
|
|
131 MouseWidget.is_mouse_handled = false;
|
|
132
|
|
133 MouseWidget.prototype._init = function() {
|
|
134 this.$el.bind('mousedown.mousewidget', $.proxy(this._mouseDown, this));
|
|
135 return this.is_mouse_started = false;
|
|
136 };
|
|
137
|
|
138 MouseWidget.prototype._deinit = function() {
|
|
139 var $document;
|
|
140 this.$el.unbind('mousedown.mousewidget');
|
|
141 $document = $(document);
|
|
142 $document.unbind('mousemove.mousewidget');
|
|
143 return $document.unbind('mouseup.mousewidget');
|
|
144 };
|
|
145
|
|
146 MouseWidget.prototype._mouseDown = function(e) {
|
|
147 var $document;
|
|
148 if (MouseWidget.is_mouse_handled) {
|
|
149 return;
|
|
150 }
|
|
151 if (!this.is_mouse_started) {
|
|
152 this._mouseUp(e);
|
|
153 }
|
|
154 if (e.which !== 1) {
|
|
155 return;
|
|
156 }
|
|
157 if (!this._mouseCapture(e)) {
|
|
158 return;
|
|
159 }
|
|
160 this.mouse_down_event = e;
|
|
161 $document = $(document);
|
|
162 $document.bind('mousemove.mousewidget', $.proxy(this._mouseMove, this));
|
|
163 $document.bind('mouseup.mousewidget', $.proxy(this._mouseUp, this));
|
|
164 e.preventDefault();
|
|
165 this.is_mouse_handled = true;
|
|
166 return true;
|
|
167 };
|
|
168
|
|
169 MouseWidget.prototype._mouseMove = function(e) {
|
|
170 if (this.is_mouse_started) {
|
|
171 this._mouseDrag(e);
|
|
172 return e.preventDefault();
|
|
173 }
|
|
174 this.is_mouse_started = this._mouseStart(this.mouse_down_event) !== false;
|
|
175 if (this.is_mouse_started) {
|
|
176 this._mouseDrag(e);
|
|
177 } else {
|
|
178 this._mouseUp(e);
|
|
179 }
|
|
180 return !this.is_mouse_started;
|
|
181 };
|
|
182
|
|
183 MouseWidget.prototype._mouseUp = function(e) {
|
|
184 var $document;
|
|
185 $document = $(document);
|
|
186 $document.unbind('mousemove.mousewidget');
|
|
187 $document.unbind('mouseup.mousewidget');
|
|
188 if (this.is_mouse_started) {
|
|
189 this.is_mouse_started = false;
|
|
190 this._mouseStop(e);
|
|
191 }
|
|
192 return false;
|
|
193 };
|
|
194
|
|
195 MouseWidget.prototype._mouseCapture = function(e) {
|
|
196 return true;
|
|
197 };
|
|
198
|
|
199 MouseWidget.prototype._mouseStart = function(e) {
|
|
200 return null;
|
|
201 };
|
|
202
|
|
203 MouseWidget.prototype._mouseDrag = function(e) {
|
|
204 return null;
|
|
205 };
|
|
206
|
|
207 MouseWidget.prototype._mouseStop = function(e) {
|
|
208 return null;
|
|
209 };
|
|
210
|
|
211 return MouseWidget;
|
|
212
|
|
213 })(SimpleWidget);
|
|
214
|
|
215 /*
|
|
216 Copyright 2012 Marco Braak
|
|
217
|
|
218 Licensed under the Apache License, Version 2.0 (the "License");
|
|
219 you may not use this file except in compliance with the License.
|
|
220 You may obtain a copy of the License at
|
|
221
|
|
222 http://www.apache.org/licenses/LICENSE-2.0
|
|
223
|
|
224 Unless required by applicable law or agreed to in writing, software
|
|
225 distributed under the License is distributed on an "AS IS" BASIS,
|
|
226 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
227 See the License for the specific language governing permissions and
|
|
228 limitations under the License.
|
|
229 */
|
|
230
|
|
231
|
|
232 this.Tree = {};
|
|
233
|
|
234 $ = this.jQuery;
|
|
235
|
|
236 indexOf = function(array, item) {
|
|
237 var i, value, _i, _len;
|
|
238 if (array.indexOf) {
|
|
239 return array.indexOf(item);
|
|
240 } else {
|
|
241 for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) {
|
|
242 value = array[i];
|
|
243 if (value === item) {
|
|
244 return i;
|
|
245 }
|
|
246 }
|
|
247 return -1;
|
|
248 }
|
|
249 };
|
|
250
|
|
251 this.Tree.indexOf = indexOf;
|
|
252
|
|
253 Json = {};
|
|
254
|
|
255 Json.escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
|
|
256
|
|
257 Json.meta = {
|
|
258 '\b': '\\b',
|
|
259 '\t': '\\t',
|
|
260 '\n': '\\n',
|
|
261 '\f': '\\f',
|
|
262 '\r': '\\r',
|
|
263 '"': '\\"',
|
|
264 '\\': '\\\\'
|
|
265 };
|
|
266
|
|
267 Json.quote = function(string) {
|
|
268 Json.escapable.lastIndex = 0;
|
|
269 if (Json.escapable.test(string)) {
|
|
270 return '"' + string.replace(Json.escapable, function(a) {
|
|
271 var c;
|
|
272 c = Json.meta[a];
|
|
273 return (typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4));
|
|
274 }) + '"';
|
|
275 } else {
|
|
276 return '"' + string + '"';
|
|
277 }
|
|
278 };
|
|
279
|
|
280 Json.str = function(key, holder) {
|
|
281 var i, k, partial, v, value, _i, _len;
|
|
282 value = holder[key];
|
|
283 switch (typeof value) {
|
|
284 case 'string':
|
|
285 return Json.quote(value);
|
|
286 case 'number':
|
|
287 if (isFinite(value)) {
|
|
288 return String(value);
|
|
289 } else {
|
|
290 return 'null';
|
|
291 }
|
|
292 case 'boolean':
|
|
293 case 'null':
|
|
294 return String(value);
|
|
295 case 'object':
|
|
296 if (!value) {
|
|
297 return 'null';
|
|
298 }
|
|
299 partial = [];
|
|
300 if (Object.prototype.toString.apply(value) === '[object Array]') {
|
|
301 for (i = _i = 0, _len = value.length; _i < _len; i = ++_i) {
|
|
302 v = value[i];
|
|
303 partial[i] = Json.str(i, value) || 'null';
|
|
304 }
|
|
305 return (partial.length === 0 ? '[]' : '[' + partial.join(',') + ']');
|
|
306 }
|
|
307 for (k in value) {
|
|
308 if (Object.prototype.hasOwnProperty.call(value, k)) {
|
|
309 v = Json.str(k, value);
|
|
310 if (v) {
|
|
311 partial.push(Json.quote(k) + ':' + v);
|
|
312 }
|
|
313 }
|
|
314 }
|
|
315 return (partial.length === 0 ? '{}' : '{' + partial.join(',') + '}');
|
|
316 }
|
|
317 };
|
|
318
|
|
319 toJson = function(value) {
|
|
320 return Json.str('', {
|
|
321 '': value
|
|
322 });
|
|
323 };
|
|
324
|
|
325 this.Tree.toJson = toJson;
|
|
326
|
|
327 html_escape = function(string) {
|
|
328 return ('' + string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/');
|
|
329 };
|
|
330
|
|
331 Position = {
|
|
332 getName: function(position) {
|
|
333 if (position === Position.BEFORE) {
|
|
334 return 'before';
|
|
335 } else if (position === Position.AFTER) {
|
|
336 return 'after';
|
|
337 } else if (position === Position.INSIDE) {
|
|
338 return 'inside';
|
|
339 } else {
|
|
340 return 'none';
|
|
341 }
|
|
342 }
|
|
343 };
|
|
344
|
|
345 Position.BEFORE = 1;
|
|
346
|
|
347 Position.AFTER = 2;
|
|
348
|
|
349 Position.INSIDE = 3;
|
|
350
|
|
351 Position.NONE = 4;
|
|
352
|
|
353 this.Tree.Position = Position;
|
|
354
|
|
355 Node = (function() {
|
|
356
|
|
357 function Node(o) {
|
|
358 this.setData(o);
|
|
359 }
|
|
360
|
|
361 Node.prototype.setData = function(o) {
|
|
362 var key, value;
|
|
363 if (typeof o !== 'object') {
|
|
364 this.name = o;
|
|
365 } else {
|
|
366 for (key in o) {
|
|
367 value = o[key];
|
|
368 if (key === 'label') {
|
|
369 this.name = value;
|
|
370 } else {
|
|
371 this[key] = value;
|
|
372 }
|
|
373 }
|
|
374 }
|
|
375 this.children = [];
|
|
376 return this.parent = null;
|
|
377 };
|
|
378
|
|
379 Node.prototype.initFromData = function(data) {
|
|
380 var addChildren, addNode,
|
|
381 _this = this;
|
|
382 addNode = function(node_data) {
|
|
383 _this.setData(node_data);
|
|
384 if (node_data.children) {
|
|
385 return addChildren(node_data.children);
|
|
386 }
|
|
387 };
|
|
388 addChildren = function(children_data) {
|
|
389 var child, node, _i, _len;
|
|
390 for (_i = 0, _len = children_data.length; _i < _len; _i++) {
|
|
391 child = children_data[_i];
|
|
392 node = new Node('');
|
|
393 node.initFromData(child);
|
|
394 _this.addChild(node);
|
|
395 }
|
|
396 return null;
|
|
397 };
|
|
398 addNode(data);
|
|
399 return null;
|
|
400 };
|
|
401
|
|
402 /*
|
|
403 Create tree from data.
|
|
404
|
|
405 Structure of data is:
|
|
406 [
|
|
407 {
|
|
408 label: 'node1',
|
|
409 children: [
|
|
410 { label: 'child1' },
|
|
411 { label: 'child2' }
|
|
412 ]
|
|
413 },
|
|
414 {
|
|
415 label: 'node2'
|
|
416 }
|
|
417 ]
|
|
418 */
|
|
419
|
|
420
|
|
421 Node.prototype.loadFromData = function(data) {
|
|
422 var node, o, _i, _len;
|
|
423 this.children = [];
|
|
424 for (_i = 0, _len = data.length; _i < _len; _i++) {
|
|
425 o = data[_i];
|
|
426 node = new Node(o);
|
|
427 this.addChild(node);
|
|
428 if (typeof o === 'object' && o.children) {
|
|
429 node.loadFromData(o.children);
|
|
430 }
|
|
431 }
|
|
432 return null;
|
|
433 };
|
|
434
|
|
435 /*
|
|
436 Add child.
|
|
437
|
|
438 tree.addChild(
|
|
439 new Node('child1')
|
|
440 );
|
|
441 */
|
|
442
|
|
443
|
|
444 Node.prototype.addChild = function(node) {
|
|
445 this.children.push(node);
|
|
446 return node._setParent(this);
|
|
447 };
|
|
448
|
|
449 /*
|
|
450 Add child at position. Index starts at 0.
|
|
451
|
|
452 tree.addChildAtPosition(
|
|
453 new Node('abc'),
|
|
454 1
|
|
455 );
|
|
456 */
|
|
457
|
|
458
|
|
459 Node.prototype.addChildAtPosition = function(node, index) {
|
|
460 this.children.splice(index, 0, node);
|
|
461 return node._setParent(this);
|
|
462 };
|
|
463
|
|
464 Node.prototype._setParent = function(parent) {
|
|
465 this.parent = parent;
|
|
466 this.tree = parent.tree;
|
|
467 return this.tree.addNodeToIndex(this);
|
|
468 };
|
|
469
|
|
470 /*
|
|
471 Remove child.
|
|
472
|
|
473 tree.removeChild(tree.children[0]);
|
|
474 */
|
|
475
|
|
476
|
|
477 Node.prototype.removeChild = function(node) {
|
|
478 this.children.splice(this.getChildIndex(node), 1);
|
|
479 return this.tree.removeNodeFromIndex(node);
|
|
480 };
|
|
481
|
|
482 /*
|
|
483 Get child index.
|
|
484
|
|
485 var index = getChildIndex(node);
|
|
486 */
|
|
487
|
|
488
|
|
489 Node.prototype.getChildIndex = function(node) {
|
|
490 return $.inArray(node, this.children);
|
|
491 };
|
|
492
|
|
493 /*
|
|
494 Does the tree have children?
|
|
495
|
|
496 if (tree.hasChildren()) {
|
|
497 //
|
|
498 }
|
|
499 */
|
|
500
|
|
501
|
|
502 Node.prototype.hasChildren = function() {
|
|
503 return this.children.length !== 0;
|
|
504 };
|
|
505
|
|
506 /*
|
|
507 Iterate over all the nodes in the tree.
|
|
508
|
|
509 Calls callback with (node, level).
|
|
510
|
|
511 The callback must return true to continue the iteration on current node.
|
|
512
|
|
513 tree.iterate(
|
|
514 function(node, level) {
|
|
515 console.log(node.name);
|
|
516
|
|
517 // stop iteration after level 2
|
|
518 return (level <= 2);
|
|
519 }
|
|
520 );
|
|
521 */
|
|
522
|
|
523
|
|
524 Node.prototype.iterate = function(callback) {
|
|
525 var _iterate,
|
|
526 _this = this;
|
|
527 _iterate = function(node, level) {
|
|
528 var child, result, _i, _len, _ref;
|
|
529 if (node.children) {
|
|
530 _ref = node.children;
|
|
531 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
532 child = _ref[_i];
|
|
533 result = callback(child, level);
|
|
534 if (_this.hasChildren() && result) {
|
|
535 _iterate(child, level + 1);
|
|
536 }
|
|
537 }
|
|
538 return null;
|
|
539 }
|
|
540 };
|
|
541 _iterate(this, 0);
|
|
542 return null;
|
|
543 };
|
|
544
|
|
545 /*
|
|
546 Move node relative to another node.
|
|
547
|
|
548 Argument position: Position.BEFORE, Position.AFTER or Position.Inside
|
|
549
|
|
550 // move node1 after node2
|
|
551 tree.moveNode(node1, node2, Position.AFTER);
|
|
552 */
|
|
553
|
|
554
|
|
555 Node.prototype.moveNode = function(moved_node, target_node, position) {
|
|
556 moved_node.parent.removeChild(moved_node);
|
|
557 if (position === Position.AFTER) {
|
|
558 return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node) + 1);
|
|
559 } else if (position === Position.BEFORE) {
|
|
560 return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node));
|
|
561 } else if (position === Position.INSIDE) {
|
|
562 return target_node.addChildAtPosition(moved_node, 0);
|
|
563 }
|
|
564 };
|
|
565
|
|
566 /*
|
|
567 Get the tree as data.
|
|
568 */
|
|
569
|
|
570
|
|
571 Node.prototype.getData = function() {
|
|
572 var getDataFromNodes,
|
|
573 _this = this;
|
|
574 getDataFromNodes = function(nodes) {
|
|
575 var data, k, node, tmp_node, v, _i, _len;
|
|
576 data = [];
|
|
577 for (_i = 0, _len = nodes.length; _i < _len; _i++) {
|
|
578 node = nodes[_i];
|
|
579 tmp_node = {};
|
|
580 for (k in node) {
|
|
581 v = node[k];
|
|
582 if ((k !== 'parent' && k !== 'children' && k !== 'element' && k !== 'tree') && Object.prototype.hasOwnProperty.call(node, k)) {
|
|
583 tmp_node[k] = v;
|
|
584 }
|
|
585 }
|
|
586 if (node.hasChildren()) {
|
|
587 tmp_node.children = getDataFromNodes(node.children);
|
|
588 }
|
|
589 data.push(tmp_node);
|
|
590 }
|
|
591 return data;
|
|
592 };
|
|
593 return getDataFromNodes(this.children);
|
|
594 };
|
|
595
|
|
596 Node.prototype.getNodeByName = function(name) {
|
|
597 var result;
|
|
598 result = null;
|
|
599 this.iterate(function(node) {
|
|
600 if (node.name === name) {
|
|
601 result = node;
|
|
602 return false;
|
|
603 } else {
|
|
604 return true;
|
|
605 }
|
|
606 });
|
|
607 return result;
|
|
608 };
|
|
609
|
|
610 Node.prototype.addAfter = function(node_info) {
|
|
611 var child_index, node;
|
|
612 if (!this.parent) {
|
|
613 return null;
|
|
614 } else {
|
|
615 node = new Node(node_info);
|
|
616 child_index = this.parent.getChildIndex(this);
|
|
617 this.parent.addChildAtPosition(node, child_index + 1);
|
|
618 return node;
|
|
619 }
|
|
620 };
|
|
621
|
|
622 Node.prototype.addBefore = function(node_info) {
|
|
623 var child_index, node;
|
|
624 if (!this.parent) {
|
|
625 return null;
|
|
626 } else {
|
|
627 node = new Node(node_info);
|
|
628 child_index = this.parent.getChildIndex(this);
|
|
629 return this.parent.addChildAtPosition(node, child_index);
|
|
630 }
|
|
631 };
|
|
632
|
|
633 Node.prototype.addParent = function(node_info) {
|
|
634 var child, new_parent, original_parent, _i, _len, _ref;
|
|
635 if (!this.parent) {
|
|
636 return null;
|
|
637 } else {
|
|
638 new_parent = new Node(node_info);
|
|
639 new_parent._setParent(this.tree);
|
|
640 original_parent = this.parent;
|
|
641 _ref = original_parent.children;
|
|
642 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
643 child = _ref[_i];
|
|
644 new_parent.addChild(child);
|
|
645 }
|
|
646 original_parent.children = [];
|
|
647 original_parent.addChild(new_parent);
|
|
648 return new_parent;
|
|
649 }
|
|
650 };
|
|
651
|
|
652 Node.prototype.remove = function() {
|
|
653 if (this.parent) {
|
|
654 this.parent.removeChild(this);
|
|
655 return this.parent = null;
|
|
656 }
|
|
657 };
|
|
658
|
|
659 Node.prototype.append = function(node_info) {
|
|
660 var node;
|
|
661 node = new Node(node_info);
|
|
662 this.addChild(node);
|
|
663 return node;
|
|
664 };
|
|
665
|
|
666 Node.prototype.prepend = function(node_info) {
|
|
667 var node;
|
|
668 node = new Node(node_info);
|
|
669 this.addChildAtPosition(node, 0);
|
|
670 return node;
|
|
671 };
|
|
672
|
|
673 return Node;
|
|
674
|
|
675 })();
|
|
676
|
|
677 Tree = (function(_super) {
|
|
678
|
|
679 __extends(Tree, _super);
|
|
680
|
|
681 function Tree(o) {
|
|
682 Tree.__super__.constructor.call(this, o, null, true);
|
|
683 this.id_mapping = {};
|
|
684 this.tree = this;
|
|
685 }
|
|
686
|
|
687 Tree.prototype.getNodeById = function(node_id) {
|
|
688 return this.id_mapping[node_id];
|
|
689 };
|
|
690
|
|
691 Tree.prototype.addNodeToIndex = function(node) {
|
|
692 if (node.id) {
|
|
693 return this.id_mapping[node.id] = node;
|
|
694 }
|
|
695 };
|
|
696
|
|
697 Tree.prototype.removeNodeFromIndex = function(node) {
|
|
698 if (node.id) {
|
|
699 return delete this.id_mapping[node.id];
|
|
700 }
|
|
701 };
|
|
702
|
|
703 return Tree;
|
|
704
|
|
705 })(Node);
|
|
706
|
|
707 this.Tree.Tree = Tree;
|
|
708
|
|
709 JqTreeWidget = (function(_super) {
|
|
710
|
|
711 __extends(JqTreeWidget, _super);
|
|
712
|
|
713 function JqTreeWidget() {
|
|
714 return JqTreeWidget.__super__.constructor.apply(this, arguments);
|
|
715 }
|
|
716
|
|
717 JqTreeWidget.prototype.defaults = {
|
|
718 autoOpen: false,
|
|
719 saveState: false,
|
|
720 dragAndDrop: false,
|
|
721 selectable: false,
|
|
722 onCanSelectNode: null,
|
|
723 onSetStateFromStorage: null,
|
|
724 onGetStateFromStorage: null,
|
|
725 onCreateLi: null,
|
|
726 onIsMoveHandle: null,
|
|
727 onCanMove: null,
|
|
728 onCanMoveTo: null,
|
|
729 autoEscape: true,
|
|
730 dataUrl: null
|
|
731 };
|
|
732
|
|
733 JqTreeWidget.prototype.toggle = function(node) {
|
|
734 if (node.hasChildren()) {
|
|
735 new FolderElement(node, this.element).toggle();
|
|
736 }
|
|
737 return this._saveState();
|
|
738 };
|
|
739
|
|
740 JqTreeWidget.prototype.getTree = function() {
|
|
741 return this.tree;
|
|
742 };
|
|
743
|
|
744 JqTreeWidget.prototype.selectNode = function(node, must_open_parents) {
|
|
745 return this.select_node_handler.selectNode(node, must_open_parents);
|
|
746 };
|
|
747
|
|
748 JqTreeWidget.prototype.getSelectedNode = function() {
|
|
749 return this.selected_node || false;
|
|
750 };
|
|
751
|
|
752 JqTreeWidget.prototype.toJson = function() {
|
|
753 return toJson(this.tree.getData());
|
|
754 };
|
|
755
|
|
756 JqTreeWidget.prototype.loadData = function(data, parent_node) {
|
|
757 var child, subtree, _i, _len, _ref;
|
|
758 if (!parent_node) {
|
|
759 this._initTree(data);
|
|
760 } else {
|
|
761 subtree = new Node('');
|
|
762 subtree._setParent(parent_node.tree);
|
|
763 subtree.loadFromData(data);
|
|
764 _ref = subtree.children;
|
|
765 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
766 child = _ref[_i];
|
|
767 parent_node.addChild(child);
|
|
768 }
|
|
769 this._refreshElements(parent_node.parent);
|
|
770 }
|
|
771 if (this.is_dragging) {
|
|
772 return this.dnd_handler.refreshHitAreas();
|
|
773 }
|
|
774 };
|
|
775
|
|
776 JqTreeWidget.prototype.getNodeById = function(node_id) {
|
|
777 return this.tree.getNodeById(node_id);
|
|
778 };
|
|
779
|
|
780 JqTreeWidget.prototype.getNodeByName = function(name) {
|
|
781 return this.tree.getNodeByName(name);
|
|
782 };
|
|
783
|
|
784 JqTreeWidget.prototype.openNode = function(node, skip_slide) {
|
|
785 if (node.hasChildren()) {
|
|
786 new FolderElement(node, this.element).open(null, skip_slide);
|
|
787 return this._saveState();
|
|
788 }
|
|
789 };
|
|
790
|
|
791 JqTreeWidget.prototype.closeNode = function(node, skip_slide) {
|
|
792 if (node.hasChildren()) {
|
|
793 new FolderElement(node, this.element).close(skip_slide);
|
|
794 return this._saveState();
|
|
795 }
|
|
796 };
|
|
797
|
|
798 JqTreeWidget.prototype.isDragging = function() {
|
|
799 return this.is_dragging;
|
|
800 };
|
|
801
|
|
802 JqTreeWidget.prototype.refreshHitAreas = function() {
|
|
803 return this.dnd_handler.refreshHitAreas();
|
|
804 };
|
|
805
|
|
806 JqTreeWidget.prototype.addNodeAfter = function(new_node_info, existing_node) {
|
|
807 var new_node;
|
|
808 new_node = existing_node.addAfter(new_node_info);
|
|
809 this._refreshElements(existing_node.parent);
|
|
810 return new_node;
|
|
811 };
|
|
812
|
|
813 JqTreeWidget.prototype.addNodeBefore = function(new_node_info, existing_node) {
|
|
814 var new_node;
|
|
815 new_node = existing_node.addBefore(new_node_info);
|
|
816 this._refreshElements(existing_node.parent);
|
|
817 return new_node;
|
|
818 };
|
|
819
|
|
820 JqTreeWidget.prototype.addParentNode = function(new_node_info, existing_node) {
|
|
821 var new_node;
|
|
822 new_node = existing_node.addParent(new_node_info);
|
|
823 this._refreshElements(new_node.parent);
|
|
824 return new_node;
|
|
825 };
|
|
826
|
|
827 JqTreeWidget.prototype.removeNode = function(node) {
|
|
828 var parent;
|
|
829 parent = node.parent;
|
|
830 if (parent) {
|
|
831 node.remove();
|
|
832 return this._refreshElements(parent.parent);
|
|
833 }
|
|
834 };
|
|
835
|
|
836 JqTreeWidget.prototype.appendNode = function(new_node_info, parent_node) {
|
|
837 var is_already_root_node, node;
|
|
838 if (!parent_node) {
|
|
839 parent_node = this.tree;
|
|
840 }
|
|
841 is_already_root_node = parent_node.hasChildren();
|
|
842 node = parent_node.append(new_node_info);
|
|
843 if (is_already_root_node) {
|
|
844 this._refreshElements(parent_node);
|
|
845 } else {
|
|
846 this._refreshElements(parent_node.parent);
|
|
847 }
|
|
848 return node;
|
|
849 };
|
|
850
|
|
851 JqTreeWidget.prototype.prependNode = function(new_node_info, parent_node) {
|
|
852 var node;
|
|
853 if (!parent_node) {
|
|
854 parent_node = this.tree;
|
|
855 }
|
|
856 node = parent_node.prepend(new_node_info);
|
|
857 this._refreshElements(parent_node);
|
|
858 return node;
|
|
859 };
|
|
860
|
|
861 JqTreeWidget.prototype._init = function() {
|
|
862 JqTreeWidget.__super__._init.call(this);
|
|
863 this.element = this.$el;
|
|
864 this._initData();
|
|
865 this.element.click($.proxy(this._click, this));
|
|
866 return this.element.bind('contextmenu', $.proxy(this._contextmenu, this));
|
|
867 };
|
|
868
|
|
869 JqTreeWidget.prototype._deinit = function() {
|
|
870 this.element.empty();
|
|
871 this.element.unbind();
|
|
872 this.tree = null;
|
|
873 return JqTreeWidget.__super__._deinit.call(this);
|
|
874 };
|
|
875
|
|
876 JqTreeWidget.prototype._initData = function() {
|
|
877 var data_url,
|
|
878 _this = this;
|
|
879 if (this.options.data) {
|
|
880 return this._initTree(this.options.data);
|
|
881 } else {
|
|
882 data_url = this.options.dataUrl || this.element.data('url');
|
|
883 if (data_url) {
|
|
884 return $.ajax({
|
|
885 url: data_url,
|
|
886 cache: false,
|
|
887 success: function(response) {
|
|
888 var data;
|
|
889 if ($.isArray(response) || typeof response === 'object') {
|
|
890 data = response;
|
|
891 } else {
|
|
892 data = $.parseJSON(response);
|
|
893 }
|
|
894 return _this._initTree(data);
|
|
895 }
|
|
896 });
|
|
897 }
|
|
898 }
|
|
899 };
|
|
900
|
|
901 JqTreeWidget.prototype._initTree = function(data) {
|
|
902 var event;
|
|
903 this.tree = new Tree();
|
|
904 this.tree.loadFromData(data);
|
|
905 this.selected_node = null;
|
|
906 this.save_state_handler = new SaveStateHandler(this);
|
|
907 this.select_node_handler = new SelectNodeHandler(this);
|
|
908 this.dnd_handler = new DragAndDropHandler(this);
|
|
909 this._openNodes();
|
|
910 this._refreshElements();
|
|
911 this.select_node_handler.selectCurrentNode();
|
|
912 event = $.Event('tree.init');
|
|
913 return this.element.trigger(event);
|
|
914 };
|
|
915
|
|
916 JqTreeWidget.prototype._openNodes = function() {
|
|
917 var max_level;
|
|
918 if (this.options.saveState) {
|
|
919 if (this.save_state_handler.restoreState()) {
|
|
920 return;
|
|
921 }
|
|
922 }
|
|
923 if (this.options.autoOpen === false) {
|
|
924 return;
|
|
925 } else if (this.options.autoOpen === true) {
|
|
926 max_level = -1;
|
|
927 } else {
|
|
928 max_level = parseInt(this.options.autoOpen);
|
|
929 }
|
|
930 return this.tree.iterate(function(node, level) {
|
|
931 node.is_open = true;
|
|
932 return level !== max_level;
|
|
933 });
|
|
934 };
|
|
935
|
|
936 JqTreeWidget.prototype._refreshElements = function(from_node) {
|
|
937 var $element, createFolderLi, createLi, createNodeLi, createUl, doCreateDomElements, escapeIfNecessary, is_root_node, node_element,
|
|
938 _this = this;
|
|
939 if (from_node == null) {
|
|
940 from_node = null;
|
|
941 }
|
|
942 escapeIfNecessary = function(value) {
|
|
943 if (_this.options.autoEscape) {
|
|
944 return html_escape(value);
|
|
945 } else {
|
|
946 return value;
|
|
947 }
|
|
948 };
|
|
949 createUl = function(is_root_node) {
|
|
950 var class_string;
|
|
951 if (is_root_node) {
|
|
952 class_string = ' class="tree"';
|
|
953 } else {
|
|
954 class_string = '';
|
|
955 }
|
|
956 return $("<ul" + class_string + "></ul>");
|
|
957 };
|
|
958 createLi = function(node) {
|
|
959 var $li;
|
|
960 if (node.hasChildren()) {
|
|
961 $li = createFolderLi(node);
|
|
962 } else {
|
|
963 $li = createNodeLi(node);
|
|
964 }
|
|
965 if (_this.options.onCreateLi) {
|
|
966 _this.options.onCreateLi(node, $li);
|
|
967 }
|
|
968 return $li;
|
|
969 };
|
|
970 createNodeLi = function(node) {
|
|
971 var escaped_name;
|
|
972 escaped_name = escapeIfNecessary(node.name);
|
|
973 return $("<li><div><span class=\"title\">" + escaped_name + "</span></div></li>");
|
|
974 };
|
|
975 createFolderLi = function(node) {
|
|
976 var button_class, escaped_name, folder_class, getButtonClass, getFolderClass;
|
|
977 getButtonClass = function() {
|
|
978 var classes;
|
|
979 classes = ['toggler'];
|
|
980 if (!node.is_open) {
|
|
981 classes.push('closed');
|
|
982 }
|
|
983 return classes.join(' ');
|
|
984 };
|
|
985 getFolderClass = function() {
|
|
986 var classes;
|
|
987 classes = ['folder'];
|
|
988 if (!node.is_open) {
|
|
989 classes.push('closed');
|
|
990 }
|
|
991 return classes.join(' ');
|
|
992 };
|
|
993 button_class = getButtonClass();
|
|
994 folder_class = getFolderClass();
|
|
995 escaped_name = escapeIfNecessary(node.name);
|
|
996 return $("<li class=\"" + folder_class + "\"><div><a class=\"" + button_class + "\">»</a><span class=\"title\">" + escaped_name + "</span></div></li>");
|
|
997 };
|
|
998 doCreateDomElements = function($element, children, is_root_node, is_open) {
|
|
999 var $li, $ul, child, _i, _len;
|
|
1000 $ul = createUl(is_root_node);
|
|
1001 $element.append($ul);
|
|
1002 for (_i = 0, _len = children.length; _i < _len; _i++) {
|
|
1003 child = children[_i];
|
|
1004 $li = createLi(child);
|
|
1005 $ul.append($li);
|
|
1006 child.element = $li[0];
|
|
1007 $li.data('node', child);
|
|
1008 if (child.hasChildren()) {
|
|
1009 doCreateDomElements($li, child.children, false, child.is_open);
|
|
1010 }
|
|
1011 }
|
|
1012 return null;
|
|
1013 };
|
|
1014 if (from_node && from_node.parent) {
|
|
1015 is_root_node = false;
|
|
1016 node_element = this._getNodeElementForNode(from_node);
|
|
1017 node_element.getUl().remove();
|
|
1018 $element = node_element.$element;
|
|
1019 } else {
|
|
1020 from_node = this.tree;
|
|
1021 $element = this.element;
|
|
1022 $element.empty();
|
|
1023 is_root_node = true;
|
|
1024 }
|
|
1025 return doCreateDomElements($element, from_node.children, is_root_node, is_root_node);
|
|
1026 };
|
|
1027
|
|
1028 JqTreeWidget.prototype._click = function(e) {
|
|
1029 var $target, event, node, node_element;
|
|
1030 if (e.ctrlKey) {
|
|
1031 return;
|
|
1032 }
|
|
1033 $target = $(e.target);
|
|
1034 if ($target.is('.toggler')) {
|
|
1035 node_element = this._getNodeElement($target);
|
|
1036 if (node_element && node_element.node.hasChildren()) {
|
|
1037 node_element.toggle();
|
|
1038 this._saveState();
|
|
1039 e.preventDefault();
|
|
1040 return e.stopPropagation();
|
|
1041 }
|
|
1042 } else if ($target.is('div') || $target.is('span')) {
|
|
1043 node = this._getNode($target);
|
|
1044 if (node) {
|
|
1045 if ((!this.options.onCanSelectNode) || this.options.onCanSelectNode(node)) {
|
|
1046 this.selectNode(node);
|
|
1047 event = $.Event('tree.click');
|
|
1048 event.node = node;
|
|
1049 return this.element.trigger(event);
|
|
1050 }
|
|
1051 }
|
|
1052 }
|
|
1053 };
|
|
1054
|
|
1055 JqTreeWidget.prototype._getNode = function($element) {
|
|
1056 var $li;
|
|
1057 $li = $element.closest('li');
|
|
1058 if ($li.length === 0) {
|
|
1059 return null;
|
|
1060 } else {
|
|
1061 return $li.data('node');
|
|
1062 }
|
|
1063 };
|
|
1064
|
|
1065 JqTreeWidget.prototype._getNodeElementForNode = function(node) {
|
|
1066 if (node.hasChildren()) {
|
|
1067 return new FolderElement(node, this.element);
|
|
1068 } else {
|
|
1069 return new NodeElement(node, this.element);
|
|
1070 }
|
|
1071 };
|
|
1072
|
|
1073 JqTreeWidget.prototype._getNodeElement = function($element) {
|
|
1074 var node;
|
|
1075 node = this._getNode($element);
|
|
1076 if (node) {
|
|
1077 return this._getNodeElementForNode(node);
|
|
1078 } else {
|
|
1079 return null;
|
|
1080 }
|
|
1081 };
|
|
1082
|
|
1083 JqTreeWidget.prototype._contextmenu = function(e) {
|
|
1084 var $div, event, node;
|
|
1085 $div = $(e.target).closest('ul.tree div');
|
|
1086 if ($div.length) {
|
|
1087 node = this._getNode($div);
|
|
1088 if (node) {
|
|
1089 e.preventDefault();
|
|
1090 e.stopPropagation();
|
|
1091 event = $.Event('tree.contextmenu');
|
|
1092 event.node = node;
|
|
1093 event.click_event = e;
|
|
1094 this.element.trigger(event);
|
|
1095 return false;
|
|
1096 }
|
|
1097 }
|
|
1098 };
|
|
1099
|
|
1100 JqTreeWidget.prototype._saveState = function() {
|
|
1101 if (this.options.saveState) {
|
|
1102 return this.save_state_handler.saveState();
|
|
1103 }
|
|
1104 };
|
|
1105
|
|
1106 JqTreeWidget.prototype._mouseCapture = function(event) {
|
|
1107 if (this.options.dragAndDrop) {
|
|
1108 return this.dnd_handler.mouseCapture(event);
|
|
1109 } else {
|
|
1110 return false;
|
|
1111 }
|
|
1112 };
|
|
1113
|
|
1114 JqTreeWidget.prototype._mouseStart = function(event) {
|
|
1115 if (this.options.dragAndDrop) {
|
|
1116 return this.dnd_handler.mouseStart(event);
|
|
1117 } else {
|
|
1118 return false;
|
|
1119 }
|
|
1120 };
|
|
1121
|
|
1122 JqTreeWidget.prototype._mouseDrag = function(event) {
|
|
1123 if (this.options.dragAndDrop) {
|
|
1124 return this.dnd_handler.mouseDrag(event);
|
|
1125 } else {
|
|
1126 return false;
|
|
1127 }
|
|
1128 };
|
|
1129
|
|
1130 JqTreeWidget.prototype._mouseStop = function() {
|
|
1131 if (this.options.dragAndDrop) {
|
|
1132 return this.dnd_handler.mouseStop();
|
|
1133 } else {
|
|
1134 return false;
|
|
1135 }
|
|
1136 };
|
|
1137
|
|
1138 JqTreeWidget.prototype.testGenerateHitAreas = function(moving_node) {
|
|
1139 this.dnd_handler.current_item = this._getNodeElementForNode(moving_node);
|
|
1140 this.dnd_handler.generateHitAreas();
|
|
1141 return this.dnd_handler.hit_areas;
|
|
1142 };
|
|
1143
|
|
1144 return JqTreeWidget;
|
|
1145
|
|
1146 })(MouseWidget);
|
|
1147
|
|
1148 SimpleWidget.register(JqTreeWidget, 'tree');
|
|
1149
|
|
1150 GhostDropHint = (function() {
|
|
1151
|
|
1152 function GhostDropHint(node, $element, position) {
|
|
1153 this.$element = $element;
|
|
1154 this.node = node;
|
|
1155 this.$ghost = $('<li class="ghost"><span class="circle"></span><span class="line"></span></li>');
|
|
1156 if (position === Position.AFTER) {
|
|
1157 this.moveAfter();
|
|
1158 } else if (position === Position.BEFORE) {
|
|
1159 this.moveBefore();
|
|
1160 } else if (position === Position.INSIDE) {
|
|
1161 if (node.hasChildren() && node.is_open) {
|
|
1162 this.moveInsideOpenFolder();
|
|
1163 } else {
|
|
1164 this.moveInside();
|
|
1165 }
|
|
1166 }
|
|
1167 }
|
|
1168
|
|
1169 GhostDropHint.prototype.remove = function() {
|
|
1170 return this.$ghost.remove();
|
|
1171 };
|
|
1172
|
|
1173 GhostDropHint.prototype.moveAfter = function() {
|
|
1174 return this.$element.after(this.$ghost);
|
|
1175 };
|
|
1176
|
|
1177 GhostDropHint.prototype.moveBefore = function() {
|
|
1178 return this.$element.before(this.$ghost);
|
|
1179 };
|
|
1180
|
|
1181 GhostDropHint.prototype.moveInsideOpenFolder = function() {
|
|
1182 return $(this.node.children[0].element).before(this.$ghost);
|
|
1183 };
|
|
1184
|
|
1185 GhostDropHint.prototype.moveInside = function() {
|
|
1186 this.$element.after(this.$ghost);
|
|
1187 return this.$ghost.addClass('inside');
|
|
1188 };
|
|
1189
|
|
1190 return GhostDropHint;
|
|
1191
|
|
1192 })();
|
|
1193
|
|
1194 BorderDropHint = (function() {
|
|
1195
|
|
1196 function BorderDropHint($element) {
|
|
1197 var $div, width;
|
|
1198 $div = $element.children('div');
|
|
1199 width = $element.width() - 4;
|
|
1200 this.$hint = $('<span class="border"></span>');
|
|
1201 $div.append(this.$hint);
|
|
1202 this.$hint.css({
|
|
1203 width: width,
|
|
1204 height: $div.height() - 4
|
|
1205 });
|
|
1206 }
|
|
1207
|
|
1208 BorderDropHint.prototype.remove = function() {
|
|
1209 return this.$hint.remove();
|
|
1210 };
|
|
1211
|
|
1212 return BorderDropHint;
|
|
1213
|
|
1214 })();
|
|
1215
|
|
1216 NodeElement = (function() {
|
|
1217
|
|
1218 function NodeElement(node, tree_element) {
|
|
1219 this.init(node, tree_element);
|
|
1220 }
|
|
1221
|
|
1222 NodeElement.prototype.init = function(node, tree_element) {
|
|
1223 this.node = node;
|
|
1224 this.tree_element = tree_element;
|
|
1225 return this.$element = $(node.element);
|
|
1226 };
|
|
1227
|
|
1228 NodeElement.prototype.getUl = function() {
|
|
1229 return this.$element.children('ul:first');
|
|
1230 };
|
|
1231
|
|
1232 NodeElement.prototype.getSpan = function() {
|
|
1233 return this.$element.children('div').find('span.title');
|
|
1234 };
|
|
1235
|
|
1236 NodeElement.prototype.getLi = function() {
|
|
1237 return this.$element;
|
|
1238 };
|
|
1239
|
|
1240 NodeElement.prototype.addDropHint = function(position) {
|
|
1241 if (position === Position.INSIDE) {
|
|
1242 return new BorderDropHint(this.$element);
|
|
1243 } else {
|
|
1244 return new GhostDropHint(this.node, this.$element, position);
|
|
1245 }
|
|
1246 };
|
|
1247
|
|
1248 NodeElement.prototype.select = function() {
|
|
1249 return this.getLi().addClass('selected');
|
|
1250 };
|
|
1251
|
|
1252 NodeElement.prototype.deselect = function() {
|
|
1253 return this.getLi().removeClass('selected');
|
|
1254 };
|
|
1255
|
|
1256 return NodeElement;
|
|
1257
|
|
1258 })();
|
|
1259
|
|
1260 FolderElement = (function(_super) {
|
|
1261
|
|
1262 __extends(FolderElement, _super);
|
|
1263
|
|
1264 function FolderElement() {
|
|
1265 return FolderElement.__super__.constructor.apply(this, arguments);
|
|
1266 }
|
|
1267
|
|
1268 FolderElement.prototype.toggle = function() {
|
|
1269 if (this.node.is_open) {
|
|
1270 return this.close();
|
|
1271 } else {
|
|
1272 return this.open();
|
|
1273 }
|
|
1274 };
|
|
1275
|
|
1276 FolderElement.prototype.open = function(on_finished, skip_slide) {
|
|
1277 var doOpen,
|
|
1278 _this = this;
|
|
1279 if (!this.node.is_open) {
|
|
1280 this.node.is_open = true;
|
|
1281 this.getButton().removeClass('closed');
|
|
1282 doOpen = function() {
|
|
1283 var event;
|
|
1284 _this.getLi().removeClass('closed');
|
|
1285 if (on_finished) {
|
|
1286 on_finished();
|
|
1287 }
|
|
1288 event = $.Event('tree.open');
|
|
1289 event.node = _this.node;
|
|
1290 return _this.tree_element.trigger(event);
|
|
1291 };
|
|
1292 if (skip_slide) {
|
|
1293 return doOpen();
|
|
1294 } else {
|
|
1295 return this.getUl().slideDown('fast', doOpen);
|
|
1296 }
|
|
1297 }
|
|
1298 };
|
|
1299
|
|
1300 FolderElement.prototype.close = function(skip_slide) {
|
|
1301 var doClose,
|
|
1302 _this = this;
|
|
1303 if (this.node.is_open) {
|
|
1304 this.node.is_open = false;
|
|
1305 this.getButton().addClass('closed');
|
|
1306 doClose = function() {
|
|
1307 var event;
|
|
1308 _this.getLi().addClass('closed');
|
|
1309 event = $.Event('tree.close');
|
|
1310 event.node = _this.node;
|
|
1311 return _this.tree_element.trigger(event);
|
|
1312 };
|
|
1313 if (skip_slide) {
|
|
1314 return doClose();
|
|
1315 } else {
|
|
1316 return this.getUl().slideUp('fast', doClose);
|
|
1317 }
|
|
1318 }
|
|
1319 };
|
|
1320
|
|
1321 FolderElement.prototype.getButton = function() {
|
|
1322 return this.$element.children('div').find('a.toggler');
|
|
1323 };
|
|
1324
|
|
1325 FolderElement.prototype.addDropHint = function(position) {
|
|
1326 if (!this.node.is_open && position === Position.INSIDE) {
|
|
1327 return new BorderDropHint(this.$element);
|
|
1328 } else {
|
|
1329 return new GhostDropHint(this.node, this.$element, position);
|
|
1330 }
|
|
1331 };
|
|
1332
|
|
1333 return FolderElement;
|
|
1334
|
|
1335 })(NodeElement);
|
|
1336
|
|
1337 DragElement = (function() {
|
|
1338
|
|
1339 function DragElement(node, offset_x, offset_y, $tree) {
|
|
1340 this.offset_x = offset_x;
|
|
1341 this.offset_y = offset_y;
|
|
1342 this.$element = $("<span class=\"title tree-dragging\">" + node.name + "</span>");
|
|
1343 this.$element.css("position", "absolute");
|
|
1344 $tree.append(this.$element);
|
|
1345 }
|
|
1346
|
|
1347 DragElement.prototype.move = function(page_x, page_y) {
|
|
1348 return this.$element.offset({
|
|
1349 left: page_x - this.offset_x,
|
|
1350 top: page_y - this.offset_y
|
|
1351 });
|
|
1352 };
|
|
1353
|
|
1354 DragElement.prototype.remove = function() {
|
|
1355 return this.$element.remove();
|
|
1356 };
|
|
1357
|
|
1358 return DragElement;
|
|
1359
|
|
1360 })();
|
|
1361
|
|
1362 SaveStateHandler = (function() {
|
|
1363
|
|
1364 function SaveStateHandler(tree_widget) {
|
|
1365 this.tree_widget = tree_widget;
|
|
1366 }
|
|
1367
|
|
1368 SaveStateHandler.prototype.saveState = function() {
|
|
1369 if (this.tree_widget.options.onSetStateFromStorage) {
|
|
1370 return this.tree_widget.options.onSetStateFromStorage(this.getState());
|
|
1371 } else if (typeof localStorage !== "undefined" && localStorage !== null) {
|
|
1372 return localStorage.setItem(this.getCookieName(), this.getState());
|
|
1373 } else if ($.cookie) {
|
|
1374 return $.cookie(this.getCookieName(), this.getState(), {
|
|
1375 path: '/'
|
|
1376 });
|
|
1377 }
|
|
1378 };
|
|
1379
|
|
1380 SaveStateHandler.prototype.restoreState = function() {
|
|
1381 var state;
|
|
1382 if (this.tree_widget.options.onGetStateFromStorage) {
|
|
1383 state = this.tree_widget.options.onGetStateFromStorage();
|
|
1384 } else if (typeof localStorage !== "undefined" && localStorage !== null) {
|
|
1385 state = localStorage.getItem(this.getCookieName());
|
|
1386 } else if ($.cookie) {
|
|
1387 state = $.cookie(this.getCookieName(), {
|
|
1388 path: '/'
|
|
1389 });
|
|
1390 } else {
|
|
1391 state = null;
|
|
1392 }
|
|
1393 if (!state) {
|
|
1394 return false;
|
|
1395 } else {
|
|
1396 this.setState(state);
|
|
1397 return true;
|
|
1398 }
|
|
1399 };
|
|
1400
|
|
1401 SaveStateHandler.prototype.getState = function() {
|
|
1402 var open_nodes, selected_node,
|
|
1403 _this = this;
|
|
1404 open_nodes = [];
|
|
1405 this.tree_widget.tree.iterate(function(node) {
|
|
1406 if (node.is_open && node.id && node.hasChildren()) {
|
|
1407 open_nodes.push(node.id);
|
|
1408 }
|
|
1409 return true;
|
|
1410 });
|
|
1411 selected_node = '';
|
|
1412 if (this.tree_widget.selected_node) {
|
|
1413 selected_node = this.tree_widget.selected_node.id;
|
|
1414 }
|
|
1415 return toJson({
|
|
1416 open_nodes: open_nodes,
|
|
1417 selected_node: selected_node
|
|
1418 });
|
|
1419 };
|
|
1420
|
|
1421 SaveStateHandler.prototype.setState = function(state) {
|
|
1422 var data, open_nodes, selected_node_id,
|
|
1423 _this = this;
|
|
1424 data = $.parseJSON(state);
|
|
1425 if (data) {
|
|
1426 open_nodes = data.open_nodes;
|
|
1427 selected_node_id = data.selected_node;
|
|
1428 return this.tree_widget.tree.iterate(function(node) {
|
|
1429 if (node.id && node.hasChildren() && (indexOf(open_nodes, node.id) >= 0)) {
|
|
1430 node.is_open = true;
|
|
1431 }
|
|
1432 if (selected_node_id && (node.id === selected_node_id)) {
|
|
1433 _this.tree_widget.selected_node = node;
|
|
1434 }
|
|
1435 return true;
|
|
1436 });
|
|
1437 }
|
|
1438 };
|
|
1439
|
|
1440 SaveStateHandler.prototype.getCookieName = function() {
|
|
1441 if (typeof this.tree_widget.options.saveState === 'string') {
|
|
1442 return this.tree_widget.options.saveState;
|
|
1443 } else {
|
|
1444 return 'tree';
|
|
1445 }
|
|
1446 };
|
|
1447
|
|
1448 return SaveStateHandler;
|
|
1449
|
|
1450 })();
|
|
1451
|
|
1452 SelectNodeHandler = (function() {
|
|
1453
|
|
1454 function SelectNodeHandler(tree_widget) {
|
|
1455 this.tree_widget = tree_widget;
|
|
1456 }
|
|
1457
|
|
1458 SelectNodeHandler.prototype.selectNode = function(node, must_open_parents) {
|
|
1459 var parent;
|
|
1460 if (this.tree_widget.options.selectable) {
|
|
1461 if (this.tree_widget.selected_node) {
|
|
1462 this.tree_widget._getNodeElementForNode(this.tree_widget.selected_node).deselect();
|
|
1463 this.tree_widget.selected_node = null;
|
|
1464 }
|
|
1465 if (node) {
|
|
1466 this.tree_widget._getNodeElementForNode(node).select();
|
|
1467 this.tree_widget.selected_node = node;
|
|
1468 if (must_open_parents) {
|
|
1469 parent = this.tree_widget.selected_node.parent;
|
|
1470 while (parent) {
|
|
1471 if (!parent.is_open) {
|
|
1472 this.tree_widget.openNode(parent, true);
|
|
1473 }
|
|
1474 parent = parent.parent;
|
|
1475 }
|
|
1476 }
|
|
1477 }
|
|
1478 if (this.tree_widget.options.saveState) {
|
|
1479 return this.tree_widget.save_state_handler.saveState();
|
|
1480 }
|
|
1481 }
|
|
1482 };
|
|
1483
|
|
1484 SelectNodeHandler.prototype.selectCurrentNode = function() {
|
|
1485 var node_element;
|
|
1486 if (this.tree_widget.selected_node) {
|
|
1487 node_element = this.tree_widget._getNodeElementForNode(this.tree_widget.selected_node);
|
|
1488 if (node_element) {
|
|
1489 return node_element.select();
|
|
1490 }
|
|
1491 }
|
|
1492 };
|
|
1493
|
|
1494 return SelectNodeHandler;
|
|
1495
|
|
1496 })();
|
|
1497
|
|
1498 DragAndDropHandler = (function() {
|
|
1499
|
|
1500 function DragAndDropHandler(tree_widget) {
|
|
1501 this.tree_widget = tree_widget;
|
|
1502 this.hovered_area = null;
|
|
1503 this.$ghost = null;
|
|
1504 this.hit_areas = [];
|
|
1505 this.is_dragging = false;
|
|
1506 }
|
|
1507
|
|
1508 DragAndDropHandler.prototype.mouseCapture = function(event) {
|
|
1509 var $element, node_element;
|
|
1510 $element = $(event.target);
|
|
1511 if (this.tree_widget.options.onIsMoveHandle && !this.tree_widget.options.onIsMoveHandle($element)) {
|
|
1512 return null;
|
|
1513 }
|
|
1514 node_element = this.tree_widget._getNodeElement($element);
|
|
1515 if (node_element && this.tree_widget.options.onCanMove) {
|
|
1516 if (!this.tree_widget.options.onCanMove(node_element.node)) {
|
|
1517 node_element = null;
|
|
1518 }
|
|
1519 }
|
|
1520 this.current_item = node_element;
|
|
1521 return this.current_item !== null;
|
|
1522 };
|
|
1523
|
|
1524 DragAndDropHandler.prototype.mouseStart = function(event) {
|
|
1525 var offsetX, offsetY, _ref;
|
|
1526 this.refreshHitAreas();
|
|
1527 _ref = this.getOffsetFromEvent(event), offsetX = _ref[0], offsetY = _ref[1];
|
|
1528 this.drag_element = new DragElement(this.current_item.node, offsetX, offsetY, this.tree_widget.element);
|
|
1529 this.is_dragging = true;
|
|
1530 this.current_item.$element.addClass('moving');
|
|
1531 return true;
|
|
1532 };
|
|
1533
|
|
1534 DragAndDropHandler.prototype.mouseDrag = function(event) {
|
|
1535 var area, position_name;
|
|
1536 this.drag_element.move(event.pageX, event.pageY);
|
|
1537 area = this.findHoveredArea(event.pageX, event.pageY);
|
|
1538 if (area && this.tree_widget.options.onCanMoveTo) {
|
|
1539 position_name = Position.getName(area.position);
|
|
1540 if (!this.tree_widget.options.onCanMoveTo(this.current_item.node, area.node, position_name)) {
|
|
1541 area = null;
|
|
1542 }
|
|
1543 }
|
|
1544 if (!area) {
|
|
1545 this.removeDropHint();
|
|
1546 this.removeHover();
|
|
1547 this.stopOpenFolderTimer();
|
|
1548 } else {
|
|
1549 if (this.hovered_area !== area) {
|
|
1550 this.hovered_area = area;
|
|
1551 this.updateDropHint();
|
|
1552 }
|
|
1553 }
|
|
1554 return true;
|
|
1555 };
|
|
1556
|
|
1557 DragAndDropHandler.prototype.mouseStop = function() {
|
|
1558 this.moveItem();
|
|
1559 this.clear();
|
|
1560 this.removeHover();
|
|
1561 this.removeDropHint();
|
|
1562 this.removeHitAreas();
|
|
1563 this.current_item.$element.removeClass('moving');
|
|
1564 this.is_dragging = false;
|
|
1565 return false;
|
|
1566 };
|
|
1567
|
|
1568 DragAndDropHandler.prototype.getOffsetFromEvent = function(event) {
|
|
1569 var element_offset;
|
|
1570 element_offset = $(event.target).offset();
|
|
1571 return [event.pageX - element_offset.left, event.pageY - element_offset.top];
|
|
1572 };
|
|
1573
|
|
1574 DragAndDropHandler.prototype.refreshHitAreas = function() {
|
|
1575 this.removeHitAreas();
|
|
1576 return this.generateHitAreas();
|
|
1577 };
|
|
1578
|
|
1579 DragAndDropHandler.prototype.removeHitAreas = function() {
|
|
1580 return this.hit_areas = [];
|
|
1581 };
|
|
1582
|
|
1583 DragAndDropHandler.prototype.clear = function() {
|
|
1584 this.drag_element.remove();
|
|
1585 return this.drag_element = null;
|
|
1586 };
|
|
1587
|
|
1588 DragAndDropHandler.prototype.removeDropHint = function() {
|
|
1589 if (this.previous_ghost) {
|
|
1590 return this.previous_ghost.remove();
|
|
1591 }
|
|
1592 };
|
|
1593
|
|
1594 DragAndDropHandler.prototype.removeHover = function() {
|
|
1595 return this.hovered_area = null;
|
|
1596 };
|
|
1597
|
|
1598 DragAndDropHandler.prototype.generateHitAreas = function() {
|
|
1599 var addPosition, getTop, groupPositions, handleAfterOpenFolder, handleClosedFolder, handleFirstNode, handleNode, handleOpenFolder, hit_areas, last_top, positions,
|
|
1600 _this = this;
|
|
1601 positions = [];
|
|
1602 last_top = 0;
|
|
1603 getTop = function($element) {
|
|
1604 return $element.offset().top;
|
|
1605 };
|
|
1606 addPosition = function(node, position, top) {
|
|
1607 positions.push({
|
|
1608 top: top,
|
|
1609 node: node,
|
|
1610 position: position
|
|
1611 });
|
|
1612 return last_top = top;
|
|
1613 };
|
|
1614 groupPositions = function(handle_group) {
|
|
1615 var group, position, previous_top, _i, _len;
|
|
1616 previous_top = -1;
|
|
1617 group = [];
|
|
1618 for (_i = 0, _len = positions.length; _i < _len; _i++) {
|
|
1619 position = positions[_i];
|
|
1620 if (position.top !== previous_top) {
|
|
1621 if (group.length) {
|
|
1622 handle_group(group, previous_top, position.top);
|
|
1623 }
|
|
1624 previous_top = position.top;
|
|
1625 group = [];
|
|
1626 }
|
|
1627 group.push(position);
|
|
1628 }
|
|
1629 return handle_group(group, previous_top, _this.tree_widget.element.offset().top + _this.tree_widget.element.height());
|
|
1630 };
|
|
1631 handleNode = function(node, next_node, $element) {
|
|
1632 var top;
|
|
1633 top = getTop($element);
|
|
1634 if (node === _this.current_item.node) {
|
|
1635 addPosition(node, Position.NONE, top);
|
|
1636 } else {
|
|
1637 addPosition(node, Position.INSIDE, top);
|
|
1638 }
|
|
1639 if (next_node === _this.current_item.node || node === _this.current_item.node) {
|
|
1640 return addPosition(node, Position.NONE, top);
|
|
1641 } else {
|
|
1642 return addPosition(node, Position.AFTER, top);
|
|
1643 }
|
|
1644 };
|
|
1645 handleOpenFolder = function(node, $element) {
|
|
1646 if (node === _this.current_item.node) {
|
|
1647 return false;
|
|
1648 }
|
|
1649 if (node.children[0] !== _this.current_item.node) {
|
|
1650 addPosition(node, Position.INSIDE, getTop($element));
|
|
1651 }
|
|
1652 return true;
|
|
1653 };
|
|
1654 handleAfterOpenFolder = function(node, next_node, $element) {
|
|
1655 if (node === _this.current_item.node || next_node === _this.current_item.node) {
|
|
1656 return addPosition(node, Position.NONE, last_top);
|
|
1657 } else {
|
|
1658 return addPosition(node, Position.AFTER, last_top);
|
|
1659 }
|
|
1660 };
|
|
1661 handleClosedFolder = function(node, next_node, $element) {
|
|
1662 var top;
|
|
1663 top = getTop($element);
|
|
1664 if (node === _this.current_item.node) {
|
|
1665 return addPosition(node, Position.NONE, top);
|
|
1666 } else {
|
|
1667 addPosition(node, Position.INSIDE, top);
|
|
1668 if (next_node !== _this.current_item.node) {
|
|
1669 return addPosition(node, Position.AFTER, top);
|
|
1670 }
|
|
1671 }
|
|
1672 };
|
|
1673 handleFirstNode = function(node, $element) {
|
|
1674 if (node !== _this.current_item.node) {
|
|
1675 return addPosition(node, Position.BEFORE, getTop($(node.element)));
|
|
1676 }
|
|
1677 };
|
|
1678 this.iterateVisibleNodes(handleNode, handleOpenFolder, handleClosedFolder, handleAfterOpenFolder, handleFirstNode);
|
|
1679 hit_areas = [];
|
|
1680 groupPositions(function(positions_in_group, top, bottom) {
|
|
1681 var area_height, area_top, position, _i, _len;
|
|
1682 area_height = (bottom - top) / positions_in_group.length;
|
|
1683 area_top = top;
|
|
1684 for (_i = 0, _len = positions_in_group.length; _i < _len; _i++) {
|
|
1685 position = positions_in_group[_i];
|
|
1686 hit_areas.push({
|
|
1687 top: area_top,
|
|
1688 bottom: area_top + area_height,
|
|
1689 node: position.node,
|
|
1690 position: position.position
|
|
1691 });
|
|
1692 area_top += area_height;
|
|
1693 }
|
|
1694 return null;
|
|
1695 });
|
|
1696 return this.hit_areas = hit_areas;
|
|
1697 };
|
|
1698
|
|
1699 DragAndDropHandler.prototype.iterateVisibleNodes = function(handle_node, handle_open_folder, handle_closed_folder, handle_after_open_folder, handle_first_node) {
|
|
1700 var is_first_node, iterate,
|
|
1701 _this = this;
|
|
1702 is_first_node = true;
|
|
1703 iterate = function(node, next_node) {
|
|
1704 var $element, child, children_length, i, must_iterate_inside, _i, _len, _ref;
|
|
1705 must_iterate_inside = (node.is_open || !node.element) && node.hasChildren();
|
|
1706 if (node.element) {
|
|
1707 $element = $(node.element);
|
|
1708 if (!$element.is(':visible')) {
|
|
1709 return;
|
|
1710 }
|
|
1711 if (is_first_node) {
|
|
1712 handle_first_node(node, $element);
|
|
1713 is_first_node = false;
|
|
1714 }
|
|
1715 if (!node.hasChildren()) {
|
|
1716 handle_node(node, next_node, $element);
|
|
1717 } else if (node.is_open) {
|
|
1718 if (!handle_open_folder(node, $element)) {
|
|
1719 must_iterate_inside = false;
|
|
1720 }
|
|
1721 } else {
|
|
1722 handle_closed_folder(node, next_node, $element);
|
|
1723 }
|
|
1724 }
|
|
1725 if (must_iterate_inside) {
|
|
1726 children_length = node.children.length;
|
|
1727 _ref = node.children;
|
|
1728 for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
|
|
1729 child = _ref[i];
|
|
1730 if (i === (children_length - 1)) {
|
|
1731 iterate(node.children[i], null);
|
|
1732 } else {
|
|
1733 iterate(node.children[i], node.children[i + 1]);
|
|
1734 }
|
|
1735 }
|
|
1736 if (node.is_open) {
|
|
1737 return handle_after_open_folder(node, next_node, $element);
|
|
1738 }
|
|
1739 }
|
|
1740 };
|
|
1741 return iterate(this.tree_widget.tree);
|
|
1742 };
|
|
1743
|
|
1744 DragAndDropHandler.prototype.findHoveredArea = function(x, y) {
|
|
1745 var area, high, low, mid, tree_offset;
|
|
1746 tree_offset = this.tree_widget.element.offset();
|
|
1747 if (x < tree_offset.left || y < tree_offset.top || x > (tree_offset.left + this.tree_widget.element.width()) || y > (tree_offset.top + this.tree_widget.element.height())) {
|
|
1748 return null;
|
|
1749 }
|
|
1750 low = 0;
|
|
1751 high = this.hit_areas.length;
|
|
1752 while (low < high) {
|
|
1753 mid = (low + high) >> 1;
|
|
1754 area = this.hit_areas[mid];
|
|
1755 if (y < area.top) {
|
|
1756 high = mid;
|
|
1757 } else if (y > area.bottom) {
|
|
1758 low = mid + 1;
|
|
1759 } else {
|
|
1760 return area;
|
|
1761 }
|
|
1762 }
|
|
1763 return null;
|
|
1764 };
|
|
1765
|
|
1766 DragAndDropHandler.prototype.updateDropHint = function() {
|
|
1767 var node, node_element;
|
|
1768 this.stopOpenFolderTimer();
|
|
1769 if (!this.hovered_area) {
|
|
1770 return;
|
|
1771 }
|
|
1772 node = this.hovered_area.node;
|
|
1773 if (node.hasChildren() && !node.is_open && this.hovered_area.position === Position.INSIDE) {
|
|
1774 this.startOpenFolderTimer(node);
|
|
1775 }
|
|
1776 this.removeDropHint();
|
|
1777 node_element = this.tree_widget._getNodeElementForNode(this.hovered_area.node);
|
|
1778 return this.previous_ghost = node_element.addDropHint(this.hovered_area.position);
|
|
1779 };
|
|
1780
|
|
1781 DragAndDropHandler.prototype.startOpenFolderTimer = function(folder) {
|
|
1782 var openFolder,
|
|
1783 _this = this;
|
|
1784 openFolder = function() {
|
|
1785 return _this.tree_widget._getNodeElementForNode(folder).open(function() {
|
|
1786 _this.refreshHitAreas();
|
|
1787 return _this.updateDropHint();
|
|
1788 });
|
|
1789 };
|
|
1790 return this.open_folder_timer = setTimeout(openFolder, 500);
|
|
1791 };
|
|
1792
|
|
1793 DragAndDropHandler.prototype.stopOpenFolderTimer = function() {
|
|
1794 if (this.open_folder_timer) {
|
|
1795 clearTimeout(this.open_folder_timer);
|
|
1796 return this.open_folder_timer = null;
|
|
1797 }
|
|
1798 };
|
|
1799
|
|
1800 DragAndDropHandler.prototype.moveItem = function() {
|
|
1801 var doMove, event, moved_node, position, previous_parent, target_node,
|
|
1802 _this = this;
|
|
1803 if (this.hovered_area && this.hovered_area.position !== Position.NONE) {
|
|
1804 moved_node = this.current_item.node;
|
|
1805 target_node = this.hovered_area.node;
|
|
1806 position = this.hovered_area.position;
|
|
1807 previous_parent = moved_node.parent;
|
|
1808 if (position === Position.INSIDE) {
|
|
1809 this.hovered_area.node.is_open = true;
|
|
1810 }
|
|
1811 doMove = function() {
|
|
1812 _this.tree_widget.tree.moveNode(moved_node, target_node, position);
|
|
1813 _this.tree_widget.element.empty();
|
|
1814 return _this.tree_widget._refreshElements();
|
|
1815 };
|
|
1816 event = $.Event('tree.move');
|
|
1817 event.move_info = {
|
|
1818 moved_node: moved_node,
|
|
1819 target_node: target_node,
|
|
1820 position: Position.getName(position),
|
|
1821 previous_parent: previous_parent,
|
|
1822 do_move: doMove
|
|
1823 };
|
|
1824 this.tree_widget.element.trigger(event);
|
|
1825 if (!event.isDefaultPrevented()) {
|
|
1826 return doMove();
|
|
1827 }
|
|
1828 }
|
|
1829 };
|
|
1830
|
|
1831 return DragAndDropHandler;
|
|
1832
|
|
1833 })();
|
|
1834
|
|
1835 this.Tree.Node = Node;
|
|
1836
|
|
1837 }).call(this);
|