nexus site path corrected
[portal.git] / ecomp-portal-FE / client / bower_components / jqTree / lib / drag_and_drop_handler.js
1 var $, DragAndDropHandler, DragElement, HitAreasGenerator, Position, VisibleNodeIterator, node_module, util,
2   extend = 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; },
3   hasProp = {}.hasOwnProperty;
4
5 node_module = require('./node');
6
7 util = require('./util');
8
9 Position = node_module.Position;
10
11 $ = jQuery;
12
13 DragAndDropHandler = (function() {
14   function DragAndDropHandler(tree_widget) {
15     this.tree_widget = tree_widget;
16     this.hovered_area = null;
17     this.$ghost = null;
18     this.hit_areas = [];
19     this.is_dragging = false;
20     this.current_item = null;
21   }
22
23   DragAndDropHandler.prototype.mouseCapture = function(position_info) {
24     var $element, node_element;
25     $element = $(position_info.target);
26     if (!this.mustCaptureElement($element)) {
27       return null;
28     }
29     if (this.tree_widget.options.onIsMoveHandle && !this.tree_widget.options.onIsMoveHandle($element)) {
30       return null;
31     }
32     node_element = this.tree_widget._getNodeElement($element);
33     if (node_element && this.tree_widget.options.onCanMove) {
34       if (!this.tree_widget.options.onCanMove(node_element.node)) {
35         node_element = null;
36       }
37     }
38     this.current_item = node_element;
39     return this.current_item !== null;
40   };
41
42   DragAndDropHandler.prototype.mouseStart = function(position_info) {
43     var node, node_name, offset;
44     this.refresh();
45     offset = $(position_info.target).offset();
46     node = this.current_item.node;
47     if (this.tree_widget.options.autoEscape) {
48       node_name = util.html_escape(node.name);
49     } else {
50       node_name = node.name;
51     }
52     this.drag_element = new DragElement(node_name, position_info.page_x - offset.left, position_info.page_y - offset.top, this.tree_widget.element);
53     this.is_dragging = true;
54     this.current_item.$element.addClass('jqtree-moving');
55     return true;
56   };
57
58   DragAndDropHandler.prototype.mouseDrag = function(position_info) {
59     var area, can_move_to;
60     this.drag_element.move(position_info.page_x, position_info.page_y);
61     area = this.findHoveredArea(position_info.page_x, position_info.page_y);
62     can_move_to = this.canMoveToArea(area);
63     if (can_move_to && area) {
64       if (!area.node.isFolder()) {
65         this.stopOpenFolderTimer();
66       }
67       if (this.hovered_area !== area) {
68         this.hovered_area = area;
69         if (this.mustOpenFolderTimer(area)) {
70           this.startOpenFolderTimer(area.node);
71         } else {
72           this.stopOpenFolderTimer();
73         }
74         this.updateDropHint();
75       }
76     } else {
77       this.removeHover();
78       this.removeDropHint();
79       this.stopOpenFolderTimer();
80     }
81     if (!area) {
82       if (this.tree_widget.options.onDragMove != null) {
83         this.tree_widget.options.onDragMove(this.current_item.node, position_info.original_event);
84       }
85     }
86     return true;
87   };
88
89   DragAndDropHandler.prototype.mustCaptureElement = function($element) {
90     return !$element.is('input,select,textarea');
91   };
92
93   DragAndDropHandler.prototype.canMoveToArea = function(area) {
94     var position_name;
95     if (!area) {
96       return false;
97     } else if (this.tree_widget.options.onCanMoveTo) {
98       position_name = Position.getName(area.position);
99       return this.tree_widget.options.onCanMoveTo(this.current_item.node, area.node, position_name);
100     } else {
101       return true;
102     }
103   };
104
105   DragAndDropHandler.prototype.mouseStop = function(position_info) {
106     var current_item;
107     this.moveItem(position_info);
108     this.clear();
109     this.removeHover();
110     this.removeDropHint();
111     this.removeHitAreas();
112     current_item = this.current_item;
113     if (this.current_item) {
114       this.current_item.$element.removeClass('jqtree-moving');
115       this.current_item = null;
116     }
117     this.is_dragging = false;
118     if (!this.hovered_area && current_item) {
119       if (this.tree_widget.options.onDragStop != null) {
120         this.tree_widget.options.onDragStop(current_item.node, position_info.original_event);
121       }
122     }
123     return false;
124   };
125
126   DragAndDropHandler.prototype.refresh = function() {
127     this.removeHitAreas();
128     if (this.current_item) {
129       this.generateHitAreas();
130       this.current_item = this.tree_widget._getNodeElementForNode(this.current_item.node);
131       if (this.is_dragging) {
132         return this.current_item.$element.addClass('jqtree-moving');
133       }
134     }
135   };
136
137   DragAndDropHandler.prototype.removeHitAreas = function() {
138     return this.hit_areas = [];
139   };
140
141   DragAndDropHandler.prototype.clear = function() {
142     this.drag_element.remove();
143     return this.drag_element = null;
144   };
145
146   DragAndDropHandler.prototype.removeDropHint = function() {
147     if (this.previous_ghost) {
148       return this.previous_ghost.remove();
149     }
150   };
151
152   DragAndDropHandler.prototype.removeHover = function() {
153     return this.hovered_area = null;
154   };
155
156   DragAndDropHandler.prototype.generateHitAreas = function() {
157     var hit_areas_generator;
158     hit_areas_generator = new HitAreasGenerator(this.tree_widget.tree, this.current_item.node, this.getTreeDimensions().bottom);
159     return this.hit_areas = hit_areas_generator.generate();
160   };
161
162   DragAndDropHandler.prototype.findHoveredArea = function(x, y) {
163     var area, dimensions, high, low, mid;
164     dimensions = this.getTreeDimensions();
165     if (x < dimensions.left || y < dimensions.top || x > dimensions.right || y > dimensions.bottom) {
166       return null;
167     }
168     low = 0;
169     high = this.hit_areas.length;
170     while (low < high) {
171       mid = (low + high) >> 1;
172       area = this.hit_areas[mid];
173       if (y < area.top) {
174         high = mid;
175       } else if (y > area.bottom) {
176         low = mid + 1;
177       } else {
178         return area;
179       }
180     }
181     return null;
182   };
183
184   DragAndDropHandler.prototype.mustOpenFolderTimer = function(area) {
185     var node;
186     node = area.node;
187     return node.isFolder() && !node.is_open && area.position === Position.INSIDE;
188   };
189
190   DragAndDropHandler.prototype.updateDropHint = function() {
191     var node_element;
192     if (!this.hovered_area) {
193       return;
194     }
195     this.removeDropHint();
196     node_element = this.tree_widget._getNodeElementForNode(this.hovered_area.node);
197     return this.previous_ghost = node_element.addDropHint(this.hovered_area.position);
198   };
199
200   DragAndDropHandler.prototype.startOpenFolderTimer = function(folder) {
201     var openFolder;
202     openFolder = (function(_this) {
203       return function() {
204         return _this.tree_widget._openNode(folder, _this.tree_widget.options.slide, function() {
205           _this.refresh();
206           return _this.updateDropHint();
207         });
208       };
209     })(this);
210     this.stopOpenFolderTimer();
211     return this.open_folder_timer = setTimeout(openFolder, this.tree_widget.options.openFolderDelay);
212   };
213
214   DragAndDropHandler.prototype.stopOpenFolderTimer = function() {
215     if (this.open_folder_timer) {
216       clearTimeout(this.open_folder_timer);
217       return this.open_folder_timer = null;
218     }
219   };
220
221   DragAndDropHandler.prototype.moveItem = function(position_info) {
222     var doMove, event, moved_node, position, previous_parent, target_node;
223     if (this.hovered_area && this.hovered_area.position !== Position.NONE && this.canMoveToArea(this.hovered_area)) {
224       moved_node = this.current_item.node;
225       target_node = this.hovered_area.node;
226       position = this.hovered_area.position;
227       previous_parent = moved_node.parent;
228       if (position === Position.INSIDE) {
229         this.hovered_area.node.is_open = true;
230       }
231       doMove = (function(_this) {
232         return function() {
233           _this.tree_widget.tree.moveNode(moved_node, target_node, position);
234           _this.tree_widget.element.empty();
235           return _this.tree_widget._refreshElements();
236         };
237       })(this);
238       event = this.tree_widget._triggerEvent('tree.move', {
239         move_info: {
240           moved_node: moved_node,
241           target_node: target_node,
242           position: Position.getName(position),
243           previous_parent: previous_parent,
244           do_move: doMove,
245           original_event: position_info.original_event
246         }
247       });
248       if (!event.isDefaultPrevented()) {
249         return doMove();
250       }
251     }
252   };
253
254   DragAndDropHandler.prototype.getTreeDimensions = function() {
255     var offset;
256     offset = this.tree_widget.element.offset();
257     return {
258       left: offset.left,
259       top: offset.top,
260       right: offset.left + this.tree_widget.element.width(),
261       bottom: offset.top + this.tree_widget.element.height() + 16
262     };
263   };
264
265   return DragAndDropHandler;
266
267 })();
268
269 VisibleNodeIterator = (function() {
270   function VisibleNodeIterator(tree) {
271     this.tree = tree;
272   }
273
274   VisibleNodeIterator.prototype.iterate = function() {
275     var _iterateNode, is_first_node;
276     is_first_node = true;
277     _iterateNode = (function(_this) {
278       return function(node, next_node) {
279         var $element, child, children_length, i, j, len, must_iterate_inside, ref;
280         must_iterate_inside = (node.is_open || !node.element) && node.hasChildren();
281         if (node.element) {
282           $element = $(node.element);
283           if (!$element.is(':visible')) {
284             return;
285           }
286           if (is_first_node) {
287             _this.handleFirstNode(node, $element);
288             is_first_node = false;
289           }
290           if (!node.hasChildren()) {
291             _this.handleNode(node, next_node, $element);
292           } else if (node.is_open) {
293             if (!_this.handleOpenFolder(node, $element)) {
294               must_iterate_inside = false;
295             }
296           } else {
297             _this.handleClosedFolder(node, next_node, $element);
298           }
299         }
300         if (must_iterate_inside) {
301           children_length = node.children.length;
302           ref = node.children;
303           for (i = j = 0, len = ref.length; j < len; i = ++j) {
304             child = ref[i];
305             if (i === (children_length - 1)) {
306               _iterateNode(node.children[i], null);
307             } else {
308               _iterateNode(node.children[i], node.children[i + 1]);
309             }
310           }
311           if (node.is_open) {
312             return _this.handleAfterOpenFolder(node, next_node, $element);
313           }
314         }
315       };
316     })(this);
317     return _iterateNode(this.tree, null);
318   };
319
320   VisibleNodeIterator.prototype.handleNode = function(node, next_node, $element) {};
321
322   VisibleNodeIterator.prototype.handleOpenFolder = function(node, $element) {};
323
324   VisibleNodeIterator.prototype.handleClosedFolder = function(node, next_node, $element) {};
325
326   VisibleNodeIterator.prototype.handleAfterOpenFolder = function(node, next_node, $element) {};
327
328   VisibleNodeIterator.prototype.handleFirstNode = function(node, $element) {};
329
330   return VisibleNodeIterator;
331
332 })();
333
334 HitAreasGenerator = (function(superClass) {
335   extend(HitAreasGenerator, superClass);
336
337   function HitAreasGenerator(tree, current_node, tree_bottom) {
338     HitAreasGenerator.__super__.constructor.call(this, tree);
339     this.current_node = current_node;
340     this.tree_bottom = tree_bottom;
341   }
342
343   HitAreasGenerator.prototype.generate = function() {
344     this.positions = [];
345     this.last_top = 0;
346     this.iterate();
347     return this.generateHitAreas(this.positions);
348   };
349
350   HitAreasGenerator.prototype.getTop = function($element) {
351     return $element.offset().top;
352   };
353
354   HitAreasGenerator.prototype.addPosition = function(node, position, top) {
355     var area;
356     area = {
357       top: top,
358       node: node,
359       position: position
360     };
361     this.positions.push(area);
362     return this.last_top = top;
363   };
364
365   HitAreasGenerator.prototype.handleNode = function(node, next_node, $element) {
366     var top;
367     top = this.getTop($element);
368     if (node === this.current_node) {
369       this.addPosition(node, Position.NONE, top);
370     } else {
371       this.addPosition(node, Position.INSIDE, top);
372     }
373     if (next_node === this.current_node || node === this.current_node) {
374       return this.addPosition(node, Position.NONE, top);
375     } else {
376       return this.addPosition(node, Position.AFTER, top);
377     }
378   };
379
380   HitAreasGenerator.prototype.handleOpenFolder = function(node, $element) {
381     if (node === this.current_node) {
382       return false;
383     }
384     if (node.children[0] !== this.current_node) {
385       this.addPosition(node, Position.INSIDE, this.getTop($element));
386     }
387     return true;
388   };
389
390   HitAreasGenerator.prototype.handleClosedFolder = function(node, next_node, $element) {
391     var top;
392     top = this.getTop($element);
393     if (node === this.current_node) {
394       return this.addPosition(node, Position.NONE, top);
395     } else {
396       this.addPosition(node, Position.INSIDE, top);
397       if (next_node !== this.current_node) {
398         return this.addPosition(node, Position.AFTER, top);
399       }
400     }
401   };
402
403   HitAreasGenerator.prototype.handleFirstNode = function(node, $element) {
404     if (node !== this.current_node) {
405       return this.addPosition(node, Position.BEFORE, this.getTop($(node.element)));
406     }
407   };
408
409   HitAreasGenerator.prototype.handleAfterOpenFolder = function(node, next_node, $element) {
410     if (node === this.current_node.node || next_node === this.current_node.node) {
411       return this.addPosition(node, Position.NONE, this.last_top);
412     } else {
413       return this.addPosition(node, Position.AFTER, this.last_top);
414     }
415   };
416
417   HitAreasGenerator.prototype.generateHitAreas = function(positions) {
418     var group, hit_areas, j, len, position, previous_top;
419     previous_top = -1;
420     group = [];
421     hit_areas = [];
422     for (j = 0, len = positions.length; j < len; j++) {
423       position = positions[j];
424       if (position.top !== previous_top && group.length) {
425         if (group.length) {
426           this.generateHitAreasForGroup(hit_areas, group, previous_top, position.top);
427         }
428         previous_top = position.top;
429         group = [];
430       }
431       group.push(position);
432     }
433     this.generateHitAreasForGroup(hit_areas, group, previous_top, this.tree_bottom);
434     return hit_areas;
435   };
436
437   HitAreasGenerator.prototype.generateHitAreasForGroup = function(hit_areas, positions_in_group, top, bottom) {
438     var area_height, area_top, i, position, position_count;
439     position_count = Math.min(positions_in_group.length, 4);
440     area_height = Math.round((bottom - top) / position_count);
441     area_top = top;
442     i = 0;
443     while (i < position_count) {
444       position = positions_in_group[i];
445       hit_areas.push({
446         top: area_top,
447         bottom: area_top + area_height,
448         node: position.node,
449         position: position.position
450       });
451       area_top += area_height;
452       i += 1;
453     }
454     return null;
455   };
456
457   return HitAreasGenerator;
458
459 })(VisibleNodeIterator);
460
461 DragElement = (function() {
462   function DragElement(node_name, offset_x, offset_y, $tree) {
463     this.offset_x = offset_x;
464     this.offset_y = offset_y;
465     this.$element = $("<span class=\"jqtree-title jqtree-dragging\">" + node_name + "</span>");
466     this.$element.css("position", "absolute");
467     $tree.append(this.$element);
468   }
469
470   DragElement.prototype.move = function(page_x, page_y) {
471     return this.$element.offset({
472       left: page_x - this.offset_x,
473       top: page_y - this.offset_y
474     });
475   };
476
477   DragElement.prototype.remove = function() {
478     return this.$element.remove();
479   };
480
481   return DragElement;
482
483 })();
484
485 module.exports = {
486   DragAndDropHandler: DragAndDropHandler,
487   DragElement: DragElement,
488   HitAreasGenerator: HitAreasGenerator
489 };