Mercurial > hg > orthanc
comparison OrthancServer/OrthancExplorer/libs/tree.jquery.js @ 4044:d25f4c0fa160 framework
splitting code into OrthancFramework and OrthancServer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 10 Jun 2020 20:30:34 +0200 |
parents | OrthancExplorer/libs/tree.jquery.js@4bc019d2f969 |
children |
comparison
equal
deleted
inserted
replaced
4043:6c6239aec462 | 4044:d25f4c0fa160 |
---|---|
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); |