OLD | NEW |
| (Empty) |
1 // Generated by CoffeeScript 1.6.3 | |
2 /* | |
3 Copyright 2013 Marco Braak | |
4 | |
5 Licensed under the Apache License, Version 2.0 (the "License"); | |
6 you may not use this file except in compliance with the License. | |
7 You may obtain a copy of the License at | |
8 | |
9 http://www.apache.org/licenses/LICENSE-2.0 | |
10 | |
11 Unless required by applicable law or agreed to in writing, software | |
12 distributed under the License is distributed on an "AS IS" BASIS, | |
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 See the License for the specific language governing permissions and | |
15 limitations under the License. | |
16 */ | |
17 | |
18 | |
19 (function() { | |
20 var $, BorderDropHint, DragAndDropHandler, DragElement, FolderElement, GhostDr
opHint, JqTreeWidget, KeyHandler, MouseWidget, Node, NodeElement, Position, Save
StateHandler, ScrollHandler, SelectNodeHandler, SimpleWidget, html_escape, index
Of, json_escapable, json_meta, json_quote, json_str, _indexOf, _ref, _ref1, _ref
2, | |
21 __slice = [].slice, | |
22 __hasProp = {}.hasOwnProperty, | |
23 __extends = function(child, parent) { for (var key in parent) { if (__hasPro
p.call(parent, key)) child[key] = parent[key]; } function ctor() { this.construc
tor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor();
child.__super__ = parent.prototype; return child; }; | |
24 | |
25 $ = this.jQuery; | |
26 | |
27 SimpleWidget = (function() { | |
28 SimpleWidget.prototype.defaults = {}; | |
29 | |
30 function SimpleWidget(el, options) { | |
31 this.$el = $(el); | |
32 this.options = $.extend({}, this.defaults, options); | |
33 } | |
34 | |
35 SimpleWidget.prototype.destroy = function() { | |
36 return this._deinit(); | |
37 }; | |
38 | |
39 SimpleWidget.prototype._init = function() { | |
40 return null; | |
41 }; | |
42 | |
43 SimpleWidget.prototype._deinit = function() { | |
44 return null; | |
45 }; | |
46 | |
47 SimpleWidget.register = function(widget_class, widget_name) { | |
48 var callFunction, createWidget, destroyWidget, getDataKey; | |
49 getDataKey = function() { | |
50 return "simple_widget_" + widget_name; | |
51 }; | |
52 createWidget = function($el, options) { | |
53 var data_key, el, widget, _i, _len; | |
54 data_key = getDataKey(); | |
55 for (_i = 0, _len = $el.length; _i < _len; _i++) { | |
56 el = $el[_i]; | |
57 widget = new widget_class(el, options); | |
58 if (!$.data(el, data_key)) { | |
59 $.data(el, data_key, widget); | |
60 } | |
61 widget._init(); | |
62 } | |
63 return $el; | |
64 }; | |
65 destroyWidget = function($el) { | |
66 var data_key, el, widget, _i, _len, _results; | |
67 data_key = getDataKey(); | |
68 _results = []; | |
69 for (_i = 0, _len = $el.length; _i < _len; _i++) { | |
70 el = $el[_i]; | |
71 widget = $.data(el, data_key); | |
72 if (widget && (widget instanceof SimpleWidget)) { | |
73 widget.destroy(); | |
74 } | |
75 _results.push($.removeData(el, data_key)); | |
76 } | |
77 return _results; | |
78 }; | |
79 callFunction = function($el, function_name, args) { | |
80 var el, result, widget, widget_function, _i, _len; | |
81 result = null; | |
82 for (_i = 0, _len = $el.length; _i < _len; _i++) { | |
83 el = $el[_i]; | |
84 widget = $.data(el, getDataKey()); | |
85 if (widget && (widget instanceof SimpleWidget)) { | |
86 widget_function = widget[function_name]; | |
87 if (widget_function && (typeof widget_function === 'function')) { | |
88 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(ar
guments, 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 __extends(MouseWidget, _super); | |
125 | |
126 function MouseWidget() { | |
127 _ref = MouseWidget.__super__.constructor.apply(this, arguments); | |
128 return _ref; | |
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 this.$el.bind('touchstart.mousewidget', $.proxy(this._touchStart, this)); | |
136 this.is_mouse_started = false; | |
137 this.mouse_delay = 0; | |
138 this._mouse_delay_timer = null; | |
139 this._is_mouse_delay_met = true; | |
140 return this.mouse_down_info = null; | |
141 }; | |
142 | |
143 MouseWidget.prototype._deinit = function() { | |
144 var $document; | |
145 this.$el.unbind('mousedown.mousewidget'); | |
146 this.$el.unbind('touchstart.mousewidget'); | |
147 $document = $(document); | |
148 $document.unbind('mousemove.mousewidget'); | |
149 return $document.unbind('mouseup.mousewidget'); | |
150 }; | |
151 | |
152 MouseWidget.prototype._mouseDown = function(e) { | |
153 var result; | |
154 if (e.which !== 1) { | |
155 return; | |
156 } | |
157 result = this._handleMouseDown(e, this._getPositionInfo(e)); | |
158 if (result) { | |
159 e.preventDefault(); | |
160 } | |
161 return result; | |
162 }; | |
163 | |
164 MouseWidget.prototype._handleMouseDown = function(e, position_info) { | |
165 if (MouseWidget.is_mouse_handled) { | |
166 return; | |
167 } | |
168 if (this.is_mouse_started) { | |
169 this._handleMouseUp(position_info); | |
170 } | |
171 this.mouse_down_info = position_info; | |
172 if (!this._mouseCapture(position_info)) { | |
173 return; | |
174 } | |
175 this._handleStartMouse(); | |
176 this.is_mouse_handled = true; | |
177 return true; | |
178 }; | |
179 | |
180 MouseWidget.prototype._handleStartMouse = function() { | |
181 var $document; | |
182 $document = $(document); | |
183 $document.bind('mousemove.mousewidget', $.proxy(this._mouseMove, this)); | |
184 $document.bind('touchmove.mousewidget', $.proxy(this._touchMove, this)); | |
185 $document.bind('mouseup.mousewidget', $.proxy(this._mouseUp, this)); | |
186 $document.bind('touchend.mousewidget', $.proxy(this._touchEnd, this)); | |
187 if (this.mouse_delay) { | |
188 return this._startMouseDelayTimer(); | |
189 } | |
190 }; | |
191 | |
192 MouseWidget.prototype._startMouseDelayTimer = function() { | |
193 var _this = this; | |
194 if (this._mouse_delay_timer) { | |
195 clearTimeout(this._mouse_delay_timer); | |
196 } | |
197 this._mouse_delay_timer = setTimeout(function() { | |
198 return _this._is_mouse_delay_met = true; | |
199 }, this.mouse_delay); | |
200 return this._is_mouse_delay_met = false; | |
201 }; | |
202 | |
203 MouseWidget.prototype._mouseMove = function(e) { | |
204 return this._handleMouseMove(e, this._getPositionInfo(e)); | |
205 }; | |
206 | |
207 MouseWidget.prototype._handleMouseMove = function(e, position_info) { | |
208 if (this.is_mouse_started) { | |
209 this._mouseDrag(position_info); | |
210 return e.preventDefault(); | |
211 } | |
212 if (this.mouse_delay && !this._is_mouse_delay_met) { | |
213 return true; | |
214 } | |
215 this.is_mouse_started = this._mouseStart(this.mouse_down_info) !== false; | |
216 if (this.is_mouse_started) { | |
217 this._mouseDrag(position_info); | |
218 } else { | |
219 this._handleMouseUp(position_info); | |
220 } | |
221 return !this.is_mouse_started; | |
222 }; | |
223 | |
224 MouseWidget.prototype._getPositionInfo = function(e) { | |
225 return { | |
226 page_x: e.pageX, | |
227 page_y: e.pageY, | |
228 target: e.target, | |
229 original_event: e | |
230 }; | |
231 }; | |
232 | |
233 MouseWidget.prototype._mouseUp = function(e) { | |
234 return this._handleMouseUp(this._getPositionInfo(e)); | |
235 }; | |
236 | |
237 MouseWidget.prototype._handleMouseUp = function(position_info) { | |
238 var $document; | |
239 $document = $(document); | |
240 $document.unbind('mousemove.mousewidget'); | |
241 $document.unbind('touchmove.mousewidget'); | |
242 $document.unbind('mouseup.mousewidget'); | |
243 $document.unbind('touchend.mousewidget'); | |
244 if (this.is_mouse_started) { | |
245 this.is_mouse_started = false; | |
246 this._mouseStop(position_info); | |
247 } | |
248 }; | |
249 | |
250 MouseWidget.prototype._mouseCapture = function(position_info) { | |
251 return true; | |
252 }; | |
253 | |
254 MouseWidget.prototype._mouseStart = function(position_info) { | |
255 return null; | |
256 }; | |
257 | |
258 MouseWidget.prototype._mouseDrag = function(position_info) { | |
259 return null; | |
260 }; | |
261 | |
262 MouseWidget.prototype._mouseStop = function(position_info) { | |
263 return null; | |
264 }; | |
265 | |
266 MouseWidget.prototype.setMouseDelay = function(mouse_delay) { | |
267 return this.mouse_delay = mouse_delay; | |
268 }; | |
269 | |
270 MouseWidget.prototype._touchStart = function(e) { | |
271 var touch; | |
272 if (e.originalEvent.touches.length > 1) { | |
273 return; | |
274 } | |
275 touch = e.originalEvent.changedTouches[0]; | |
276 return this._handleMouseDown(e, this._getPositionInfo(touch)); | |
277 }; | |
278 | |
279 MouseWidget.prototype._touchMove = function(e) { | |
280 var touch; | |
281 if (e.originalEvent.touches.length > 1) { | |
282 return; | |
283 } | |
284 touch = e.originalEvent.changedTouches[0]; | |
285 return this._handleMouseMove(e, this._getPositionInfo(touch)); | |
286 }; | |
287 | |
288 MouseWidget.prototype._touchEnd = function(e) { | |
289 var touch; | |
290 if (e.originalEvent.touches.length > 1) { | |
291 return; | |
292 } | |
293 touch = e.originalEvent.changedTouches[0]; | |
294 return this._handleMouseUp(this._getPositionInfo(touch)); | |
295 }; | |
296 | |
297 return MouseWidget; | |
298 | |
299 })(SimpleWidget); | |
300 | |
301 this.Tree = {}; | |
302 | |
303 $ = this.jQuery; | |
304 | |
305 Position = { | |
306 getName: function(position) { | |
307 return Position.strings[position - 1]; | |
308 }, | |
309 nameToIndex: function(name) { | |
310 var i, _i, _ref1; | |
311 for (i = _i = 1, _ref1 = Position.strings.length; 1 <= _ref1 ? _i <= _ref1
: _i >= _ref1; i = 1 <= _ref1 ? ++_i : --_i) { | |
312 if (Position.strings[i - 1] === name) { | |
313 return i; | |
314 } | |
315 } | |
316 return 0; | |
317 } | |
318 }; | |
319 | |
320 Position.BEFORE = 1; | |
321 | |
322 Position.AFTER = 2; | |
323 | |
324 Position.INSIDE = 3; | |
325 | |
326 Position.NONE = 4; | |
327 | |
328 Position.strings = ['before', 'after', 'inside', 'none']; | |
329 | |
330 this.Tree.Position = Position; | |
331 | |
332 Node = (function() { | |
333 function Node(o, is_root, node_class) { | |
334 if (is_root == null) { | |
335 is_root = false; | |
336 } | |
337 if (node_class == null) { | |
338 node_class = Node; | |
339 } | |
340 this.setData(o); | |
341 this.children = []; | |
342 this.parent = null; | |
343 if (is_root) { | |
344 this.id_mapping = {}; | |
345 this.tree = this; | |
346 this.node_class = node_class; | |
347 } | |
348 } | |
349 | |
350 Node.prototype.setData = function(o) { | |
351 var key, value, _results; | |
352 if (typeof o !== 'object') { | |
353 return this.name = o; | |
354 } else { | |
355 _results = []; | |
356 for (key in o) { | |
357 value = o[key]; | |
358 if (key === 'label') { | |
359 _results.push(this.name = value); | |
360 } else { | |
361 _results.push(this[key] = value); | |
362 } | |
363 } | |
364 return _results; | |
365 } | |
366 }; | |
367 | |
368 Node.prototype.initFromData = function(data) { | |
369 var addChildren, addNode, | |
370 _this = this; | |
371 addNode = function(node_data) { | |
372 _this.setData(node_data); | |
373 if (node_data.children) { | |
374 return addChildren(node_data.children); | |
375 } | |
376 }; | |
377 addChildren = function(children_data) { | |
378 var child, node, _i, _len; | |
379 for (_i = 0, _len = children_data.length; _i < _len; _i++) { | |
380 child = children_data[_i]; | |
381 node = new _this.tree.node_class(''); | |
382 node.initFromData(child); | |
383 _this.addChild(node); | |
384 } | |
385 return null; | |
386 }; | |
387 addNode(data); | |
388 return null; | |
389 }; | |
390 | |
391 /* | |
392 Create tree from data. | |
393 | |
394 Structure of data is: | |
395 [ | |
396 { | |
397 label: 'node1', | |
398 children: [ | |
399 { label: 'child1' }, | |
400 { label: 'child2' } | |
401 ] | |
402 }, | |
403 { | |
404 label: 'node2' | |
405 } | |
406 ] | |
407 */ | |
408 | |
409 | |
410 Node.prototype.loadFromData = function(data) { | |
411 var node, o, _i, _len; | |
412 this.removeChildren(); | |
413 for (_i = 0, _len = data.length; _i < _len; _i++) { | |
414 o = data[_i]; | |
415 node = new this.tree.node_class(o); | |
416 this.addChild(node); | |
417 if (typeof o === 'object' && o.children) { | |
418 node.loadFromData(o.children); | |
419 } | |
420 } | |
421 return null; | |
422 }; | |
423 | |
424 /* | |
425 Add child. | |
426 | |
427 tree.addChild( | |
428 new Node('child1') | |
429 ); | |
430 */ | |
431 | |
432 | |
433 Node.prototype.addChild = function(node) { | |
434 this.children.push(node); | |
435 return node._setParent(this); | |
436 }; | |
437 | |
438 /* | |
439 Add child at position. Index starts at 0. | |
440 | |
441 tree.addChildAtPosition( | |
442 new Node('abc'), | |
443 1 | |
444 ); | |
445 */ | |
446 | |
447 | |
448 Node.prototype.addChildAtPosition = function(node, index) { | |
449 this.children.splice(index, 0, node); | |
450 return node._setParent(this); | |
451 }; | |
452 | |
453 Node.prototype._setParent = function(parent) { | |
454 this.parent = parent; | |
455 this.tree = parent.tree; | |
456 return this.tree.addNodeToIndex(this); | |
457 }; | |
458 | |
459 /* | |
460 Remove child. This also removes the children of the node. | |
461 | |
462 tree.removeChild(tree.children[0]); | |
463 */ | |
464 | |
465 | |
466 Node.prototype.removeChild = function(node) { | |
467 node.removeChildren(); | |
468 return this._removeChild(node); | |
469 }; | |
470 | |
471 Node.prototype._removeChild = function(node) { | |
472 this.children.splice(this.getChildIndex(node), 1); | |
473 return this.tree.removeNodeFromIndex(node); | |
474 }; | |
475 | |
476 /* | |
477 Get child index. | |
478 | |
479 var index = getChildIndex(node); | |
480 */ | |
481 | |
482 | |
483 Node.prototype.getChildIndex = function(node) { | |
484 return $.inArray(node, this.children); | |
485 }; | |
486 | |
487 /* | |
488 Does the tree have children? | |
489 | |
490 if (tree.hasChildren()) { | |
491 // | |
492 } | |
493 */ | |
494 | |
495 | |
496 Node.prototype.hasChildren = function() { | |
497 return this.children.length !== 0; | |
498 }; | |
499 | |
500 Node.prototype.isFolder = function() { | |
501 return this.hasChildren() || this.load_on_demand; | |
502 }; | |
503 | |
504 /* | |
505 Iterate over all the nodes in the tree. | |
506 | |
507 Calls callback with (node, level). | |
508 | |
509 The callback must return true to continue the iteration on current node. | |
510 | |
511 tree.iterate( | |
512 function(node, level) { | |
513 console.log(node.name); | |
514 | |
515 // stop iteration after level 2 | |
516 return (level <= 2); | |
517 } | |
518 ); | |
519 */ | |
520 | |
521 | |
522 Node.prototype.iterate = function(callback) { | |
523 var _iterate, | |
524 _this = this; | |
525 _iterate = function(node, level) { | |
526 var child, result, _i, _len, _ref1; | |
527 if (node.children) { | |
528 _ref1 = node.children; | |
529 for (_i = 0, _len = _ref1.length; _i < _len; _i++) { | |
530 child = _ref1[_i]; | |
531 result = callback(child, level); | |
532 if (_this.hasChildren() && result) { | |
533 _iterate(child, level + 1); | |
534 } | |
535 } | |
536 return null; | |
537 } | |
538 }; | |
539 _iterate(this, 0); | |
540 return null; | |
541 }; | |
542 | |
543 /* | |
544 Move node relative to another node. | |
545 | |
546 Argument position: Position.BEFORE, Position.AFTER or Position.Inside | |
547 | |
548 // move node1 after node2 | |
549 tree.moveNode(node1, node2, Position.AFTER); | |
550 */ | |
551 | |
552 | |
553 Node.prototype.moveNode = function(moved_node, target_node, position) { | |
554 if (moved_node.isParentOf(target_node)) { | |
555 return; | |
556 } | |
557 moved_node.parent._removeChild(moved_node); | |
558 if (position === Position.AFTER) { | |
559 return target_node.parent.addChildAtPosition(moved_node, target_node.par
ent.getChildIndex(target_node) + 1); | |
560 } else if (position === Position.BEFORE) { | |
561 return target_node.parent.addChildAtPosition(moved_node, target_node.par
ent.getChildIndex(target_node)); | |
562 } else if (position === Position.INSIDE) { | |
563 return target_node.addChildAtPosition(moved_node, 0); | |
564 } | |
565 }; | |
566 | |
567 /* | |
568 Get the tree as data. | |
569 */ | |
570 | |
571 | |
572 Node.prototype.getData = function() { | |
573 var getDataFromNodes, | |
574 _this = this; | |
575 getDataFromNodes = function(nodes) { | |
576 var data, k, node, tmp_node, v, _i, _len; | |
577 data = []; | |
578 for (_i = 0, _len = nodes.length; _i < _len; _i++) { | |
579 node = nodes[_i]; | |
580 tmp_node = {}; | |
581 for (k in node) { | |
582 v = node[k]; | |
583 if ((k !== 'parent' && k !== 'children' && k !== 'element' && k !==
'tree') && Object.prototype.hasOwnProperty.call(node, k)) { | |
584 tmp_node[k] = v; | |
585 } | |
586 } | |
587 if (node.hasChildren()) { | |
588 tmp_node.children = getDataFromNodes(node.children); | |
589 } | |
590 data.push(tmp_node); | |
591 } | |
592 return data; | |
593 }; | |
594 return getDataFromNodes(this.children); | |
595 }; | |
596 | |
597 Node.prototype.getNodeByName = function(name) { | |
598 var result; | |
599 result = null; | |
600 this.iterate(function(node) { | |
601 if (node.name === name) { | |
602 result = node; | |
603 return false; | |
604 } else { | |
605 return true; | |
606 } | |
607 }); | |
608 return result; | |
609 }; | |
610 | |
611 Node.prototype.addAfter = function(node_info) { | |
612 var child_index, node; | |
613 if (!this.parent) { | |
614 return null; | |
615 } else { | |
616 node = new this.tree.node_class(node_info); | |
617 child_index = this.parent.getChildIndex(this); | |
618 this.parent.addChildAtPosition(node, child_index + 1); | |
619 return node; | |
620 } | |
621 }; | |
622 | |
623 Node.prototype.addBefore = function(node_info) { | |
624 var child_index, node; | |
625 if (!this.parent) { | |
626 return null; | |
627 } else { | |
628 node = new this.tree.node_class(node_info); | |
629 child_index = this.parent.getChildIndex(this); | |
630 this.parent.addChildAtPosition(node, child_index); | |
631 return node; | |
632 } | |
633 }; | |
634 | |
635 Node.prototype.addParent = function(node_info) { | |
636 var child, new_parent, original_parent, _i, _len, _ref1; | |
637 if (!this.parent) { | |
638 return null; | |
639 } else { | |
640 new_parent = new this.tree.node_class(node_info); | |
641 new_parent._setParent(this.tree); | |
642 original_parent = this.parent; | |
643 _ref1 = original_parent.children; | |
644 for (_i = 0, _len = _ref1.length; _i < _len; _i++) { | |
645 child = _ref1[_i]; | |
646 new_parent.addChild(child); | |
647 } | |
648 original_parent.children = []; | |
649 original_parent.addChild(new_parent); | |
650 return new_parent; | |
651 } | |
652 }; | |
653 | |
654 Node.prototype.remove = function() { | |
655 if (this.parent) { | |
656 this.parent.removeChild(this); | |
657 return this.parent = null; | |
658 } | |
659 }; | |
660 | |
661 Node.prototype.append = function(node_info) { | |
662 var node; | |
663 node = new this.tree.node_class(node_info); | |
664 this.addChild(node); | |
665 return node; | |
666 }; | |
667 | |
668 Node.prototype.prepend = function(node_info) { | |
669 var node; | |
670 node = new this.tree.node_class(node_info); | |
671 this.addChildAtPosition(node, 0); | |
672 return node; | |
673 }; | |
674 | |
675 Node.prototype.isParentOf = function(node) { | |
676 var parent; | |
677 parent = node.parent; | |
678 while (parent) { | |
679 if (parent === this) { | |
680 return true; | |
681 } | |
682 parent = parent.parent; | |
683 } | |
684 return false; | |
685 }; | |
686 | |
687 Node.prototype.getLevel = function() { | |
688 var level, node; | |
689 level = 0; | |
690 node = this; | |
691 while (node.parent) { | |
692 level += 1; | |
693 node = node.parent; | |
694 } | |
695 return level; | |
696 }; | |
697 | |
698 Node.prototype.getNodeById = function(node_id) { | |
699 return this.id_mapping[node_id]; | |
700 }; | |
701 | |
702 Node.prototype.addNodeToIndex = function(node) { | |
703 if (node.id) { | |
704 return this.id_mapping[node.id] = node; | |
705 } | |
706 }; | |
707 | |
708 Node.prototype.removeNodeFromIndex = function(node) { | |
709 if (node.id) { | |
710 return delete this.id_mapping[node.id]; | |
711 } | |
712 }; | |
713 | |
714 Node.prototype.removeChildren = function() { | |
715 var _this = this; | |
716 this.iterate(function(child) { | |
717 _this.tree.removeNodeFromIndex(child); | |
718 return true; | |
719 }); | |
720 return this.children = []; | |
721 }; | |
722 | |
723 Node.prototype.getPreviousSibling = function() { | |
724 var previous_index; | |
725 if (!this.parent) { | |
726 return null; | |
727 } else { | |
728 previous_index = this.parent.getChildIndex(this) - 1; | |
729 if (previous_index >= 0) { | |
730 return this.parent.children[previous_index]; | |
731 } else { | |
732 return null; | |
733 } | |
734 } | |
735 }; | |
736 | |
737 Node.prototype.getNextSibling = function() { | |
738 var next_index; | |
739 if (!this.parent) { | |
740 return null; | |
741 } else { | |
742 next_index = this.parent.getChildIndex(this) + 1; | |
743 if (next_index < this.parent.children.length) { | |
744 return this.parent.children[next_index]; | |
745 } else { | |
746 return null; | |
747 } | |
748 } | |
749 }; | |
750 | |
751 return Node; | |
752 | |
753 })(); | |
754 | |
755 this.Tree.Node = Node; | |
756 | |
757 /* | |
758 Copyright 2013 Marco Braak | |
759 | |
760 Licensed under the Apache License, Version 2.0 (the "License"); | |
761 you may not use this file except in compliance with the License. | |
762 You may obtain a copy of the License at | |
763 | |
764 http://www.apache.org/licenses/LICENSE-2.0 | |
765 | |
766 Unless required by applicable law or agreed to in writing, software | |
767 distributed under the License is distributed on an "AS IS" BASIS, | |
768 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
769 See the License for the specific language governing permissions and | |
770 limitations under the License. | |
771 */ | |
772 | |
773 | |
774 JqTreeWidget = (function(_super) { | |
775 __extends(JqTreeWidget, _super); | |
776 | |
777 function JqTreeWidget() { | |
778 _ref1 = JqTreeWidget.__super__.constructor.apply(this, arguments); | |
779 return _ref1; | |
780 } | |
781 | |
782 JqTreeWidget.prototype.defaults = { | |
783 autoOpen: false, | |
784 saveState: false, | |
785 dragAndDrop: false, | |
786 selectable: true, | |
787 useContextMenu: true, | |
788 onCanSelectNode: null, | |
789 onSetStateFromStorage: null, | |
790 onGetStateFromStorage: null, | |
791 onCreateLi: null, | |
792 onIsMoveHandle: null, | |
793 onCanMove: null, | |
794 onCanMoveTo: null, | |
795 onLoadFailed: null, | |
796 autoEscape: true, | |
797 dataUrl: null, | |
798 closedIcon: '►', | |
799 openedIcon: '▼', | |
800 slide: true, | |
801 nodeClass: Node | |
802 }; | |
803 | |
804 JqTreeWidget.prototype.toggle = function(node, slide) { | |
805 if (slide == null) { | |
806 slide = true; | |
807 } | |
808 if (node.is_open) { | |
809 return this.closeNode(node, slide); | |
810 } else { | |
811 return this.openNode(node, slide); | |
812 } | |
813 }; | |
814 | |
815 JqTreeWidget.prototype.getTree = function() { | |
816 return this.tree; | |
817 }; | |
818 | |
819 JqTreeWidget.prototype.selectNode = function(node) { | |
820 return this._selectNode(node, true); | |
821 }; | |
822 | |
823 JqTreeWidget.prototype._selectNode = function(node, must_toggle) { | |
824 var canSelect, openParents, saveState, | |
825 _this = this; | |
826 if (must_toggle == null) { | |
827 must_toggle = false; | |
828 } | |
829 if (!this.select_node_handler) { | |
830 return; | |
831 } | |
832 canSelect = function() { | |
833 if (_this.options.onCanSelectNode) { | |
834 return _this.options.selectable && _this.options.onCanSelectNode(node)
; | |
835 } else { | |
836 return _this.options.selectable; | |
837 } | |
838 }; | |
839 openParents = function() { | |
840 var parent; | |
841 parent = node.parent; | |
842 if (parent && parent.parent && !parent.is_open) { | |
843 return _this.openNode(parent, false); | |
844 } | |
845 }; | |
846 saveState = function() { | |
847 if (_this.options.saveState) { | |
848 return _this.save_state_handler.saveState(); | |
849 } | |
850 }; | |
851 if (!node) { | |
852 this._deselectCurrentNode(); | |
853 saveState(); | |
854 return; | |
855 } | |
856 if (!canSelect()) { | |
857 return; | |
858 } | |
859 if (this.select_node_handler.isNodeSelected(node)) { | |
860 if (must_toggle) { | |
861 this._deselectCurrentNode(); | |
862 this._triggerEvent('tree.select', { | |
863 node: null, | |
864 previous_node: node | |
865 }); | |
866 } | |
867 } else { | |
868 this._deselectCurrentNode(); | |
869 this.addToSelection(node); | |
870 this._triggerEvent('tree.select', { | |
871 node: node | |
872 }); | |
873 openParents(); | |
874 } | |
875 return saveState(); | |
876 }; | |
877 | |
878 JqTreeWidget.prototype.getSelectedNode = function() { | |
879 return this.select_node_handler.getSelectedNode(); | |
880 }; | |
881 | |
882 JqTreeWidget.prototype.toJson = function() { | |
883 return JSON.stringify(this.tree.getData()); | |
884 }; | |
885 | |
886 JqTreeWidget.prototype.loadData = function(data, parent_node) { | |
887 return this._loadData(data, parent_node); | |
888 }; | |
889 | |
890 JqTreeWidget.prototype.loadDataFromUrl = function(url, parent_node, on_finis
hed) { | |
891 if ($.type(url) !== 'string') { | |
892 on_finished = parent_node; | |
893 parent_node = url; | |
894 url = null; | |
895 } | |
896 return this._loadDataFromUrl(url, parent_node, on_finished); | |
897 }; | |
898 | |
899 JqTreeWidget.prototype._loadDataFromUrl = function(url_info, parent_node, on
_finished) { | |
900 var $el, addLoadingClass, parseUrlInfo, removeLoadingClass, | |
901 _this = this; | |
902 $el = null; | |
903 addLoadingClass = function() { | |
904 var folder_element; | |
905 if (!parent_node) { | |
906 $el = _this.element; | |
907 } else { | |
908 folder_element = new FolderElement(parent_node, _this); | |
909 $el = folder_element.getLi(); | |
910 } | |
911 return $el.addClass('jqtree-loading'); | |
912 }; | |
913 removeLoadingClass = function() { | |
914 if ($el) { | |
915 return $el.removeClass('jqtree-loading'); | |
916 } | |
917 }; | |
918 parseUrlInfo = function() { | |
919 if ($.type(url_info) === 'string') { | |
920 url_info = { | |
921 url: url_info | |
922 }; | |
923 } | |
924 if (!url_info.method) { | |
925 return url_info.method = 'get'; | |
926 } | |
927 }; | |
928 addLoadingClass(); | |
929 if (!url_info) { | |
930 url_info = this._getDataUrlInfo(parent_node); | |
931 } | |
932 parseUrlInfo(); | |
933 return $.ajax({ | |
934 url: url_info.url, | |
935 data: url_info.data, | |
936 type: url_info.method.toUpperCase(), | |
937 cache: false, | |
938 dataType: 'json', | |
939 success: function(response) { | |
940 var data; | |
941 if ($.isArray(response) || typeof response === 'object') { | |
942 data = response; | |
943 } else { | |
944 data = $.parseJSON(response); | |
945 } | |
946 removeLoadingClass(); | |
947 _this._loadData(data, parent_node); | |
948 if (on_finished && $.isFunction(on_finished)) { | |
949 return on_finished(); | |
950 } | |
951 }, | |
952 error: function(response) { | |
953 removeLoadingClass(); | |
954 if (_this.options.onLoadFailed) { | |
955 return _this.options.onLoadFailed(response); | |
956 } | |
957 } | |
958 }); | |
959 }; | |
960 | |
961 JqTreeWidget.prototype._loadData = function(data, parent_node) { | |
962 var n, selected_nodes_under_parent, _i, _len; | |
963 this._triggerEvent('tree.load_data', { | |
964 tree_data: data | |
965 }); | |
966 if (!parent_node) { | |
967 this._initTree(data); | |
968 } else { | |
969 selected_nodes_under_parent = this.select_node_handler.getSelectedNodes(
parent_node); | |
970 for (_i = 0, _len = selected_nodes_under_parent.length; _i < _len; _i++)
{ | |
971 n = selected_nodes_under_parent[_i]; | |
972 this.select_node_handler.removeFromSelection(n); | |
973 } | |
974 parent_node.loadFromData(data); | |
975 parent_node.load_on_demand = false; | |
976 this._refreshElements(parent_node.parent); | |
977 } | |
978 if (this.is_dragging) { | |
979 return this.dnd_handler.refreshHitAreas(); | |
980 } | |
981 }; | |
982 | |
983 JqTreeWidget.prototype.getNodeById = function(node_id) { | |
984 return this.tree.getNodeById(node_id); | |
985 }; | |
986 | |
987 JqTreeWidget.prototype.getNodeByName = function(name) { | |
988 return this.tree.getNodeByName(name); | |
989 }; | |
990 | |
991 JqTreeWidget.prototype.openNode = function(node, slide) { | |
992 if (slide == null) { | |
993 slide = true; | |
994 } | |
995 return this._openNode(node, slide); | |
996 }; | |
997 | |
998 JqTreeWidget.prototype._openNode = function(node, slide, on_finished) { | |
999 var doOpenNode, parent, | |
1000 _this = this; | |
1001 if (slide == null) { | |
1002 slide = true; | |
1003 } | |
1004 doOpenNode = function(_node, _slide, _on_finished) { | |
1005 var folder_element; | |
1006 folder_element = new FolderElement(_node, _this); | |
1007 return folder_element.open(_on_finished, _slide); | |
1008 }; | |
1009 if (node.isFolder()) { | |
1010 if (node.load_on_demand) { | |
1011 return this._loadFolderOnDemand(node, slide, on_finished); | |
1012 } else { | |
1013 parent = node.parent; | |
1014 while (parent && !parent.is_open) { | |
1015 if (parent.parent) { | |
1016 doOpenNode(parent, false, null); | |
1017 } | |
1018 parent = parent.parent; | |
1019 } | |
1020 doOpenNode(node, slide, on_finished); | |
1021 return this._saveState(); | |
1022 } | |
1023 } | |
1024 }; | |
1025 | |
1026 JqTreeWidget.prototype._loadFolderOnDemand = function(node, slide, on_finish
ed) { | |
1027 var _this = this; | |
1028 if (slide == null) { | |
1029 slide = true; | |
1030 } | |
1031 return this._loadDataFromUrl(null, node, function() { | |
1032 return _this._openNode(node, slide, on_finished); | |
1033 }); | |
1034 }; | |
1035 | |
1036 JqTreeWidget.prototype.closeNode = function(node, slide) { | |
1037 if (slide == null) { | |
1038 slide = true; | |
1039 } | |
1040 if (node.isFolder()) { | |
1041 new FolderElement(node, this).close(slide); | |
1042 return this._saveState(); | |
1043 } | |
1044 }; | |
1045 | |
1046 JqTreeWidget.prototype.isDragging = function() { | |
1047 return this.is_dragging; | |
1048 }; | |
1049 | |
1050 JqTreeWidget.prototype.refreshHitAreas = function() { | |
1051 return this.dnd_handler.refreshHitAreas(); | |
1052 }; | |
1053 | |
1054 JqTreeWidget.prototype.addNodeAfter = function(new_node_info, existing_node)
{ | |
1055 var new_node; | |
1056 new_node = existing_node.addAfter(new_node_info); | |
1057 this._refreshElements(existing_node.parent); | |
1058 return new_node; | |
1059 }; | |
1060 | |
1061 JqTreeWidget.prototype.addNodeBefore = function(new_node_info, existing_node
) { | |
1062 var new_node; | |
1063 new_node = existing_node.addBefore(new_node_info); | |
1064 this._refreshElements(existing_node.parent); | |
1065 return new_node; | |
1066 }; | |
1067 | |
1068 JqTreeWidget.prototype.addParentNode = function(new_node_info, existing_node
) { | |
1069 var new_node; | |
1070 new_node = existing_node.addParent(new_node_info); | |
1071 this._refreshElements(new_node.parent); | |
1072 return new_node; | |
1073 }; | |
1074 | |
1075 JqTreeWidget.prototype.removeNode = function(node) { | |
1076 var parent; | |
1077 parent = node.parent; | |
1078 if (parent) { | |
1079 this.select_node_handler.removeFromSelection(node, true); | |
1080 node.remove(); | |
1081 return this._refreshElements(parent.parent); | |
1082 } | |
1083 }; | |
1084 | |
1085 JqTreeWidget.prototype.appendNode = function(new_node_info, parent_node) { | |
1086 var is_already_root_node, node; | |
1087 if (!parent_node) { | |
1088 parent_node = this.tree; | |
1089 } | |
1090 is_already_root_node = parent_node.isFolder(); | |
1091 node = parent_node.append(new_node_info); | |
1092 if (is_already_root_node) { | |
1093 this._refreshElements(parent_node); | |
1094 } else { | |
1095 this._refreshElements(parent_node.parent); | |
1096 } | |
1097 return node; | |
1098 }; | |
1099 | |
1100 JqTreeWidget.prototype.prependNode = function(new_node_info, parent_node) { | |
1101 var node; | |
1102 if (!parent_node) { | |
1103 parent_node = this.tree; | |
1104 } | |
1105 node = parent_node.prepend(new_node_info); | |
1106 this._refreshElements(parent_node); | |
1107 return node; | |
1108 }; | |
1109 | |
1110 JqTreeWidget.prototype.updateNode = function(node, data) { | |
1111 var id_is_changed; | |
1112 id_is_changed = data.id && data.id !== node.id; | |
1113 if (id_is_changed) { | |
1114 this.tree.removeNodeFromIndex(node); | |
1115 } | |
1116 node.setData(data); | |
1117 if (id_is_changed) { | |
1118 this.tree.addNodeToIndex(node); | |
1119 } | |
1120 this._refreshElements(node.parent); | |
1121 return this._selectCurrentNode(); | |
1122 }; | |
1123 | |
1124 JqTreeWidget.prototype.moveNode = function(node, target_node, position) { | |
1125 var position_index; | |
1126 position_index = Position.nameToIndex(position); | |
1127 this.tree.moveNode(node, target_node, position_index); | |
1128 return this._refreshElements(); | |
1129 }; | |
1130 | |
1131 JqTreeWidget.prototype.getStateFromStorage = function() { | |
1132 return this.save_state_handler.getStateFromStorage(); | |
1133 }; | |
1134 | |
1135 JqTreeWidget.prototype.addToSelection = function(node) { | |
1136 this.select_node_handler.addToSelection(node); | |
1137 return this._getNodeElementForNode(node).select(); | |
1138 }; | |
1139 | |
1140 JqTreeWidget.prototype.getSelectedNodes = function() { | |
1141 return this.select_node_handler.getSelectedNodes(); | |
1142 }; | |
1143 | |
1144 JqTreeWidget.prototype.isNodeSelected = function(node) { | |
1145 return this.select_node_handler.isNodeSelected(node); | |
1146 }; | |
1147 | |
1148 JqTreeWidget.prototype.removeFromSelection = function(node) { | |
1149 this.select_node_handler.removeFromSelection(node); | |
1150 return this._getNodeElementForNode(node).deselect(); | |
1151 }; | |
1152 | |
1153 JqTreeWidget.prototype.scrollToNode = function(node) { | |
1154 var $element, top; | |
1155 $element = $(node.element); | |
1156 top = $element.offset().top - this.$el.offset().top; | |
1157 return this.scroll_handler.scrollTo(top); | |
1158 }; | |
1159 | |
1160 JqTreeWidget.prototype.getState = function() { | |
1161 return this.save_state_handler.getState(); | |
1162 }; | |
1163 | |
1164 JqTreeWidget.prototype.setState = function(state) { | |
1165 this.save_state_handler.setState(state); | |
1166 return this._refreshElements(); | |
1167 }; | |
1168 | |
1169 JqTreeWidget.prototype._init = function() { | |
1170 JqTreeWidget.__super__._init.call(this); | |
1171 this.element = this.$el; | |
1172 this.mouse_delay = 300; | |
1173 this.is_initialized = false; | |
1174 if (typeof SaveStateHandler !== "undefined" && SaveStateHandler !== null)
{ | |
1175 this.save_state_handler = new SaveStateHandler(this); | |
1176 } else { | |
1177 this.options.saveState = false; | |
1178 } | |
1179 if (typeof SelectNodeHandler !== "undefined" && SelectNodeHandler !== null
) { | |
1180 this.select_node_handler = new SelectNodeHandler(this); | |
1181 } | |
1182 if (typeof DragAndDropHandler !== "undefined" && DragAndDropHandler !== nu
ll) { | |
1183 this.dnd_handler = new DragAndDropHandler(this); | |
1184 } else { | |
1185 this.options.dragAndDrop = false; | |
1186 } | |
1187 if (typeof ScrollHandler !== "undefined" && ScrollHandler !== null) { | |
1188 this.scroll_handler = new ScrollHandler(this); | |
1189 } | |
1190 if ((typeof KeyHandler !== "undefined" && KeyHandler !== null) && (typeof
SelectNodeHandler !== "undefined" && SelectNodeHandler !== null)) { | |
1191 this.key_handler = new KeyHandler(this); | |
1192 } | |
1193 this._initData(); | |
1194 this.element.click($.proxy(this._click, this)); | |
1195 if (this.options.useContextMenu) { | |
1196 return this.element.bind('contextmenu', $.proxy(this._contextmenu, this)
); | |
1197 } | |
1198 }; | |
1199 | |
1200 JqTreeWidget.prototype._deinit = function() { | |
1201 this.element.empty(); | |
1202 this.element.unbind(); | |
1203 this.key_handler.deinit(); | |
1204 this.tree = null; | |
1205 return JqTreeWidget.__super__._deinit.call(this); | |
1206 }; | |
1207 | |
1208 JqTreeWidget.prototype._initData = function() { | |
1209 if (this.options.data) { | |
1210 return this._loadData(this.options.data); | |
1211 } else { | |
1212 return this._loadDataFromUrl(this._getDataUrlInfo()); | |
1213 } | |
1214 }; | |
1215 | |
1216 JqTreeWidget.prototype._getDataUrlInfo = function(node) { | |
1217 var data, data_url, url_info; | |
1218 data_url = this.options.dataUrl || this.element.data('url'); | |
1219 if ($.isFunction(data_url)) { | |
1220 return data_url(node); | |
1221 } else if ($.type(data_url) === 'string') { | |
1222 url_info = { | |
1223 url: data_url | |
1224 }; | |
1225 if (node && node.id) { | |
1226 data = { | |
1227 node: node.id | |
1228 }; | |
1229 url_info['data'] = data; | |
1230 } | |
1231 return url_info; | |
1232 } else { | |
1233 return data_url; | |
1234 } | |
1235 }; | |
1236 | |
1237 JqTreeWidget.prototype._initTree = function(data) { | |
1238 this.tree = new this.options.nodeClass(null, true, this.options.nodeClass)
; | |
1239 if (this.select_node_handler) { | |
1240 this.select_node_handler.clear(); | |
1241 } | |
1242 this.tree.loadFromData(data); | |
1243 this._openNodes(); | |
1244 this._refreshElements(); | |
1245 if (!this.is_initialized) { | |
1246 this.is_initialized = true; | |
1247 return this._triggerEvent('tree.init'); | |
1248 } | |
1249 }; | |
1250 | |
1251 JqTreeWidget.prototype._openNodes = function() { | |
1252 var max_level; | |
1253 if (this.options.saveState) { | |
1254 if (this.save_state_handler.restoreState()) { | |
1255 return; | |
1256 } | |
1257 } | |
1258 if (this.options.autoOpen === false) { | |
1259 return; | |
1260 } else if (this.options.autoOpen === true) { | |
1261 max_level = -1; | |
1262 } else { | |
1263 max_level = parseInt(this.options.autoOpen); | |
1264 } | |
1265 return this.tree.iterate(function(node, level) { | |
1266 if (node.hasChildren()) { | |
1267 node.is_open = true; | |
1268 } | |
1269 return level !== max_level; | |
1270 }); | |
1271 }; | |
1272 | |
1273 JqTreeWidget.prototype._refreshElements = function(from_node) { | |
1274 var $element, createFolderLi, createLi, createNodeLi, createUl, doCreateDo
mElements, escapeIfNecessary, is_root_node, node_element, | |
1275 _this = this; | |
1276 if (from_node == null) { | |
1277 from_node = null; | |
1278 } | |
1279 escapeIfNecessary = function(value) { | |
1280 if (_this.options.autoEscape) { | |
1281 return html_escape(value); | |
1282 } else { | |
1283 return value; | |
1284 } | |
1285 }; | |
1286 createUl = function(is_root_node) { | |
1287 var class_string; | |
1288 if (is_root_node) { | |
1289 class_string = 'jqtree-tree'; | |
1290 } else { | |
1291 class_string = ''; | |
1292 } | |
1293 return $("<ul class=\"jqtree_common " + class_string + "\"></ul>"); | |
1294 }; | |
1295 createLi = function(node) { | |
1296 var $li; | |
1297 if (node.isFolder()) { | |
1298 $li = createFolderLi(node); | |
1299 } else { | |
1300 $li = createNodeLi(node); | |
1301 } | |
1302 if (_this.options.onCreateLi) { | |
1303 _this.options.onCreateLi(node, $li); | |
1304 } | |
1305 return $li; | |
1306 }; | |
1307 createNodeLi = function(node) { | |
1308 var class_string, escaped_name, li_classes; | |
1309 li_classes = ['jqtree_common']; | |
1310 if (_this.select_node_handler && _this.select_node_handler.isNodeSelecte
d(node)) { | |
1311 li_classes.push('jqtree-selected'); | |
1312 } | |
1313 class_string = li_classes.join(' '); | |
1314 escaped_name = escapeIfNecessary(node.name); | |
1315 return $("<li class=\"" + class_string + "\"><div class=\"jqtree-element
jqtree_common\"><span class=\"jqtree-title jqtree_common\">" + escaped_name + "
</span></div></li>"); | |
1316 }; | |
1317 createFolderLi = function(node) { | |
1318 var button_char, button_classes, escaped_name, folder_classes, getButton
Classes, getFolderClasses; | |
1319 getButtonClasses = function() { | |
1320 var classes; | |
1321 classes = ['jqtree-toggler']; | |
1322 if (!node.is_open) { | |
1323 classes.push('jqtree-closed'); | |
1324 } | |
1325 return classes.join(' '); | |
1326 }; | |
1327 getFolderClasses = function() { | |
1328 var classes; | |
1329 classes = ['jqtree-folder']; | |
1330 if (!node.is_open) { | |
1331 classes.push('jqtree-closed'); | |
1332 } | |
1333 if (_this.select_node_handler && _this.select_node_handler.isNodeSelec
ted(node)) { | |
1334 classes.push('jqtree-selected'); | |
1335 } | |
1336 return classes.join(' '); | |
1337 }; | |
1338 button_classes = getButtonClasses(); | |
1339 folder_classes = getFolderClasses(); | |
1340 escaped_name = escapeIfNecessary(node.name); | |
1341 if (node.is_open) { | |
1342 button_char = _this.options.openedIcon; | |
1343 } else { | |
1344 button_char = _this.options.closedIcon; | |
1345 } | |
1346 return $("<li class=\"jqtree_common " + folder_classes + "\"><div class=
\"jqtree-element jqtree_common\"><a class=\"jqtree_common " + button_classes + "
\">" + button_char + "</a><span class=\"jqtree_common jqtree-title\">" + escaped
_name + "</span></div></li>"); | |
1347 }; | |
1348 doCreateDomElements = function($element, children, is_root_node, is_open)
{ | |
1349 var $li, $ul, child, _i, _len; | |
1350 $ul = createUl(is_root_node); | |
1351 $element.append($ul); | |
1352 for (_i = 0, _len = children.length; _i < _len; _i++) { | |
1353 child = children[_i]; | |
1354 $li = createLi(child); | |
1355 $ul.append($li); | |
1356 child.element = $li[0]; | |
1357 $li.data('node', child); | |
1358 if (child.hasChildren()) { | |
1359 doCreateDomElements($li, child.children, false, child.is_open); | |
1360 } | |
1361 } | |
1362 return null; | |
1363 }; | |
1364 if (from_node && from_node.parent) { | |
1365 is_root_node = false; | |
1366 node_element = this._getNodeElementForNode(from_node); | |
1367 node_element.getUl().remove(); | |
1368 $element = node_element.$element; | |
1369 } else { | |
1370 from_node = this.tree; | |
1371 $element = this.element; | |
1372 $element.empty(); | |
1373 is_root_node = true; | |
1374 } | |
1375 doCreateDomElements($element, from_node.children, is_root_node, is_root_no
de); | |
1376 return this._triggerEvent('tree.refresh'); | |
1377 }; | |
1378 | |
1379 JqTreeWidget.prototype._click = function(e) { | |
1380 var $button, $el, $target, event, node; | |
1381 $target = $(e.target); | |
1382 $button = $target.closest('.jqtree-toggler'); | |
1383 if ($button.length) { | |
1384 node = this._getNode($button); | |
1385 if (node) { | |
1386 this.toggle(node, this.options.slide); | |
1387 e.preventDefault(); | |
1388 return e.stopPropagation(); | |
1389 } | |
1390 } else { | |
1391 $el = $target.closest('.jqtree-element'); | |
1392 if ($el.length) { | |
1393 node = this._getNode($el); | |
1394 if (node) { | |
1395 event = this._triggerEvent('tree.click', { | |
1396 node: node | |
1397 }); | |
1398 if (!event.isDefaultPrevented()) { | |
1399 return this._selectNode(node, true); | |
1400 } | |
1401 } | |
1402 } | |
1403 } | |
1404 }; | |
1405 | |
1406 JqTreeWidget.prototype._getNode = function($element) { | |
1407 var $li; | |
1408 $li = $element.closest('li'); | |
1409 if ($li.length === 0) { | |
1410 return null; | |
1411 } else { | |
1412 return $li.data('node'); | |
1413 } | |
1414 }; | |
1415 | |
1416 JqTreeWidget.prototype._getNodeElementForNode = function(node) { | |
1417 if (node.isFolder()) { | |
1418 return new FolderElement(node, this); | |
1419 } else { | |
1420 return new NodeElement(node, this); | |
1421 } | |
1422 }; | |
1423 | |
1424 JqTreeWidget.prototype._getNodeElement = function($element) { | |
1425 var node; | |
1426 node = this._getNode($element); | |
1427 if (node) { | |
1428 return this._getNodeElementForNode(node); | |
1429 } else { | |
1430 return null; | |
1431 } | |
1432 }; | |
1433 | |
1434 JqTreeWidget.prototype._contextmenu = function(e) { | |
1435 var $div, node; | |
1436 $div = $(e.target).closest('ul.jqtree-tree .jqtree-element'); | |
1437 if ($div.length) { | |
1438 node = this._getNode($div); | |
1439 if (node) { | |
1440 e.preventDefault(); | |
1441 e.stopPropagation(); | |
1442 this._triggerEvent('tree.contextmenu', { | |
1443 node: node, | |
1444 click_event: e | |
1445 }); | |
1446 return false; | |
1447 } | |
1448 } | |
1449 }; | |
1450 | |
1451 JqTreeWidget.prototype._saveState = function() { | |
1452 if (this.options.saveState) { | |
1453 return this.save_state_handler.saveState(); | |
1454 } | |
1455 }; | |
1456 | |
1457 JqTreeWidget.prototype._mouseCapture = function(position_info) { | |
1458 if (this.options.dragAndDrop) { | |
1459 return this.dnd_handler.mouseCapture(position_info); | |
1460 } else { | |
1461 return false; | |
1462 } | |
1463 }; | |
1464 | |
1465 JqTreeWidget.prototype._mouseStart = function(position_info) { | |
1466 if (this.options.dragAndDrop) { | |
1467 return this.dnd_handler.mouseStart(position_info); | |
1468 } else { | |
1469 return false; | |
1470 } | |
1471 }; | |
1472 | |
1473 JqTreeWidget.prototype._mouseDrag = function(position_info) { | |
1474 var result; | |
1475 if (this.options.dragAndDrop) { | |
1476 result = this.dnd_handler.mouseDrag(position_info); | |
1477 if (this.scroll_handler) { | |
1478 this.scroll_handler.checkScrolling(); | |
1479 } | |
1480 return result; | |
1481 } else { | |
1482 return false; | |
1483 } | |
1484 }; | |
1485 | |
1486 JqTreeWidget.prototype._mouseStop = function(position_info) { | |
1487 if (this.options.dragAndDrop) { | |
1488 return this.dnd_handler.mouseStop(position_info); | |
1489 } else { | |
1490 return false; | |
1491 } | |
1492 }; | |
1493 | |
1494 JqTreeWidget.prototype._triggerEvent = function(event_name, values) { | |
1495 var event; | |
1496 event = $.Event(event_name); | |
1497 $.extend(event, values); | |
1498 this.element.trigger(event); | |
1499 return event; | |
1500 }; | |
1501 | |
1502 JqTreeWidget.prototype.testGenerateHitAreas = function(moving_node) { | |
1503 this.dnd_handler.current_item = this._getNodeElementForNode(moving_node); | |
1504 this.dnd_handler.generateHitAreas(); | |
1505 return this.dnd_handler.hit_areas; | |
1506 }; | |
1507 | |
1508 JqTreeWidget.prototype._selectCurrentNode = function() { | |
1509 var node, node_element; | |
1510 node = this.getSelectedNode(); | |
1511 if (node) { | |
1512 node_element = this._getNodeElementForNode(node); | |
1513 if (node_element) { | |
1514 return node_element.select(); | |
1515 } | |
1516 } | |
1517 }; | |
1518 | |
1519 JqTreeWidget.prototype._deselectCurrentNode = function() { | |
1520 var node; | |
1521 node = this.getSelectedNode(); | |
1522 if (node) { | |
1523 return this.removeFromSelection(node); | |
1524 } | |
1525 }; | |
1526 | |
1527 return JqTreeWidget; | |
1528 | |
1529 })(MouseWidget); | |
1530 | |
1531 SimpleWidget.register(JqTreeWidget, 'tree'); | |
1532 | |
1533 NodeElement = (function() { | |
1534 function NodeElement(node, tree_widget) { | |
1535 this.init(node, tree_widget); | |
1536 } | |
1537 | |
1538 NodeElement.prototype.init = function(node, tree_widget) { | |
1539 this.node = node; | |
1540 this.tree_widget = tree_widget; | |
1541 return this.$element = $(node.element); | |
1542 }; | |
1543 | |
1544 NodeElement.prototype.getUl = function() { | |
1545 return this.$element.children('ul:first'); | |
1546 }; | |
1547 | |
1548 NodeElement.prototype.getSpan = function() { | |
1549 return this.$element.children('.jqtree-element').find('span.jqtree-title')
; | |
1550 }; | |
1551 | |
1552 NodeElement.prototype.getLi = function() { | |
1553 return this.$element; | |
1554 }; | |
1555 | |
1556 NodeElement.prototype.addDropHint = function(position) { | |
1557 if (position === Position.INSIDE) { | |
1558 return new BorderDropHint(this.$element); | |
1559 } else { | |
1560 return new GhostDropHint(this.node, this.$element, position); | |
1561 } | |
1562 }; | |
1563 | |
1564 NodeElement.prototype.select = function() { | |
1565 return this.getLi().addClass('jqtree-selected'); | |
1566 }; | |
1567 | |
1568 NodeElement.prototype.deselect = function() { | |
1569 return this.getLi().removeClass('jqtree-selected'); | |
1570 }; | |
1571 | |
1572 return NodeElement; | |
1573 | |
1574 })(); | |
1575 | |
1576 FolderElement = (function(_super) { | |
1577 __extends(FolderElement, _super); | |
1578 | |
1579 function FolderElement() { | |
1580 _ref2 = FolderElement.__super__.constructor.apply(this, arguments); | |
1581 return _ref2; | |
1582 } | |
1583 | |
1584 FolderElement.prototype.open = function(on_finished, slide) { | |
1585 var $button, doOpen, | |
1586 _this = this; | |
1587 if (slide == null) { | |
1588 slide = true; | |
1589 } | |
1590 if (!this.node.is_open) { | |
1591 this.node.is_open = true; | |
1592 $button = this.getButton(); | |
1593 $button.removeClass('jqtree-closed'); | |
1594 $button.html(this.tree_widget.options.openedIcon); | |
1595 doOpen = function() { | |
1596 _this.getLi().removeClass('jqtree-closed'); | |
1597 if (on_finished) { | |
1598 on_finished(); | |
1599 } | |
1600 return _this.tree_widget._triggerEvent('tree.open', { | |
1601 node: _this.node | |
1602 }); | |
1603 }; | |
1604 if (slide) { | |
1605 return this.getUl().slideDown('fast', doOpen); | |
1606 } else { | |
1607 this.getUl().show(); | |
1608 return doOpen(); | |
1609 } | |
1610 } | |
1611 }; | |
1612 | |
1613 FolderElement.prototype.close = function(slide) { | |
1614 var $button, doClose, | |
1615 _this = this; | |
1616 if (slide == null) { | |
1617 slide = true; | |
1618 } | |
1619 if (this.node.is_open) { | |
1620 this.node.is_open = false; | |
1621 $button = this.getButton(); | |
1622 $button.addClass('jqtree-closed'); | |
1623 $button.html(this.tree_widget.options.closedIcon); | |
1624 doClose = function() { | |
1625 _this.getLi().addClass('jqtree-closed'); | |
1626 return _this.tree_widget._triggerEvent('tree.close', { | |
1627 node: _this.node | |
1628 }); | |
1629 }; | |
1630 if (slide) { | |
1631 return this.getUl().slideUp('fast', doClose); | |
1632 } else { | |
1633 this.getUl().hide(); | |
1634 return doClose(); | |
1635 } | |
1636 } | |
1637 }; | |
1638 | |
1639 FolderElement.prototype.getButton = function() { | |
1640 return this.$element.children('.jqtree-element').find('a.jqtree-toggler'); | |
1641 }; | |
1642 | |
1643 FolderElement.prototype.addDropHint = function(position) { | |
1644 if (!this.node.is_open && position === Position.INSIDE) { | |
1645 return new BorderDropHint(this.$element); | |
1646 } else { | |
1647 return new GhostDropHint(this.node, this.$element, position); | |
1648 } | |
1649 }; | |
1650 | |
1651 return FolderElement; | |
1652 | |
1653 })(NodeElement); | |
1654 | |
1655 html_escape = function(string) { | |
1656 return ('' + string).replace(/&/g, '&').replace(/</g, '<').replace(/>
/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '
F;'); | |
1657 }; | |
1658 | |
1659 _indexOf = function(array, item) { | |
1660 var i, value, _i, _len; | |
1661 for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) { | |
1662 value = array[i]; | |
1663 if (value === item) { | |
1664 return i; | |
1665 } | |
1666 } | |
1667 return -1; | |
1668 }; | |
1669 | |
1670 indexOf = function(array, item) { | |
1671 if (array.indexOf) { | |
1672 return array.indexOf(item); | |
1673 } else { | |
1674 return _indexOf(array, item); | |
1675 } | |
1676 }; | |
1677 | |
1678 this.Tree.indexOf = indexOf; | |
1679 | |
1680 this.Tree._indexOf = _indexOf; | |
1681 | |
1682 if (!((this.JSON != null) && (this.JSON.stringify != null) && typeof this.JSON
.stringify === 'function')) { | |
1683 json_escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17
b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; | |
1684 json_meta = { | |
1685 '\b': '\\b', | |
1686 '\t': '\\t', | |
1687 '\n': '\\n', | |
1688 '\f': '\\f', | |
1689 '\r': '\\r', | |
1690 '"': '\\"', | |
1691 '\\': '\\\\' | |
1692 }; | |
1693 json_quote = function(string) { | |
1694 json_escapable.lastIndex = 0; | |
1695 if (json_escapable.test(string)) { | |
1696 return '"' + string.replace(json_escapable, function(a) { | |
1697 var c; | |
1698 c = json_meta[a]; | |
1699 return (typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).
toString(16)).slice(-4)); | |
1700 }) + '"'; | |
1701 } else { | |
1702 return '"' + string + '"'; | |
1703 } | |
1704 }; | |
1705 json_str = function(key, holder) { | |
1706 var i, k, partial, v, value, _i, _len; | |
1707 value = holder[key]; | |
1708 switch (typeof value) { | |
1709 case 'string': | |
1710 return json_quote(value); | |
1711 case 'number': | |
1712 if (isFinite(value)) { | |
1713 return String(value); | |
1714 } else { | |
1715 return 'null'; | |
1716 } | |
1717 case 'boolean': | |
1718 case 'null': | |
1719 return String(value); | |
1720 case 'object': | |
1721 if (!value) { | |
1722 return 'null'; | |
1723 } | |
1724 partial = []; | |
1725 if (Object.prototype.toString.apply(value) === '[object Array]') { | |
1726 for (i = _i = 0, _len = value.length; _i < _len; i = ++_i) { | |
1727 v = value[i]; | |
1728 partial[i] = json_str(i, value) || 'null'; | |
1729 } | |
1730 return (partial.length === 0 ? '[]' : '[' + partial.join(',') + ']')
; | |
1731 } | |
1732 for (k in value) { | |
1733 if (Object.prototype.hasOwnProperty.call(value, k)) { | |
1734 v = json_str(k, value); | |
1735 if (v) { | |
1736 partial.push(json_quote(k) + ':' + v); | |
1737 } | |
1738 } | |
1739 } | |
1740 return (partial.length === 0 ? '{}' : '{' + partial.join(',') + '}'); | |
1741 } | |
1742 }; | |
1743 if (this.JSON == null) { | |
1744 this.JSON = {}; | |
1745 } | |
1746 this.JSON.stringify = function(value) { | |
1747 return json_str('', { | |
1748 '': value | |
1749 }); | |
1750 }; | |
1751 } | |
1752 | |
1753 SaveStateHandler = (function() { | |
1754 function SaveStateHandler(tree_widget) { | |
1755 this.tree_widget = tree_widget; | |
1756 } | |
1757 | |
1758 SaveStateHandler.prototype.saveState = function() { | |
1759 var state; | |
1760 state = JSON.stringify(this.getState()); | |
1761 if (this.tree_widget.options.onSetStateFromStorage) { | |
1762 return this.tree_widget.options.onSetStateFromStorage(state); | |
1763 } else if (typeof localStorage !== "undefined" && localStorage !== null) { | |
1764 return localStorage.setItem(this.getCookieName(), state); | |
1765 } else if ($.cookie) { | |
1766 $.cookie.raw = true; | |
1767 return $.cookie(this.getCookieName(), state, { | |
1768 path: '/' | |
1769 }); | |
1770 } | |
1771 }; | |
1772 | |
1773 SaveStateHandler.prototype.restoreState = function() { | |
1774 var state; | |
1775 state = this.getStateFromStorage(); | |
1776 if (state) { | |
1777 this.setState($.parseJSON(state)); | |
1778 return true; | |
1779 } else { | |
1780 return false; | |
1781 } | |
1782 }; | |
1783 | |
1784 SaveStateHandler.prototype.getStateFromStorage = function() { | |
1785 if (this.tree_widget.options.onGetStateFromStorage) { | |
1786 return this.tree_widget.options.onGetStateFromStorage(); | |
1787 } else if (typeof localStorage !== "undefined" && localStorage !== null) { | |
1788 return localStorage.getItem(this.getCookieName()); | |
1789 } else if ($.cookie) { | |
1790 $.cookie.raw = true; | |
1791 return $.cookie(this.getCookieName()); | |
1792 } else { | |
1793 return null; | |
1794 } | |
1795 }; | |
1796 | |
1797 SaveStateHandler.prototype.getState = function() { | |
1798 var open_nodes, selected_node, selected_node_id, | |
1799 _this = this; | |
1800 open_nodes = []; | |
1801 this.tree_widget.tree.iterate(function(node) { | |
1802 if (node.is_open && node.id && node.hasChildren()) { | |
1803 open_nodes.push(node.id); | |
1804 } | |
1805 return true; | |
1806 }); | |
1807 selected_node = this.tree_widget.getSelectedNode(); | |
1808 if (selected_node) { | |
1809 selected_node_id = selected_node.id; | |
1810 } else { | |
1811 selected_node_id = ''; | |
1812 } | |
1813 return { | |
1814 open_nodes: open_nodes, | |
1815 selected_node: selected_node_id | |
1816 }; | |
1817 }; | |
1818 | |
1819 SaveStateHandler.prototype.setState = function(state) { | |
1820 var open_nodes, selected_node, selected_node_id, | |
1821 _this = this; | |
1822 if (state) { | |
1823 open_nodes = state.open_nodes; | |
1824 selected_node_id = state.selected_node; | |
1825 this.tree_widget.tree.iterate(function(node) { | |
1826 node.is_open = node.id && node.hasChildren() && (indexOf(open_nodes, n
ode.id) >= 0); | |
1827 return true; | |
1828 }); | |
1829 if (selected_node_id && this.tree_widget.select_node_handler) { | |
1830 this.tree_widget.select_node_handler.clear(); | |
1831 selected_node = this.tree_widget.getNodeById(selected_node_id); | |
1832 if (selected_node) { | |
1833 return this.tree_widget.select_node_handler.addToSelection(selected_
node); | |
1834 } | |
1835 } | |
1836 } | |
1837 }; | |
1838 | |
1839 SaveStateHandler.prototype.getCookieName = function() { | |
1840 if (typeof this.tree_widget.options.saveState === 'string') { | |
1841 return this.tree_widget.options.saveState; | |
1842 } else { | |
1843 return 'tree'; | |
1844 } | |
1845 }; | |
1846 | |
1847 return SaveStateHandler; | |
1848 | |
1849 })(); | |
1850 | |
1851 SelectNodeHandler = (function() { | |
1852 function SelectNodeHandler(tree_widget) { | |
1853 this.tree_widget = tree_widget; | |
1854 this.clear(); | |
1855 } | |
1856 | |
1857 SelectNodeHandler.prototype.getSelectedNode = function() { | |
1858 var selected_nodes; | |
1859 selected_nodes = this.getSelectedNodes(); | |
1860 if (selected_nodes.length) { | |
1861 return selected_nodes[0]; | |
1862 } else { | |
1863 return false; | |
1864 } | |
1865 }; | |
1866 | |
1867 SelectNodeHandler.prototype.getSelectedNodes = function() { | |
1868 var id, node, selected_nodes; | |
1869 if (this.selected_single_node) { | |
1870 return [this.selected_single_node]; | |
1871 } else { | |
1872 selected_nodes = []; | |
1873 for (id in this.selected_nodes) { | |
1874 node = this.tree_widget.getNodeById(id); | |
1875 if (node) { | |
1876 selected_nodes.push(node); | |
1877 } | |
1878 } | |
1879 return selected_nodes; | |
1880 } | |
1881 }; | |
1882 | |
1883 SelectNodeHandler.prototype.isNodeSelected = function(node) { | |
1884 if (node.id) { | |
1885 return this.selected_nodes[node.id]; | |
1886 } else if (this.selected_single_node) { | |
1887 return this.selected_single_node.element === node.element; | |
1888 } else { | |
1889 return false; | |
1890 } | |
1891 }; | |
1892 | |
1893 SelectNodeHandler.prototype.clear = function() { | |
1894 this.selected_nodes = {}; | |
1895 return this.selected_single_node = null; | |
1896 }; | |
1897 | |
1898 SelectNodeHandler.prototype.removeFromSelection = function(node, include_chi
ldren) { | |
1899 var _this = this; | |
1900 if (include_children == null) { | |
1901 include_children = false; | |
1902 } | |
1903 if (!node.id) { | |
1904 if (node.element === this.selected_single_node.element) { | |
1905 return this.selected_single_node = null; | |
1906 } | |
1907 } else { | |
1908 delete this.selected_nodes[node.id]; | |
1909 if (include_children) { | |
1910 return node.iterate(function(n) { | |
1911 delete _this.selected_nodes[node.id]; | |
1912 return true; | |
1913 }); | |
1914 } | |
1915 } | |
1916 }; | |
1917 | |
1918 SelectNodeHandler.prototype.addToSelection = function(node) { | |
1919 if (node.id) { | |
1920 return this.selected_nodes[node.id] = true; | |
1921 } else { | |
1922 return this.selected_single_node = node; | |
1923 } | |
1924 }; | |
1925 | |
1926 return SelectNodeHandler; | |
1927 | |
1928 })(); | |
1929 | |
1930 DragAndDropHandler = (function() { | |
1931 function DragAndDropHandler(tree_widget) { | |
1932 this.tree_widget = tree_widget; | |
1933 this.hovered_area = null; | |
1934 this.$ghost = null; | |
1935 this.hit_areas = []; | |
1936 this.is_dragging = false; | |
1937 } | |
1938 | |
1939 DragAndDropHandler.prototype.mouseCapture = function(position_info) { | |
1940 var $element, node_element; | |
1941 $element = $(position_info.target); | |
1942 if (this.tree_widget.options.onIsMoveHandle && !this.tree_widget.options.o
nIsMoveHandle($element)) { | |
1943 return null; | |
1944 } | |
1945 node_element = this.tree_widget._getNodeElement($element); | |
1946 if (node_element && this.tree_widget.options.onCanMove) { | |
1947 if (!this.tree_widget.options.onCanMove(node_element.node)) { | |
1948 node_element = null; | |
1949 } | |
1950 } | |
1951 this.current_item = node_element; | |
1952 return this.current_item !== null; | |
1953 }; | |
1954 | |
1955 DragAndDropHandler.prototype.mouseStart = function(position_info) { | |
1956 var offset; | |
1957 this.refreshHitAreas(); | |
1958 offset = $(position_info.target).offset(); | |
1959 this.drag_element = new DragElement(this.current_item.node, position_info.
page_x - offset.left, position_info.page_y - offset.top, this.tree_widget.elemen
t); | |
1960 this.is_dragging = true; | |
1961 this.current_item.$element.addClass('jqtree-moving'); | |
1962 return true; | |
1963 }; | |
1964 | |
1965 DragAndDropHandler.prototype.mouseDrag = function(position_info) { | |
1966 var area, can_move_to; | |
1967 this.drag_element.move(position_info.page_x, position_info.page_y); | |
1968 area = this.findHoveredArea(position_info.page_x, position_info.page_y); | |
1969 can_move_to = this.canMoveToArea(area); | |
1970 if (area) { | |
1971 if (this.hovered_area !== area) { | |
1972 this.hovered_area = area; | |
1973 if (this.mustOpenFolderTimer(area)) { | |
1974 this.startOpenFolderTimer(area.node); | |
1975 } | |
1976 if (can_move_to) { | |
1977 this.updateDropHint(); | |
1978 } | |
1979 } | |
1980 } else { | |
1981 this.removeHover(); | |
1982 this.removeDropHint(); | |
1983 this.stopOpenFolderTimer(); | |
1984 } | |
1985 return true; | |
1986 }; | |
1987 | |
1988 DragAndDropHandler.prototype.canMoveToArea = function(area) { | |
1989 var position_name; | |
1990 if (!area) { | |
1991 return false; | |
1992 } else if (this.tree_widget.options.onCanMoveTo) { | |
1993 position_name = Position.getName(area.position); | |
1994 return this.tree_widget.options.onCanMoveTo(this.current_item.node, area
.node, position_name); | |
1995 } else { | |
1996 return true; | |
1997 } | |
1998 }; | |
1999 | |
2000 DragAndDropHandler.prototype.mouseStop = function(position_info) { | |
2001 this.moveItem(position_info); | |
2002 this.clear(); | |
2003 this.removeHover(); | |
2004 this.removeDropHint(); | |
2005 this.removeHitAreas(); | |
2006 if (this.current_item) { | |
2007 this.current_item.$element.removeClass('jqtree-moving'); | |
2008 } | |
2009 this.is_dragging = false; | |
2010 return false; | |
2011 }; | |
2012 | |
2013 DragAndDropHandler.prototype.refreshHitAreas = function() { | |
2014 this.removeHitAreas(); | |
2015 return this.generateHitAreas(); | |
2016 }; | |
2017 | |
2018 DragAndDropHandler.prototype.removeHitAreas = function() { | |
2019 return this.hit_areas = []; | |
2020 }; | |
2021 | |
2022 DragAndDropHandler.prototype.clear = function() { | |
2023 this.drag_element.remove(); | |
2024 return this.drag_element = null; | |
2025 }; | |
2026 | |
2027 DragAndDropHandler.prototype.removeDropHint = function() { | |
2028 if (this.previous_ghost) { | |
2029 return this.previous_ghost.remove(); | |
2030 } | |
2031 }; | |
2032 | |
2033 DragAndDropHandler.prototype.removeHover = function() { | |
2034 return this.hovered_area = null; | |
2035 }; | |
2036 | |
2037 DragAndDropHandler.prototype.generateHitAreas = function() { | |
2038 var addPosition, getTop, groupPositions, handleAfterOpenFolder, handleClos
edFolder, handleFirstNode, handleNode, handleOpenFolder, hit_areas, last_top, po
sitions, | |
2039 _this = this; | |
2040 positions = []; | |
2041 last_top = 0; | |
2042 getTop = function($element) { | |
2043 return $element.offset().top; | |
2044 }; | |
2045 addPosition = function(node, position, top) { | |
2046 positions.push({ | |
2047 top: top, | |
2048 node: node, | |
2049 position: position | |
2050 }); | |
2051 return last_top = top; | |
2052 }; | |
2053 groupPositions = function(handle_group) { | |
2054 var group, position, previous_top, _i, _len; | |
2055 previous_top = -1; | |
2056 group = []; | |
2057 for (_i = 0, _len = positions.length; _i < _len; _i++) { | |
2058 position = positions[_i]; | |
2059 if (position.top !== previous_top) { | |
2060 if (group.length) { | |
2061 handle_group(group, previous_top, position.top); | |
2062 } | |
2063 previous_top = position.top; | |
2064 group = []; | |
2065 } | |
2066 group.push(position); | |
2067 } | |
2068 return handle_group(group, previous_top, _this.tree_widget.element.offse
t().top + _this.tree_widget.element.height()); | |
2069 }; | |
2070 handleNode = function(node, next_node, $element) { | |
2071 var top; | |
2072 top = getTop($element); | |
2073 if (node === _this.current_item.node) { | |
2074 addPosition(node, Position.NONE, top); | |
2075 } else { | |
2076 addPosition(node, Position.INSIDE, top); | |
2077 } | |
2078 if (next_node === _this.current_item.node || node === _this.current_item
.node) { | |
2079 return addPosition(node, Position.NONE, top); | |
2080 } else { | |
2081 return addPosition(node, Position.AFTER, top); | |
2082 } | |
2083 }; | |
2084 handleOpenFolder = function(node, $element) { | |
2085 if (node === _this.current_item.node) { | |
2086 return false; | |
2087 } | |
2088 if (node.children[0] !== _this.current_item.node) { | |
2089 addPosition(node, Position.INSIDE, getTop($element)); | |
2090 } | |
2091 return true; | |
2092 }; | |
2093 handleAfterOpenFolder = function(node, next_node, $element) { | |
2094 if (node === _this.current_item.node || next_node === _this.current_item
.node) { | |
2095 return addPosition(node, Position.NONE, last_top); | |
2096 } else { | |
2097 return addPosition(node, Position.AFTER, last_top); | |
2098 } | |
2099 }; | |
2100 handleClosedFolder = function(node, next_node, $element) { | |
2101 var top; | |
2102 top = getTop($element); | |
2103 if (node === _this.current_item.node) { | |
2104 return addPosition(node, Position.NONE, top); | |
2105 } else { | |
2106 addPosition(node, Position.INSIDE, top); | |
2107 if (next_node !== _this.current_item.node) { | |
2108 return addPosition(node, Position.AFTER, top); | |
2109 } | |
2110 } | |
2111 }; | |
2112 handleFirstNode = function(node, $element) { | |
2113 if (node !== _this.current_item.node) { | |
2114 return addPosition(node, Position.BEFORE, getTop($(node.element))); | |
2115 } | |
2116 }; | |
2117 this.iterateVisibleNodes(handleNode, handleOpenFolder, handleClosedFolder,
handleAfterOpenFolder, handleFirstNode); | |
2118 hit_areas = []; | |
2119 groupPositions(function(positions_in_group, top, bottom) { | |
2120 var area_height, area_top, position, _i, _len; | |
2121 area_height = (bottom - top) / positions_in_group.length; | |
2122 area_top = top; | |
2123 for (_i = 0, _len = positions_in_group.length; _i < _len; _i++) { | |
2124 position = positions_in_group[_i]; | |
2125 hit_areas.push({ | |
2126 top: area_top, | |
2127 bottom: area_top + area_height, | |
2128 node: position.node, | |
2129 position: position.position | |
2130 }); | |
2131 area_top += area_height; | |
2132 } | |
2133 return null; | |
2134 }); | |
2135 return this.hit_areas = hit_areas; | |
2136 }; | |
2137 | |
2138 DragAndDropHandler.prototype.iterateVisibleNodes = function(handle_node, han
dle_open_folder, handle_closed_folder, handle_after_open_folder, handle_first_no
de) { | |
2139 var is_first_node, iterate, | |
2140 _this = this; | |
2141 is_first_node = true; | |
2142 iterate = function(node, next_node) { | |
2143 var $element, child, children_length, i, must_iterate_inside, _i, _len,
_ref3; | |
2144 must_iterate_inside = (node.is_open || !node.element) && node.hasChildre
n(); | |
2145 if (node.element) { | |
2146 $element = $(node.element); | |
2147 if (!$element.is(':visible')) { | |
2148 return; | |
2149 } | |
2150 if (is_first_node) { | |
2151 handle_first_node(node, $element); | |
2152 is_first_node = false; | |
2153 } | |
2154 if (!node.hasChildren()) { | |
2155 handle_node(node, next_node, $element); | |
2156 } else if (node.is_open) { | |
2157 if (!handle_open_folder(node, $element)) { | |
2158 must_iterate_inside = false; | |
2159 } | |
2160 } else { | |
2161 handle_closed_folder(node, next_node, $element); | |
2162 } | |
2163 } | |
2164 if (must_iterate_inside) { | |
2165 children_length = node.children.length; | |
2166 _ref3 = node.children; | |
2167 for (i = _i = 0, _len = _ref3.length; _i < _len; i = ++_i) { | |
2168 child = _ref3[i]; | |
2169 if (i === (children_length - 1)) { | |
2170 iterate(node.children[i], null); | |
2171 } else { | |
2172 iterate(node.children[i], node.children[i + 1]); | |
2173 } | |
2174 } | |
2175 if (node.is_open) { | |
2176 return handle_after_open_folder(node, next_node, $element); | |
2177 } | |
2178 } | |
2179 }; | |
2180 return iterate(this.tree_widget.tree); | |
2181 }; | |
2182 | |
2183 DragAndDropHandler.prototype.findHoveredArea = function(x, y) { | |
2184 var area, high, low, mid, tree_offset; | |
2185 tree_offset = this.tree_widget.element.offset(); | |
2186 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.el
ement.height())) { | |
2187 return null; | |
2188 } | |
2189 low = 0; | |
2190 high = this.hit_areas.length; | |
2191 while (low < high) { | |
2192 mid = (low + high) >> 1; | |
2193 area = this.hit_areas[mid]; | |
2194 if (y < area.top) { | |
2195 high = mid; | |
2196 } else if (y > area.bottom) { | |
2197 low = mid + 1; | |
2198 } else { | |
2199 return area; | |
2200 } | |
2201 } | |
2202 return null; | |
2203 }; | |
2204 | |
2205 DragAndDropHandler.prototype.mustOpenFolderTimer = function(area) { | |
2206 var node; | |
2207 node = area.node; | |
2208 return node.isFolder() && !node.is_open && area.position === Position.INSI
DE; | |
2209 }; | |
2210 | |
2211 DragAndDropHandler.prototype.updateDropHint = function() { | |
2212 var node_element; | |
2213 if (!this.hovered_area) { | |
2214 return; | |
2215 } | |
2216 this.removeDropHint(); | |
2217 node_element = this.tree_widget._getNodeElementForNode(this.hovered_area.n
ode); | |
2218 return this.previous_ghost = node_element.addDropHint(this.hovered_area.po
sition); | |
2219 }; | |
2220 | |
2221 DragAndDropHandler.prototype.startOpenFolderTimer = function(folder) { | |
2222 var openFolder, | |
2223 _this = this; | |
2224 openFolder = function() { | |
2225 return _this.tree_widget._openNode(folder, _this.tree_widget.options.sli
de, function() { | |
2226 _this.refreshHitAreas(); | |
2227 return _this.updateDropHint(); | |
2228 }); | |
2229 }; | |
2230 return this.open_folder_timer = setTimeout(openFolder, 500); | |
2231 }; | |
2232 | |
2233 DragAndDropHandler.prototype.stopOpenFolderTimer = function() { | |
2234 if (this.open_folder_timer) { | |
2235 clearTimeout(this.open_folder_timer); | |
2236 return this.open_folder_timer = null; | |
2237 } | |
2238 }; | |
2239 | |
2240 DragAndDropHandler.prototype.moveItem = function(position_info) { | |
2241 var doMove, event, moved_node, position, previous_parent, target_node, | |
2242 _this = this; | |
2243 if (this.hovered_area && this.hovered_area.position !== Position.NONE && t
his.canMoveToArea(this.hovered_area)) { | |
2244 moved_node = this.current_item.node; | |
2245 target_node = this.hovered_area.node; | |
2246 position = this.hovered_area.position; | |
2247 previous_parent = moved_node.parent; | |
2248 if (position === Position.INSIDE) { | |
2249 this.hovered_area.node.is_open = true; | |
2250 } | |
2251 doMove = function() { | |
2252 _this.tree_widget.tree.moveNode(moved_node, target_node, position); | |
2253 _this.tree_widget.element.empty(); | |
2254 return _this.tree_widget._refreshElements(); | |
2255 }; | |
2256 event = this.tree_widget._triggerEvent('tree.move', { | |
2257 move_info: { | |
2258 moved_node: moved_node, | |
2259 target_node: target_node, | |
2260 position: Position.getName(position), | |
2261 previous_parent: previous_parent, | |
2262 do_move: doMove, | |
2263 original_event: position_info.original_event | |
2264 } | |
2265 }); | |
2266 if (!event.isDefaultPrevented()) { | |
2267 return doMove(); | |
2268 } | |
2269 } | |
2270 }; | |
2271 | |
2272 return DragAndDropHandler; | |
2273 | |
2274 })(); | |
2275 | |
2276 DragElement = (function() { | |
2277 function DragElement(node, offset_x, offset_y, $tree) { | |
2278 this.offset_x = offset_x; | |
2279 this.offset_y = offset_y; | |
2280 this.$element = $("<span class=\"jqtree-title jqtree-dragging\">" + node.n
ame + "</span>"); | |
2281 this.$element.css("position", "absolute"); | |
2282 $tree.append(this.$element); | |
2283 } | |
2284 | |
2285 DragElement.prototype.move = function(page_x, page_y) { | |
2286 return this.$element.offset({ | |
2287 left: page_x - this.offset_x, | |
2288 top: page_y - this.offset_y | |
2289 }); | |
2290 }; | |
2291 | |
2292 DragElement.prototype.remove = function() { | |
2293 return this.$element.remove(); | |
2294 }; | |
2295 | |
2296 return DragElement; | |
2297 | |
2298 })(); | |
2299 | |
2300 GhostDropHint = (function() { | |
2301 function GhostDropHint(node, $element, position) { | |
2302 this.$element = $element; | |
2303 this.node = node; | |
2304 this.$ghost = $('<li class="jqtree_common jqtree-ghost"><span class="jqtre
e_common jqtree-circle"></span><span class="jqtree_common jqtree-line"></span></
li>'); | |
2305 if (position === Position.AFTER) { | |
2306 this.moveAfter(); | |
2307 } else if (position === Position.BEFORE) { | |
2308 this.moveBefore(); | |
2309 } else if (position === Position.INSIDE) { | |
2310 if (node.isFolder() && node.is_open) { | |
2311 this.moveInsideOpenFolder(); | |
2312 } else { | |
2313 this.moveInside(); | |
2314 } | |
2315 } | |
2316 } | |
2317 | |
2318 GhostDropHint.prototype.remove = function() { | |
2319 return this.$ghost.remove(); | |
2320 }; | |
2321 | |
2322 GhostDropHint.prototype.moveAfter = function() { | |
2323 return this.$element.after(this.$ghost); | |
2324 }; | |
2325 | |
2326 GhostDropHint.prototype.moveBefore = function() { | |
2327 return this.$element.before(this.$ghost); | |
2328 }; | |
2329 | |
2330 GhostDropHint.prototype.moveInsideOpenFolder = function() { | |
2331 return $(this.node.children[0].element).before(this.$ghost); | |
2332 }; | |
2333 | |
2334 GhostDropHint.prototype.moveInside = function() { | |
2335 this.$element.after(this.$ghost); | |
2336 return this.$ghost.addClass('jqtree-inside'); | |
2337 }; | |
2338 | |
2339 return GhostDropHint; | |
2340 | |
2341 })(); | |
2342 | |
2343 BorderDropHint = (function() { | |
2344 function BorderDropHint($element) { | |
2345 var $div, width; | |
2346 $div = $element.children('.jqtree-element'); | |
2347 width = $element.width() - 4; | |
2348 this.$hint = $('<span class="jqtree-border"></span>'); | |
2349 $div.append(this.$hint); | |
2350 this.$hint.css({ | |
2351 width: width, | |
2352 height: $div.height() - 4 | |
2353 }); | |
2354 } | |
2355 | |
2356 BorderDropHint.prototype.remove = function() { | |
2357 return this.$hint.remove(); | |
2358 }; | |
2359 | |
2360 return BorderDropHint; | |
2361 | |
2362 })(); | |
2363 | |
2364 ScrollHandler = (function() { | |
2365 function ScrollHandler(tree_widget) { | |
2366 this.tree_widget = tree_widget; | |
2367 this.previous_top = -1; | |
2368 this._initScrollParent(); | |
2369 } | |
2370 | |
2371 ScrollHandler.prototype._initScrollParent = function() { | |
2372 var $scroll_parent, getParentWithOverflow, setDocumentAsScrollParent, | |
2373 _this = this; | |
2374 getParentWithOverflow = function() { | |
2375 var css_value, css_values, parent, scroll_parent, _i, _j, _len, _len1, _
ref3, _ref4; | |
2376 css_values = ['overflow', 'overflow-y']; | |
2377 scroll_parent = null; | |
2378 _ref3 = _this.tree_widget.$el.parents(); | |
2379 for (_i = 0, _len = _ref3.length; _i < _len; _i++) { | |
2380 parent = _ref3[_i]; | |
2381 for (_j = 0, _len1 = css_values.length; _j < _len1; _j++) { | |
2382 css_value = css_values[_j]; | |
2383 if ((_ref4 = $.css(parent, css_value)) === 'auto' || _ref4 === 'scro
ll') { | |
2384 return $(parent); | |
2385 } | |
2386 } | |
2387 } | |
2388 return null; | |
2389 }; | |
2390 setDocumentAsScrollParent = function() { | |
2391 _this.scroll_parent_top = 0; | |
2392 return _this.$scroll_parent = null; | |
2393 }; | |
2394 if (this.tree_widget.$el.css('position') === 'fixed') { | |
2395 setDocumentAsScrollParent(); | |
2396 } | |
2397 $scroll_parent = getParentWithOverflow(); | |
2398 if ($scroll_parent && $scroll_parent.length && $scroll_parent[0].tagName !
== 'HTML') { | |
2399 this.$scroll_parent = $scroll_parent; | |
2400 return this.scroll_parent_top = this.$scroll_parent.offset().top; | |
2401 } else { | |
2402 return setDocumentAsScrollParent(); | |
2403 } | |
2404 }; | |
2405 | |
2406 ScrollHandler.prototype.checkScrolling = function() { | |
2407 var hovered_area; | |
2408 hovered_area = this.tree_widget.dnd_handler.hovered_area; | |
2409 if (hovered_area && hovered_area.top !== this.previous_top) { | |
2410 this.previous_top = hovered_area.top; | |
2411 if (this.$scroll_parent) { | |
2412 return this._handleScrollingWithScrollParent(hovered_area); | |
2413 } else { | |
2414 return this._handleScrollingWithDocument(hovered_area); | |
2415 } | |
2416 } | |
2417 }; | |
2418 | |
2419 ScrollHandler.prototype._handleScrollingWithScrollParent = function(area) { | |
2420 var distance_bottom; | |
2421 distance_bottom = this.scroll_parent_top + this.$scroll_parent[0].offsetHe
ight - area.bottom; | |
2422 if (distance_bottom < 20) { | |
2423 this.$scroll_parent[0].scrollTop += 20; | |
2424 this.tree_widget.refreshHitAreas(); | |
2425 return this.previous_top = -1; | |
2426 } else if ((area.top - this.scroll_parent_top) < 20) { | |
2427 this.$scroll_parent[0].scrollTop -= 20; | |
2428 this.tree_widget.refreshHitAreas(); | |
2429 return this.previous_top = -1; | |
2430 } | |
2431 }; | |
2432 | |
2433 ScrollHandler.prototype._handleScrollingWithDocument = function(area) { | |
2434 var distance_top; | |
2435 distance_top = area.top - $(document).scrollTop(); | |
2436 if (distance_top < 20) { | |
2437 return $(document).scrollTop($(document).scrollTop() - 20); | |
2438 } else if ($(window).height() - (area.bottom - $(document).scrollTop()) <
20) { | |
2439 return $(document).scrollTop($(document).scrollTop() + 20); | |
2440 } | |
2441 }; | |
2442 | |
2443 ScrollHandler.prototype.scrollTo = function(top) { | |
2444 var tree_top; | |
2445 if (this.$scroll_parent) { | |
2446 return this.$scroll_parent[0].scrollTop = top; | |
2447 } else { | |
2448 tree_top = this.tree_widget.$el.offset().top; | |
2449 return $(document).scrollTop(top + tree_top); | |
2450 } | |
2451 }; | |
2452 | |
2453 ScrollHandler.prototype.isScrolledIntoView = function(element) { | |
2454 var $element, element_bottom, element_top, view_bottom, view_top; | |
2455 $element = $(element); | |
2456 if (this.$scroll_parent) { | |
2457 view_top = 0; | |
2458 view_bottom = this.$scroll_parent.height(); | |
2459 element_top = $element.offset().top - this.scroll_parent_top; | |
2460 element_bottom = element_top + $element.height(); | |
2461 } else { | |
2462 view_top = $(window).scrollTop(); | |
2463 view_bottom = view_top + $(window).height(); | |
2464 element_top = $element.offset().top; | |
2465 element_bottom = element_top + $element.height(); | |
2466 } | |
2467 return (element_bottom <= view_bottom) && (element_top >= view_top); | |
2468 }; | |
2469 | |
2470 return ScrollHandler; | |
2471 | |
2472 })(); | |
2473 | |
2474 KeyHandler = (function() { | |
2475 var DOWN, LEFT, RIGHT, UP; | |
2476 | |
2477 LEFT = 37; | |
2478 | |
2479 UP = 38; | |
2480 | |
2481 RIGHT = 39; | |
2482 | |
2483 DOWN = 40; | |
2484 | |
2485 function KeyHandler(tree_widget) { | |
2486 this.tree_widget = tree_widget; | |
2487 $(document).bind('keydown.jqtree', $.proxy(this.handleKeyDown, this)); | |
2488 } | |
2489 | |
2490 KeyHandler.prototype.deinit = function() { | |
2491 return $(document).unbind('keydown.jqtree'); | |
2492 }; | |
2493 | |
2494 KeyHandler.prototype.handleKeyDown = function(e) { | |
2495 var current_node, key, moveDown, moveLeft, moveRight, moveUp, selectNode, | |
2496 _this = this; | |
2497 current_node = this.tree_widget.getSelectedNode(); | |
2498 selectNode = function(node) { | |
2499 if (node) { | |
2500 _this.tree_widget.selectNode(node); | |
2501 if (_this.tree_widget.scroll_handler && (!_this.tree_widget.scroll_han
dler.isScrolledIntoView($(node.element).find('.jqtree-element')))) { | |
2502 _this.tree_widget.scrollToNode(node); | |
2503 } | |
2504 return false; | |
2505 } else { | |
2506 return true; | |
2507 } | |
2508 }; | |
2509 moveDown = function() { | |
2510 return selectNode(_this.getNextNode(current_node)); | |
2511 }; | |
2512 moveUp = function() { | |
2513 return selectNode(_this.getPreviousNode(current_node)); | |
2514 }; | |
2515 moveRight = function() { | |
2516 if (current_node.hasChildren() && !current_node.is_open) { | |
2517 _this.tree_widget.openNode(current_node); | |
2518 return false; | |
2519 } else { | |
2520 return true; | |
2521 } | |
2522 }; | |
2523 moveLeft = function() { | |
2524 if (current_node.hasChildren() && current_node.is_open) { | |
2525 _this.tree_widget.closeNode(current_node); | |
2526 return false; | |
2527 } else { | |
2528 return true; | |
2529 } | |
2530 }; | |
2531 if (!current_node) { | |
2532 return true; | |
2533 } else { | |
2534 key = e.which; | |
2535 switch (key) { | |
2536 case DOWN: | |
2537 return moveDown(); | |
2538 case UP: | |
2539 return moveUp(); | |
2540 case RIGHT: | |
2541 return moveRight(); | |
2542 case LEFT: | |
2543 return moveLeft(); | |
2544 } | |
2545 } | |
2546 }; | |
2547 | |
2548 KeyHandler.prototype.getNextNode = function(node, include_children) { | |
2549 var next_sibling; | |
2550 if (include_children == null) { | |
2551 include_children = true; | |
2552 } | |
2553 if (include_children && node.hasChildren() && node.is_open) { | |
2554 return node.children[0]; | |
2555 } else { | |
2556 if (!node.parent) { | |
2557 return null; | |
2558 } else { | |
2559 next_sibling = node.getNextSibling(); | |
2560 if (next_sibling) { | |
2561 return next_sibling; | |
2562 } else { | |
2563 return this.getNextNode(node.parent, false); | |
2564 } | |
2565 } | |
2566 } | |
2567 }; | |
2568 | |
2569 KeyHandler.prototype.getPreviousNode = function(node) { | |
2570 var previous_sibling; | |
2571 if (!node.parent) { | |
2572 return null; | |
2573 } else { | |
2574 previous_sibling = node.getPreviousSibling(); | |
2575 if (previous_sibling) { | |
2576 if (!previous_sibling.hasChildren() || !previous_sibling.is_open) { | |
2577 return previous_sibling; | |
2578 } else { | |
2579 return this.getLastChild(previous_sibling); | |
2580 } | |
2581 } else { | |
2582 if (node.parent.parent) { | |
2583 return node.parent; | |
2584 } else { | |
2585 return null; | |
2586 } | |
2587 } | |
2588 } | |
2589 }; | |
2590 | |
2591 KeyHandler.prototype.getLastChild = function(node) { | |
2592 var last_child; | |
2593 if (!node.hasChildren()) { | |
2594 return null; | |
2595 } else { | |
2596 last_child = node.children[node.children.length - 1]; | |
2597 if (!last_child.hasChildren() || !last_child.is_open) { | |
2598 return last_child; | |
2599 } else { | |
2600 return this.getLastChild(last_child); | |
2601 } | |
2602 } | |
2603 }; | |
2604 | |
2605 return KeyHandler; | |
2606 | |
2607 })(); | |
2608 | |
2609 }).call(this); | |
OLD | NEW |