vendor/assets/javascripts/tree.jquery.js in jqtree-rails-0.1.0 vs vendor/assets/javascripts/tree.jquery.js in jqtree-rails-0.1.3

- old
+ new

@@ -1,6 +1,6 @@ -// Generated by CoffeeScript 1.3.1 +// Generated by CoffeeScript 1.3.3 /* Copyright 2012 Marco Braak Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,27 +16,24 @@ limitations under the License. */ (function() { - var $, BorderDropHint, DragElement, FolderElement, GhostDropHint, JqueryWidget, Json, MouseWidget, Node, NodeElement, Position, SimpleWidget, indexOf, toJson, + var $, BorderDropHint, DragAndDropHandler, DragElement, FolderElement, GhostDropHint, JqTreeWidget, MouseWidget, Node, NodeElement, Position, SaveStateHandler, SelectNodeHandler, SimpleWidget, TRIANGLE_DOWN, TRIANGLE_RIGHT, Tree, html_escape, indexOf, json_escapable, json_meta, json_quote, json_str, __slice = [].slice, __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; $ = this.jQuery; SimpleWidget = (function() { - SimpleWidget.name = 'SimpleWidget'; - SimpleWidget.prototype.defaults = {}; function SimpleWidget(el, options) { this.$el = $(el); this.options = $.extend({}, this.defaults, options); - this._init(); } SimpleWidget.prototype.destroy = function() { return this._deinit(); }; @@ -47,76 +44,79 @@ SimpleWidget.prototype._deinit = function() { return null; }; - return SimpleWidget; - - })(); - - SimpleWidget.register = function(widget_class, widget_name) { - var callFunction, createWidget, destroyWidget, getDataKey; - getDataKey = function() { - return "simple_widget_" + widget_name; - }; - createWidget = function($el, options) { - var data_key; - data_key = getDataKey(); - $el.each(function() { - var widget; - widget = new widget_class(this, options); - if (!$.data(this, data_key)) { - return $.data(this, data_key, widget); + SimpleWidget.register = function(widget_class, widget_name) { + var callFunction, createWidget, destroyWidget, getDataKey; + getDataKey = function() { + return "simple_widget_" + widget_name; + }; + createWidget = function($el, options) { + var data_key, el, widget, _i, _len; + data_key = getDataKey(); + for (_i = 0, _len = $el.length; _i < _len; _i++) { + el = $el[_i]; + widget = new widget_class(el, options); + if (!$.data(el, data_key)) { + $.data(el, data_key, widget); + } + widget._init(); } - }); - return $el; - }; - destroyWidget = function($el) { - var data_key; - data_key = getDataKey(); - return $el.each(function() { - var widget; - widget = $.data(this, data_key); - if (widget && (widget instanceof SimpleWidget)) { - widget.destroy(); + return $el; + }; + destroyWidget = function($el) { + var data_key, el, widget, _i, _len, _results; + data_key = getDataKey(); + _results = []; + for (_i = 0, _len = $el.length; _i < _len; _i++) { + el = $el[_i]; + widget = $.data(el, data_key); + if (widget && (widget instanceof SimpleWidget)) { + widget.destroy(); + } + _results.push($.removeData(el, data_key)); } - return $.removeData(this, data_key); - }); - }; - callFunction = function($el, function_name, args) { - var result; - result = null; - $el.each(function() { - var widget, widget_function; - widget = $.data(this, getDataKey()); - if (widget && (widget instanceof SimpleWidget)) { - widget_function = widget[function_name]; - if (widget_function && (typeof widget_function === 'function')) { - return result = widget_function.apply(widget, args); + return _results; + }; + callFunction = function($el, function_name, args) { + var el, result, widget, widget_function, _i, _len; + result = null; + for (_i = 0, _len = $el.length; _i < _len; _i++) { + el = $el[_i]; + widget = $.data(el, getDataKey()); + if (widget && (widget instanceof SimpleWidget)) { + widget_function = widget[function_name]; + if (widget_function && (typeof widget_function === 'function')) { + result = widget_function.apply(widget, args); + } } } - }); - return result; - }; - return $.fn[widget_name] = function() { - var $el, args, argument1, function_name, options; - argument1 = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; - $el = this; - if (argument1 === void 0 || typeof argument1 === 'object') { - options = argument1; - return createWidget($el, options); - } else if (typeof argument1 === 'string' && argument1[0] !== '_') { - function_name = argument1; - if (function_name === 'destroy') { - return destroyWidget($el); - } else { - return callFunction($el, function_name, args); + return result; + }; + return $.fn[widget_name] = function() { + var $el, args, argument1, function_name, options; + argument1 = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + $el = this; + if (argument1 === void 0 || typeof argument1 === 'object') { + options = argument1; + return createWidget($el, options); + } else if (typeof argument1 === 'string' && argument1[0] !== '_') { + function_name = argument1; + if (function_name === 'destroy') { + return destroyWidget($el); + } else { + return callFunction($el, function_name, args); + } } - } + }; }; - }; + return SimpleWidget; + + })(); + this.SimpleWidget = SimpleWidget; /* This widget does the same a the mouse widget in jqueryui. */ @@ -124,29 +124,30 @@ MouseWidget = (function(_super) { __extends(MouseWidget, _super); - MouseWidget.name = 'MouseWidget'; - function MouseWidget() { return MouseWidget.__super__.constructor.apply(this, arguments); } MouseWidget.is_mouse_handled = false; MouseWidget.prototype._init = function() { - this.$el.bind('mousedown', $.proxy(this._mouseDown, this)); - return this.is_mouse_started = false; + this.$el.bind('mousedown.mousewidget', $.proxy(this._mouseDown, this)); + this.is_mouse_started = false; + this.mouse_delay = 0; + this._mouse_delay_timer = null; + return this._is_mouse_delay_met = true; }; MouseWidget.prototype._deinit = function() { var $document; - this.$el.unbind('mousedown'); + this.$el.unbind('mousedown.mousewidget'); $document = $(document); - $document.unbind('mousemove'); - return $document.unbind('mouseup'); + $document.unbind('mousemove.mousewidget'); + return $document.unbind('mouseup.mousewidget'); }; MouseWidget.prototype._mouseDown = function(e) { var $document; if (MouseWidget.is_mouse_handled) { @@ -161,22 +162,39 @@ if (!this._mouseCapture(e)) { return; } this.mouse_down_event = e; $document = $(document); - $document.bind('mousemove', $.proxy(this._mouseMove, this)); - $document.bind('mouseup', $.proxy(this._mouseUp, this)); + $document.bind('mousemove.mousewidget', $.proxy(this._mouseMove, this)); + $document.bind('mouseup.mousewidget', $.proxy(this._mouseUp, this)); + if (this.mouse_delay) { + this._startMouseDelayTimer(); + } e.preventDefault(); this.is_mouse_handled = true; return true; }; + MouseWidget.prototype._startMouseDelayTimer = function() { + var _this = this; + if (this._mouse_delay_timer) { + clearTimeout(this._mouse_delay_timer); + } + this._mouse_delay_timer = setTimeout(function() { + return _this._is_mouse_delay_met = true; + }, this.mouse_delay); + return this._is_mouse_delay_met = false; + }; + MouseWidget.prototype._mouseMove = function(e) { if (this.is_mouse_started) { this._mouseDrag(e); return e.preventDefault(); } + if (this.mouse_delay && !this._is_mouse_delay_met) { + return true; + } this.is_mouse_started = this._mouseStart(this.mouse_down_event) !== false; if (this.is_mouse_started) { this._mouseDrag(e); } else { this._mouseUp(e); @@ -185,12 +203,12 @@ }; MouseWidget.prototype._mouseUp = function(e) { var $document; $document = $(document); - $document.unbind('mousemove'); - $document.unbind('mouseup'); + $document.unbind('mousemove.mousewidget'); + $document.unbind('mouseup.mousewidget'); if (this.is_mouse_started) { this.is_mouse_started = false; this._mouseStop(e); } return false; @@ -252,98 +270,97 @@ } }; this.Tree.indexOf = indexOf; - Json = {}; - - Json.escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - - Json.meta = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"': '\\"', - '\\': '\\\\' - }; - - Json.quote = function(string) { - Json.escapable.lastIndex = 0; - if (Json.escapable.test(string)) { - return '"' + string.replace(Json.escapable, function(a) { - var c; - c = Json.meta[a]; - return (typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)); - }) + '"'; - } else { - return '"' + string + '"'; - } - }; - - Json.str = function(key, holder) { - var i, k, partial, v, value, _i, _len; - value = holder[key]; - if (value && typeof value === 'object' && typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - switch (typeof value) { - case 'string': - return Json.quote(value); - case 'number': - if (isFinite(value)) { + if (!((this.JSON != null) && (this.JSON.stringify != null) && typeof this.JSON.stringify === 'function')) { + json_escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + json_meta = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"': '\\"', + '\\': '\\\\' + }; + json_quote = function(string) { + json_escapable.lastIndex = 0; + if (json_escapable.test(string)) { + return '"' + string.replace(json_escapable, function(a) { + var c; + c = json_meta[a]; + return (typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)); + }) + '"'; + } else { + return '"' + string + '"'; + } + }; + json_str = function(key, holder) { + var i, k, partial, v, value, _i, _len; + value = holder[key]; + switch (typeof value) { + case 'string': + return json_quote(value); + case 'number': + if (isFinite(value)) { + return String(value); + } else { + return 'null'; + } + case 'boolean': + case 'null': return String(value); - } else { - return 'null'; - } - case 'boolean': - case 'null': - return String(value); - case 'object': - if (!value) { - return 'null'; - } - partial = []; - if (Object.prototype.toString.apply(value) === '[object Array]') { - for (i = _i = 0, _len = value.length; _i < _len; i = ++_i) { - v = value[i]; - partial[i] = Json.str(i, value) || 'null'; + case 'object': + if (!value) { + return 'null'; } - return (partial.length === 0 ? '[]' : '[' + partial.join(',') + ']'); - } - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = Json.str(k, value); - if (v) { - partial.push(Json.quote(k) + ':' + v); + partial = []; + if (Object.prototype.toString.apply(value) === '[object Array]') { + for (i = _i = 0, _len = value.length; _i < _len; i = ++_i) { + v = value[i]; + partial[i] = json_str(i, value) || 'null'; } + return (partial.length === 0 ? '[]' : '[' + partial.join(',') + ']'); } - } - return (partial.length === 0 ? '{}' : '{' + partial.join(',') + '}'); + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = json_str(k, value); + if (v) { + partial.push(json_quote(k) + ':' + v); + } + } + } + return (partial.length === 0 ? '{}' : '{' + partial.join(',') + '}'); + } + }; + if (!(this.JSON != null)) { + this.JSON = {}; } - }; + this.JSON.stringify = function(value) { + return json_str('', { + '': value + }); + }; + } - toJson = function(value) { - return Json.str('', { - '': value - }); + html_escape = function(string) { + return ('' + string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g, '&#x2F;'); }; - this.Tree.toJson = toJson; - Position = { getName: function(position) { - if (position === Position.BEFORE) { - return 'before'; - } else if (position === Position.AFTER) { - return 'after'; - } else if (position === Position.INSIDE) { - return 'inside'; - } else { - return 'none'; + return Position.strings[position - 1]; + }, + nameToIndex: function(name) { + var i, _i, _ref; + for (i = _i = 1, _ref = Position.strings.length; 1 <= _ref ? _i <= _ref : _i >= _ref; i = 1 <= _ref ? ++_i : --_i) { + if (Position.strings[i - 1] === name) { + return i; + } } + return 0; } }; Position.BEFORE = 1; @@ -351,53 +368,61 @@ Position.INSIDE = 3; Position.NONE = 4; + Position.strings = ['before', 'after', 'inside', 'none']; + this.Tree.Position = Position; Node = (function() { - Node.name = 'Node'; - - function Node(name) { - this.init(name); + function Node(o) { + this.setData(o); + this.children = []; + this.parent = null; } - Node.prototype.init = function(name) { - this.name = name; - this.children = []; - return this.parent = null; + Node.prototype.setData = function(o) { + var key, value, _results; + if (typeof o !== 'object') { + return this.name = o; + } else { + _results = []; + for (key in o) { + value = o[key]; + if (key === 'label') { + _results.push(this.name = value); + } else { + _results.push(this[key] = value); + } + } + return _results; + } }; Node.prototype.initFromData = function(data) { var addChildren, addNode, _this = this; addNode = function(node_data) { - return $.each(node_data, function(key, value) { - if (key === 'children') { - addChildren(value); - } else if (key === 'label') { - _this['name'] = value; - } else { - _this[key] = value; - } - return true; - }); + _this.setData(node_data); + if (node_data.children) { + return addChildren(node_data.children); + } }; addChildren = function(children_data) { - var child, node, _i, _len, _results; - _results = []; + var child, node, _i, _len; for (_i = 0, _len = children_data.length; _i < _len; _i++) { child = children_data[_i]; - node = new Node(); + node = new Node(''); node.initFromData(child); - _results.push(_this.addChild(node)); + _this.addChild(node); } - return _results; + return null; }; - return addNode(data); + addNode(data); + return null; }; /* Create tree from data. @@ -416,31 +441,21 @@ ] */ Node.prototype.loadFromData = function(data) { - var node, o, _i, _len, _results, - _this = this; + var node, o, _i, _len; this.children = []; - _results = []; for (_i = 0, _len = data.length; _i < _len; _i++) { o = data[_i]; - node = new Node(o.label); - $.each(o, function(key, value) { - if (key !== 'label') { - node[key] = value; - } - return true; - }); + node = new Node(o); this.addChild(node); - if (o.children) { - _results.push(node.loadFromData(o.children)); - } else { - _results.push(void 0); + if (typeof o === 'object' && o.children) { + node.loadFromData(o.children); } } - return _results; + return null; }; /* Add child. @@ -450,11 +465,11 @@ */ Node.prototype.addChild = function(node) { this.children.push(node); - return node.parent = this; + return node._setParent(this); }; /* Add child at position. Index starts at 0. @@ -465,22 +480,29 @@ */ Node.prototype.addChildAtPosition = function(node, index) { this.children.splice(index, 0, node); - return node.parent = this; + return node._setParent(this); }; + Node.prototype._setParent = function(parent) { + this.parent = parent; + this.tree = parent.tree; + return this.tree.addNodeToIndex(this); + }; + /* Remove child. - tree.removeChile(tree.children[0]); + tree.removeChild(tree.children[0]); */ Node.prototype.removeChild = function(node) { - return this.children.splice(this.getChildIndex(node), 1); + this.children.splice(this.getChildIndex(node), 1); + return this.tree.removeNodeFromIndex(node); }; /* Get child index. @@ -503,10 +525,14 @@ Node.prototype.hasChildren = function() { return this.children.length !== 0; }; + Node.prototype.isFolder = function() { + return this.hasChildren() || this.load_on_demand; + }; + /* Iterate over all the nodes in the tree. Calls callback with (node, level). @@ -524,26 +550,26 @@ Node.prototype.iterate = function(callback) { var _iterate, _this = this; - _iterate = function(level) { - var child, result, _i, _len, _ref, _results; - _ref = _this.children; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - child = _ref[_i]; - result = callback(child, level); - if (_this.hasChildren() && result) { - _results.push(child.iterate(callback, level + 1)); - } else { - _results.push(void 0); + _iterate = function(node, level) { + var child, result, _i, _len, _ref; + if (node.children) { + _ref = node.children; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + result = callback(child, level); + if (_this.hasChildren() && result) { + _iterate(child, level + 1); + } } + return null; } - return _results; }; - return _iterate(0); + _iterate(this, 0); + return null; }; /* Move node relative to another node. @@ -553,10 +579,13 @@ tree.moveNode(node1, node2, Position.AFTER); */ Node.prototype.moveNode = function(moved_node, target_node, position) { + if (moved_node.isParentOf(target_node)) { + return; + } moved_node.parent.removeChild(moved_node); if (position === Position.AFTER) { return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node) + 1); } else if (position === Position.BEFORE) { return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node)); @@ -579,11 +608,11 @@ for (_i = 0, _len = nodes.length; _i < _len; _i++) { node = nodes[_i]; tmp_node = {}; for (k in node) { v = node[k]; - if ((k !== 'parent' && k !== 'children' && k !== 'element') && Object.prototype.hasOwnProperty.call(node, k)) { + if ((k !== 'parent' && k !== 'children' && k !== 'element' && k !== 'tree') && Object.prototype.hasOwnProperty.call(node, k)) { tmp_node[k] = v; } } if (node.hasChildren()) { tmp_node.children = getDataFromNodes(node.children); @@ -593,163 +622,432 @@ return data; }; return getDataFromNodes(this.children); }; + Node.prototype.getNodeByName = function(name) { + var result; + result = null; + this.iterate(function(node) { + if (node.name === name) { + result = node; + return false; + } else { + return true; + } + }); + return result; + }; + + Node.prototype.addAfter = function(node_info) { + var child_index, node; + if (!this.parent) { + return null; + } else { + node = new Node(node_info); + child_index = this.parent.getChildIndex(this); + this.parent.addChildAtPosition(node, child_index + 1); + return node; + } + }; + + Node.prototype.addBefore = function(node_info) { + var child_index, node; + if (!this.parent) { + return null; + } else { + node = new Node(node_info); + child_index = this.parent.getChildIndex(this); + return this.parent.addChildAtPosition(node, child_index); + } + }; + + Node.prototype.addParent = function(node_info) { + var child, new_parent, original_parent, _i, _len, _ref; + if (!this.parent) { + return null; + } else { + new_parent = new Node(node_info); + new_parent._setParent(this.tree); + original_parent = this.parent; + _ref = original_parent.children; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + new_parent.addChild(child); + } + original_parent.children = []; + original_parent.addChild(new_parent); + return new_parent; + } + }; + + Node.prototype.remove = function() { + if (this.parent) { + this.parent.removeChild(this); + return this.parent = null; + } + }; + + Node.prototype.append = function(node_info) { + var node; + node = new Node(node_info); + this.addChild(node); + return node; + }; + + Node.prototype.prepend = function(node_info) { + var node; + node = new Node(node_info); + this.addChildAtPosition(node, 0); + return node; + }; + + Node.prototype.isParentOf = function(node) { + var parent; + parent = node.parent; + while (parent) { + if (parent === this) { + return true; + } + parent = parent.parent; + } + return false; + }; + return Node; })(); - this.Tree.Tree = Node; + Tree = (function(_super) { - JqueryWidget = (function(_super) { + __extends(Tree, _super); - __extends(JqueryWidget, _super); + function Tree(o) { + Tree.__super__.constructor.call(this, o, null, true); + this.id_mapping = {}; + this.tree = this; + } - JqueryWidget.name = 'JqueryWidget'; + Tree.prototype.getNodeById = function(node_id) { + return this.id_mapping[node_id]; + }; - function JqueryWidget() { - return JqueryWidget.__super__.constructor.apply(this, arguments); + Tree.prototype.addNodeToIndex = function(node) { + if (node.id) { + return this.id_mapping[node.id] = node; + } + }; + + Tree.prototype.removeNodeFromIndex = function(node) { + if (node.id) { + return delete this.id_mapping[node.id]; + } + }; + + return Tree; + + })(Node); + + this.Tree.Tree = Tree; + + TRIANGLE_RIGHT = '&#x25ba;'; + + TRIANGLE_DOWN = '&#x25bc;'; + + JqTreeWidget = (function(_super) { + + __extends(JqTreeWidget, _super); + + function JqTreeWidget() { + return JqTreeWidget.__super__.constructor.apply(this, arguments); } - JqueryWidget.prototype.defaults = { + JqTreeWidget.prototype.defaults = { autoOpen: false, saveState: false, dragAndDrop: false, selectable: false, onCanSelectNode: null, onSetStateFromStorage: null, onGetStateFromStorage: null, onCreateLi: null, onIsMoveHandle: null, onCanMove: null, - onCanMoveTo: null + onCanMoveTo: null, + autoEscape: true, + dataUrl: null }; - JqueryWidget.prototype.toggle = function(node, on_finished) { - if (node.hasChildren()) { - new FolderElement(node).toggle(on_finished); + JqTreeWidget.prototype.toggle = function(node) { + if (node.is_open) { + return this.closeNode(node); + } else { + return this.openNode(node); } - if (this.options.saveState) { - return this._saveState(); - } }; - JqueryWidget.prototype.getTree = function() { + JqTreeWidget.prototype.getTree = function() { return this.tree; }; - JqueryWidget.prototype.selectNode = function(node, must_open_parents) { - var parent; - if (this.options.selectable) { - if (this.selected_node) { - this._getNodeElementForNode(this.selected_node).deselect(); - } - this._getNodeElementForNode(node).select(); - this.selected_node = node; - if (must_open_parents) { - parent = this.selected_node.parent; - while (parent) { - if (!parent.is_open) { - this.openNode(parent, null, true); - } - parent = parent.parent; - } - } - if (this.options.saveState) { - return this._saveState(); - } - } + JqTreeWidget.prototype.selectNode = function(node, must_open_parents) { + return this.select_node_handler.selectNode(node, must_open_parents); }; - JqueryWidget.prototype.getSelectedNode = function() { + JqTreeWidget.prototype.getSelectedNode = function() { return this.selected_node || false; }; - JqueryWidget.prototype.toJson = function() { - return toJson(this.tree.getData()); + JqTreeWidget.prototype.toJson = function() { + return JSON.stringify(this.tree.getData()); }; - JqueryWidget.prototype.loadData = function(data, parent_node) { - var $div, $element, child, subtree, _i, _len, _ref; + JqTreeWidget.prototype.loadData = function(data_or_url, parent_node, on_finished) { + var data, data_url; + if (typeof data_or_url === 'string') { + data_url = data_or_url; + return this._loadDataFromServer(data_url, parent_node, on_finished); + } else { + data = data_or_url; + this._loadData(data, parent_node); + if (on_finished) { + return on_finished(); + } + } + }; + + JqTreeWidget.prototype._loadData = function(data, parent_node) { + var child, subtree, _i, _len, _ref; + this._triggerEvent('tree.load_data', { + tree_data: data + }); if (!parent_node) { - return this._initTree(data); + this._initTree(data); } else { - subtree = new Node(); + subtree = new Node(''); + subtree._setParent(parent_node.tree); subtree.loadFromData(data); _ref = subtree.children; for (_i = 0, _len = _ref.length; _i < _len; _i++) { child = _ref[_i]; parent_node.addChild(child); } - $element = $(parent_node.element); - $element.children('ul').detach(); - this._createDomElements(parent_node, $element); - $div = $element.children('div'); - if (!$div.find('.toggler').length) { - return $div.prepend('<a class="toggler">&raquo;</a>'); - } + this._refreshElements(parent_node.parent); } + if (this.is_dragging) { + return this.dnd_handler.refreshHitAreas(); + } }; - JqueryWidget.prototype.getNodeById = function(node_id) { - var result; - result = null; - this.tree.iterate(function(node) { - if (node.id === node_id) { - result = node; - return false; + JqTreeWidget.prototype._loadDataFromServer = function(data_url, parent_node, on_finished) { + var $li, folder_element, + _this = this; + if (!data_url) { + return; + } + if (parent_node) { + folder_element = new FolderElement(parent_node, this); + $li = folder_element.getLi(); + $li.addClass('jqtree-loading'); + } else { + $li = null; + } + return $.ajax({ + url: data_url, + cache: false, + success: function(response) { + var data; + if ($.isArray(response) || typeof response === 'object') { + data = response; + } else { + data = $.parseJSON(response); + } + if ($li) { + $li.removeClass('loading'); + } + _this._loadData(data, parent_node); + if (on_finished) { + return on_finished(); + } + } + }); + }; + + JqTreeWidget.prototype.getNodeById = function(node_id) { + return this.tree.getNodeById(node_id); + }; + + JqTreeWidget.prototype.getNodeByName = function(name) { + return this.tree.getNodeByName(name); + }; + + JqTreeWidget.prototype.openNode = function(node, skip_slide) { + return this._openNode(node, skip_slide); + }; + + JqTreeWidget.prototype._openNode = function(node, skip_slide, on_finished) { + var folder_element; + if (node.isFolder()) { + if (node.load_on_demand) { + return this._loadFolderOnDemand(node, skip_slide, on_finished); } else { - return true; + folder_element = new FolderElement(node, this); + folder_element.open(on_finished, skip_slide); + return this._saveState(); } + } + }; + + JqTreeWidget.prototype._loadFolderOnDemand = function(node, skip_slide, on_finished) { + var _this = this; + node.load_on_demand = false; + return this.loadData(this._getDataUrl(node), node, function() { + return _this._openNode(node, skip_slide, on_finished); }); - return result; }; - JqueryWidget.prototype.openNode = function(node, on_finished, skip_slide) { - if (node.hasChildren()) { - return new FolderElement(node).open(on_finished, skip_slide); + JqTreeWidget.prototype.closeNode = function(node, skip_slide) { + if (node.isFolder()) { + new FolderElement(node, this).close(skip_slide); + return this._saveState(); } }; - JqueryWidget.prototype._init = function() { - JqueryWidget.__super__._init.apply(this, arguments); + JqTreeWidget.prototype.isDragging = function() { + return this.is_dragging; + }; + + JqTreeWidget.prototype.refreshHitAreas = function() { + return this.dnd_handler.refreshHitAreas(); + }; + + JqTreeWidget.prototype.addNodeAfter = function(new_node_info, existing_node) { + var new_node; + new_node = existing_node.addAfter(new_node_info); + this._refreshElements(existing_node.parent); + return new_node; + }; + + JqTreeWidget.prototype.addNodeBefore = function(new_node_info, existing_node) { + var new_node; + new_node = existing_node.addBefore(new_node_info); + this._refreshElements(existing_node.parent); + return new_node; + }; + + JqTreeWidget.prototype.addParentNode = function(new_node_info, existing_node) { + var new_node; + new_node = existing_node.addParent(new_node_info); + this._refreshElements(new_node.parent); + return new_node; + }; + + JqTreeWidget.prototype.removeNode = function(node) { + var parent; + parent = node.parent; + if (parent) { + node.remove(); + return this._refreshElements(parent.parent); + } + }; + + JqTreeWidget.prototype.appendNode = function(new_node_info, parent_node) { + var is_already_root_node, node; + if (!parent_node) { + parent_node = this.tree; + } + is_already_root_node = parent_node.isFolder(); + node = parent_node.append(new_node_info); + if (is_already_root_node) { + this._refreshElements(parent_node); + } else { + this._refreshElements(parent_node.parent); + } + return node; + }; + + JqTreeWidget.prototype.prependNode = function(new_node_info, parent_node) { + var node; + if (!parent_node) { + parent_node = this.tree; + } + node = parent_node.prepend(new_node_info); + this._refreshElements(parent_node); + return node; + }; + + JqTreeWidget.prototype.updateNode = function(node, data) { + node.setData(data); + this._refreshElements(node.parent); + return this.select_node_handler.selectCurrentNode(); + }; + + JqTreeWidget.prototype.moveNode = function(node, target_node, position) { + var position_index; + position_index = Position.nameToIndex(position); + this.tree.moveNode(node, target_node, position_index); + return this._refreshElements(); + }; + + JqTreeWidget.prototype.getStateFromStorage = function() { + return this.save_state_handler.getStateFromStorage(); + }; + + JqTreeWidget.prototype._init = function() { + JqTreeWidget.__super__._init.call(this); this.element = this.$el; - this._initTree(this.options.data); + this.selected_node = null; + this.mouse_delay = 300; + this.save_state_handler = new SaveStateHandler(this); + this.select_node_handler = new SelectNodeHandler(this); + this.dnd_handler = new DragAndDropHandler(this); + this._initData(); this.element.click($.proxy(this._click, this)); - this.element.bind('contextmenu', $.proxy(this._contextmenu, this)); - this.hovered_area = null; - this.$ghost = null; - return this.hit_areas = []; + return this.element.bind('contextmenu', $.proxy(this._contextmenu, this)); }; - JqueryWidget.prototype._deinit = function() { + JqTreeWidget.prototype._deinit = function() { this.element.empty(); this.element.unbind(); this.tree = null; - return JqueryWidget.__super__._deinit.apply(this, arguments); + return JqTreeWidget.__super__._deinit.call(this); }; - JqueryWidget.prototype._initTree = function(data) { - var node_element; - this.tree = new Node(); - this.tree.loadFromData(data); - this.selected_node = null; - this._openNodes(); - this._createDomElements(this.tree); - if (this.selected_node) { - node_element = this._getNodeElementForNode(this.selected_node); - if (node_element) { - return node_element.select(); + JqTreeWidget.prototype._initData = function() { + if (this.options.data) { + return this.loadData(this.options.data); + } else { + return this.loadData(this._getDataUrl()); + } + }; + + JqTreeWidget.prototype._getDataUrl = function(node) { + var data_url; + data_url = this.options.dataUrl || this.element.data('url'); + if ($.isFunction(data_url)) { + return data_url(node); + } else { + if (node) { + data_url += "?node=" + node.id; } + return data_url; } }; - JqueryWidget.prototype._openNodes = function() { + JqTreeWidget.prototype._initTree = function(data) { + this.tree = new Tree(); + this.tree.loadFromData(data); + this._openNodes(); + this._refreshElements(); + this.select_node_handler.selectCurrentNode(); + return this._triggerEvent('tree.init'); + }; + + JqTreeWidget.prototype._openNodes = function() { var max_level; if (this.options.saveState) { - if (this._restoreState()) { + if (this.save_state_handler.restoreState()) { return; } } if (this.options.autoOpen === false) { return; @@ -762,328 +1060,697 @@ node.is_open = true; return level !== max_level; }); }; - JqueryWidget.prototype._createDomElements = function(tree, $element) { - var createFolderLi, createLi, createNodeLi, createUl, depth, doCreateDomElements, + JqTreeWidget.prototype._refreshElements = function(from_node) { + var $element, createFolderLi, createLi, createNodeLi, createUl, doCreateDomElements, escapeIfNecessary, is_root_node, node_element, _this = this; - createUl = function(depth, is_open) { + if (from_node == null) { + from_node = null; + } + escapeIfNecessary = function(value) { + if (_this.options.autoEscape) { + return html_escape(value); + } else { + return value; + } + }; + createUl = function(is_root_node) { var class_string; - if (depth) { - class_string = ''; + if (is_root_node) { + class_string = ' class="jqtree-tree"'; } else { - class_string = ' class="tree"'; + class_string = ''; } return $("<ul" + class_string + "></ul>"); }; createLi = function(node) { var $li; - if (node.hasChildren()) { + if (node.isFolder()) { $li = createFolderLi(node); } else { $li = createNodeLi(node); } if (_this.options.onCreateLi) { _this.options.onCreateLi(node, $li); } return $li; }; createNodeLi = function(node) { - return $("<li><div><span class=\"title\">" + node.name + "</span></div></li>"); + var escaped_name; + escaped_name = escapeIfNecessary(node.name); + return $("<li><div><span class=\"jqtree-title\">" + escaped_name + "</span></div></li>"); }; createFolderLi = function(node) { - var button_class, folder_class, getButtonClass, getFolderClass; - getButtonClass = function() { + var button_char, button_classes, escaped_name, folder_classes, getButtonClasses, getFolderClasses; + getButtonClasses = function() { var classes; - classes = ['toggler']; + classes = ['jqtree-toggler']; if (!node.is_open) { - classes.push('closed'); + classes.push('jqtree-closed'); } return classes.join(' '); }; - getFolderClass = function() { + getFolderClasses = function() { var classes; - classes = ['folder']; + classes = ['jqtree-folder']; if (!node.is_open) { - classes.push('closed'); + classes.push('jqtree-closed'); } return classes.join(' '); }; - button_class = getButtonClass(); - folder_class = getFolderClass(); - return $("<li class=\"" + folder_class + "\"><div><a class=\"" + button_class + "\">&raquo;</a><span class=\"title\">" + node.name + "</span></div></li>"); + button_classes = getButtonClasses(); + folder_classes = getFolderClasses(); + escaped_name = escapeIfNecessary(node.name); + if (node.is_open) { + button_char = TRIANGLE_DOWN; + } else { + button_char = TRIANGLE_RIGHT; + } + return $("<li class=\"" + folder_classes + "\"><div><a class=\"" + button_classes + "\">" + button_char + "</a><span class=\"jqtree-title\">" + escaped_name + "</span></div></li>"); }; - doCreateDomElements = function($element, children, depth, is_open) { - var $li, $ul, child, _i, _len, _results; - $ul = createUl(depth, is_open); + doCreateDomElements = function($element, children, is_root_node, is_open) { + var $li, $ul, child, _i, _len; + $ul = createUl(is_root_node); $element.append($ul); - _results = []; for (_i = 0, _len = children.length; _i < _len; _i++) { child = children[_i]; $li = createLi(child); $ul.append($li); child.element = $li[0]; $li.data('node', child); if (child.hasChildren()) { - _results.push(doCreateDomElements($li, child.children, depth + 1, child.is_open)); - } else { - _results.push(void 0); + doCreateDomElements($li, child.children, false, child.is_open); } } - return _results; + return null; }; - if ($element) { - depth = 1; + if (from_node && from_node.parent) { + is_root_node = false; + node_element = this._getNodeElementForNode(from_node); + node_element.getUl().remove(); + $element = node_element.$element; } else { + from_node = this.tree; $element = this.element; $element.empty(); - depth = 0; + is_root_node = true; } - return doCreateDomElements($element, tree.children, depth, true); + doCreateDomElements($element, from_node.children, is_root_node, is_root_node); + return this._triggerEvent('tree.refresh'); }; - JqueryWidget.prototype._click = function(e) { - var $target, event, node, node_element, - _this = this; + JqTreeWidget.prototype._click = function(e) { + var $target, node; if (e.ctrlKey) { return; } $target = $(e.target); - if ($target.is('.toggler')) { - node_element = this._getNodeElement($target); - if (node_element && node_element.node.hasChildren()) { - node_element.toggle(function() { - var event, event_name, node; - node = node_element.node; - if (node.is_open) { - event_name = 'tree.open'; - } else { - event_name = 'tree.close'; - } - event = $.Event(event_name); - event.node = node; - return _this.element.trigger(event); - }); - if (this.options.saveState) { - this._saveState(); - } + if ($target.is('.jqtree-toggler')) { + node = this._getNode($target); + if (node) { + this.toggle(node); e.preventDefault(); return e.stopPropagation(); } } else if ($target.is('div') || $target.is('span')) { node = this._getNode($target); if (node) { - if ((!this.options.onCanSelectNode) || this.options.onCanSelectNode(node)) { - this.selectNode(node); - event = $.Event('tree.click'); - event.node = node; - return this.element.trigger(event); - } + this._triggerEvent('tree.click', { + node: node + }); + return this.selectNode(node); } } }; - JqueryWidget.prototype._getNode = function($element) { + JqTreeWidget.prototype._getNode = function($element) { var $li; $li = $element.closest('li'); if ($li.length === 0) { return null; } else { return $li.data('node'); } }; - JqueryWidget.prototype._restoreState = function() { - var state; - if (this.options.onGetStateFromStorage) { - state = this.options.onGetStateFromStorage(); + JqTreeWidget.prototype._getNodeElementForNode = function(node) { + if (node.isFolder()) { + return new FolderElement(node, this); } else { - if ($.cookie) { - state = $.cookie(this._getCookieName(), { - path: '/' + return new NodeElement(node, this); + } + }; + + JqTreeWidget.prototype._getNodeElement = function($element) { + var node; + node = this._getNode($element); + if (node) { + return this._getNodeElementForNode(node); + } else { + return null; + } + }; + + JqTreeWidget.prototype._contextmenu = function(e) { + var $div, node; + $div = $(e.target).closest('ul.jqtree-tree div'); + if ($div.length) { + node = this._getNode($div); + if (node) { + e.preventDefault(); + e.stopPropagation(); + this._triggerEvent('tree.contextmenu', { + node: node, + click_event: e }); - } else { - state = null; + return false; } } - if (!state) { + }; + + JqTreeWidget.prototype._saveState = function() { + if (this.options.saveState) { + return this.save_state_handler.saveState(); + } + }; + + JqTreeWidget.prototype._mouseCapture = function(event) { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseCapture(event); + } else { return false; + } + }; + + JqTreeWidget.prototype._mouseStart = function(event) { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseStart(event); } else { - this._setState(state); - return true; + return false; } }; - JqueryWidget.prototype._saveState = function() { - if (this.options.onSetStateFromStorage) { - return this.options.onSetStateFromStorage(this._getState()); + JqTreeWidget.prototype._mouseDrag = function(event) { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseDrag(event); } else { - if ($.cookie) { - return $.cookie(this._getCookieName(), this._getState(), { - path: '/' + return false; + } + }; + + JqTreeWidget.prototype._mouseStop = function() { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseStop(); + } else { + return false; + } + }; + + JqTreeWidget.prototype._triggerEvent = function(event_name, values) { + var event; + event = $.Event(event_name); + $.extend(event, values); + this.element.trigger(event); + return event; + }; + + JqTreeWidget.prototype.testGenerateHitAreas = function(moving_node) { + this.dnd_handler.current_item = this._getNodeElementForNode(moving_node); + this.dnd_handler.generateHitAreas(); + return this.dnd_handler.hit_areas; + }; + + return JqTreeWidget; + + })(MouseWidget); + + SimpleWidget.register(JqTreeWidget, 'tree'); + + GhostDropHint = (function() { + + function GhostDropHint(node, $element, position) { + this.$element = $element; + this.node = node; + this.$ghost = $('<li class="jqtree-ghost"><span class="jqtree-circle"></span><span class="jqtree-line"></span></li>'); + if (position === Position.AFTER) { + this.moveAfter(); + } else if (position === Position.BEFORE) { + this.moveBefore(); + } else if (position === Position.INSIDE) { + if (node.isFolder() && node.is_open) { + this.moveInsideOpenFolder(); + } else { + this.moveInside(); + } + } + } + + GhostDropHint.prototype.remove = function() { + return this.$ghost.remove(); + }; + + GhostDropHint.prototype.moveAfter = function() { + return this.$element.after(this.$ghost); + }; + + GhostDropHint.prototype.moveBefore = function() { + return this.$element.before(this.$ghost); + }; + + GhostDropHint.prototype.moveInsideOpenFolder = function() { + return $(this.node.children[0].element).before(this.$ghost); + }; + + GhostDropHint.prototype.moveInside = function() { + this.$element.after(this.$ghost); + return this.$ghost.addClass('jqtree-inside'); + }; + + return GhostDropHint; + + })(); + + BorderDropHint = (function() { + + function BorderDropHint($element) { + var $div, width; + $div = $element.children('div'); + width = $element.width() - 4; + this.$hint = $('<span class="jqtree-border"></span>'); + $div.append(this.$hint); + this.$hint.css({ + width: width, + height: $div.height() - 4 + }); + } + + BorderDropHint.prototype.remove = function() { + return this.$hint.remove(); + }; + + return BorderDropHint; + + })(); + + NodeElement = (function() { + + function NodeElement(node, tree_widget) { + this.init(node, tree_widget); + } + + NodeElement.prototype.init = function(node, tree_widget) { + this.node = node; + this.tree_widget = tree_widget; + return this.$element = $(node.element); + }; + + NodeElement.prototype.getUl = function() { + return this.$element.children('ul:first'); + }; + + NodeElement.prototype.getSpan = function() { + return this.$element.children('div').find('span.jqtree-title'); + }; + + NodeElement.prototype.getLi = function() { + return this.$element; + }; + + NodeElement.prototype.addDropHint = function(position) { + if (position === Position.INSIDE) { + return new BorderDropHint(this.$element); + } else { + return new GhostDropHint(this.node, this.$element, position); + } + }; + + NodeElement.prototype.select = function() { + return this.getLi().addClass('jqtree-selected'); + }; + + NodeElement.prototype.deselect = function() { + return this.getLi().removeClass('jqtree-selected'); + }; + + return NodeElement; + + })(); + + FolderElement = (function(_super) { + + __extends(FolderElement, _super); + + function FolderElement() { + return FolderElement.__super__.constructor.apply(this, arguments); + } + + FolderElement.prototype.open = function(on_finished, skip_slide) { + var $button, doOpen, + _this = this; + if (!this.node.is_open) { + this.node.is_open = true; + $button = this.getButton(); + $button.removeClass('jqtree-closed'); + $button.html(TRIANGLE_DOWN); + doOpen = function() { + _this.getLi().removeClass('jqtree-closed'); + if (on_finished) { + on_finished(); + } + return _this.tree_widget._triggerEvent('tree.open', { + node: _this.node }); + }; + if (skip_slide) { + this.getUl().show(); + return doOpen(); + } else { + return this.getUl().slideDown('fast', doOpen); } } }; - JqueryWidget.prototype._getState = function() { + FolderElement.prototype.close = function(skip_slide) { + var $button, doClose, + _this = this; + if (this.node.is_open) { + this.node.is_open = false; + $button = this.getButton(); + $button.addClass('jqtree-closed'); + $button.html(TRIANGLE_RIGHT); + doClose = function() { + _this.getLi().addClass('jqtree-closed'); + return _this.tree_widget._triggerEvent('tree.close', { + node: _this.node + }); + }; + if (skip_slide) { + this.getUl().hide(); + return doClose(); + } else { + return this.getUl().slideUp('fast', doClose); + } + } + }; + + FolderElement.prototype.getButton = function() { + return this.$element.children('div').find('a.jqtree-toggler'); + }; + + FolderElement.prototype.addDropHint = function(position) { + if (!this.node.is_open && position === Position.INSIDE) { + return new BorderDropHint(this.$element); + } else { + return new GhostDropHint(this.node, this.$element, position); + } + }; + + return FolderElement; + + })(NodeElement); + + DragElement = (function() { + + function DragElement(node, offset_x, offset_y, $tree) { + this.offset_x = offset_x; + this.offset_y = offset_y; + this.$element = $("<span class=\"jqtree-title jqtree-dragging\">" + node.name + "</span>"); + this.$element.css("position", "absolute"); + $tree.append(this.$element); + } + + DragElement.prototype.move = function(page_x, page_y) { + return this.$element.offset({ + left: page_x - this.offset_x, + top: page_y - this.offset_y + }); + }; + + DragElement.prototype.remove = function() { + return this.$element.remove(); + }; + + return DragElement; + + })(); + + SaveStateHandler = (function() { + + function SaveStateHandler(tree_widget) { + this.tree_widget = tree_widget; + } + + SaveStateHandler.prototype.saveState = function() { + if (this.tree_widget.options.onSetStateFromStorage) { + return this.tree_widget.options.onSetStateFromStorage(this.getState()); + } else if (typeof localStorage !== "undefined" && localStorage !== null) { + return localStorage.setItem(this.getCookieName(), this.getState()); + } else if ($.cookie) { + return $.cookie(this.getCookieName(), this.getState(), { + path: '/' + }); + } + }; + + SaveStateHandler.prototype.restoreState = function() { + var state; + state = this.getStateFromStorage(); + if (state) { + this.setState(state); + return true; + } else { + return false; + } + }; + + SaveStateHandler.prototype.getStateFromStorage = function() { + if (this.tree_widget.options.onGetStateFromStorage) { + return this.tree_widget.options.onGetStateFromStorage(); + } else if (typeof localStorage !== "undefined" && localStorage !== null) { + return localStorage.getItem(this.getCookieName()); + } else if ($.cookie) { + return $.cookie(this.getCookieName(), { + path: '/' + }); + } else { + return null; + } + }; + + SaveStateHandler.prototype.getState = function() { var open_nodes, selected_node, _this = this; open_nodes = []; - this.tree.iterate(function(node) { + this.tree_widget.tree.iterate(function(node) { if (node.is_open && node.id && node.hasChildren()) { open_nodes.push(node.id); } return true; }); selected_node = ''; - if (this.selected_node) { - selected_node = this.selected_node.id; + if (this.tree_widget.selected_node) { + selected_node = this.tree_widget.selected_node.id; } - return toJson({ + return JSON.stringify({ open_nodes: open_nodes, selected_node: selected_node }); }; - JqueryWidget.prototype._setState = function(state) { + SaveStateHandler.prototype.setState = function(state) { var data, open_nodes, selected_node_id, _this = this; data = $.parseJSON(state); - open_nodes = data.open_nodes; - selected_node_id = data.selected_node; - return this.tree.iterate(function(node) { - if (node.id && node.hasChildren() && (indexOf(open_nodes, node.id) >= 0)) { - node.is_open = true; - } - if (selected_node_id && (node.id === selected_node_id)) { - _this.selected_node = node; - } - return true; - }); + if (data) { + open_nodes = data.open_nodes; + selected_node_id = data.selected_node; + return this.tree_widget.tree.iterate(function(node) { + if (node.id && node.hasChildren() && (indexOf(open_nodes, node.id) >= 0)) { + node.is_open = true; + } + if (selected_node_id && (node.id === selected_node_id)) { + _this.tree_widget.selected_node = node; + } + return true; + }); + } }; - JqueryWidget.prototype._getCookieName = function() { - if (typeof this.options.saveState === 'string') { - return this.options.saveState; + SaveStateHandler.prototype.getCookieName = function() { + if (typeof this.tree_widget.options.saveState === 'string') { + return this.tree_widget.options.saveState; } else { return 'tree'; } }; - JqueryWidget.prototype._getNodeElementForNode = function(node) { - if (node.hasChildren()) { - return new FolderElement(node); - } else { - return new NodeElement(node); - } - }; + return SaveStateHandler; - JqueryWidget.prototype._getNodeElement = function($element) { - var node; - node = this._getNode($element); - if (node) { - return this._getNodeElementForNode(node); - } else { - return null; + })(); + + SelectNodeHandler = (function() { + + function SelectNodeHandler(tree_widget) { + this.tree_widget = tree_widget; + } + + SelectNodeHandler.prototype.selectNode = function(node, must_open_parents) { + var canSelect, parent, + _this = this; + canSelect = function() { + if (!_this.tree_widget.options.selectable) { + return false; + } + if (!_this.tree_widget.options.onCanSelectNode) { + return true; + } + return _this.tree_widget.options.onCanSelectNode(node); + }; + if (canSelect()) { + if (this.tree_widget.selected_node) { + this.tree_widget._getNodeElementForNode(this.tree_widget.selected_node).deselect(); + this.tree_widget.selected_node = null; + } + if (node) { + this.tree_widget._getNodeElementForNode(node).select(); + this.tree_widget.selected_node = node; + this.tree_widget._triggerEvent('tree.select', { + node: node + }); + if (must_open_parents) { + parent = this.tree_widget.selected_node.parent; + while (parent) { + if (!parent.is_open) { + this.tree_widget.openNode(parent, true); + } + parent = parent.parent; + } + } + } + if (this.tree_widget.options.saveState) { + return this.tree_widget.save_state_handler.saveState(); + } } }; - JqueryWidget.prototype._contextmenu = function(e) { - var $div, event, node; - $div = $(e.target).closest('ul.tree div'); - if ($div.length) { - node = this._getNode($div); - if (node) { - e.preventDefault(); - e.stopPropagation(); - event = $.Event('tree.contextmenu'); - event.node = node; - event.click_event = e; - this.element.trigger(event); - return false; + SelectNodeHandler.prototype.selectCurrentNode = function() { + var node_element; + if (this.tree_widget.selected_node) { + node_element = this.tree_widget._getNodeElementForNode(this.tree_widget.selected_node); + if (node_element) { + return node_element.select(); } } }; - JqueryWidget.prototype._mouseCapture = function(event) { + return SelectNodeHandler; + + })(); + + DragAndDropHandler = (function() { + + function DragAndDropHandler(tree_widget) { + this.tree_widget = tree_widget; + this.hovered_area = null; + this.$ghost = null; + this.hit_areas = []; + this.is_dragging = false; + } + + DragAndDropHandler.prototype.mouseCapture = function(event) { var $element, node_element; - if (!this.options.dragAndDrop) { - return; - } $element = $(event.target); - if (this.options.onIsMoveHandle && !this.options.onIsMoveHandle($element)) { + if (this.tree_widget.options.onIsMoveHandle && !this.tree_widget.options.onIsMoveHandle($element)) { return null; } - node_element = this._getNodeElement($(event.target)); - if (node_element && this.options.onCanMove) { - if (!this.options.onCanMove(node_element.node)) { + node_element = this.tree_widget._getNodeElement($element); + if (node_element && this.tree_widget.options.onCanMove) { + if (!this.tree_widget.options.onCanMove(node_element.node)) { node_element = null; } } this.current_item = node_element; return this.current_item !== null; }; - JqueryWidget.prototype._mouseStart = function(event) { + DragAndDropHandler.prototype.mouseStart = function(event) { var offsetX, offsetY, _ref; - if (!this.options.dragAndDrop) { - return; - } - this._refreshHitAreas(); - _ref = this._getOffsetFromEvent(event), offsetX = _ref[0], offsetY = _ref[1]; - this.drag_element = new DragElement(this.current_item.node, offsetX, offsetY, this.element); - this.current_item.$element.addClass('moving'); + this.refreshHitAreas(); + _ref = this.getOffsetFromEvent(event), offsetX = _ref[0], offsetY = _ref[1]; + this.drag_element = new DragElement(this.current_item.node, offsetX, offsetY, this.tree_widget.element); + this.is_dragging = true; + this.current_item.$element.addClass('jqtree-moving'); return true; }; - JqueryWidget.prototype._mouseDrag = function(event) { + DragAndDropHandler.prototype.mouseDrag = function(event) { var area, position_name; - if (!this.options.dragAndDrop) { - return; - } this.drag_element.move(event.pageX, event.pageY); - area = this._findHoveredArea(event.pageX, event.pageY); - if (area && this.options.onCanMoveTo) { + area = this.findHoveredArea(event.pageX, event.pageY); + if (area && this.tree_widget.options.onCanMoveTo) { position_name = Position.getName(area.position); - if (!this.options.onCanMoveTo(this.current_item.node, area.node, position_name)) { + if (!this.tree_widget.options.onCanMoveTo(this.current_item.node, area.node, position_name)) { area = null; } } if (!area) { - this._removeDropHint(); - this._removeHover(); - this._stopOpenFolderTimer(); + this.removeDropHint(); + this.removeHover(); + this.stopOpenFolderTimer(); } else { if (this.hovered_area !== area) { this.hovered_area = area; - this._updateDropHint(); + this.updateDropHint(); } } return true; }; - JqueryWidget.prototype._mouseStop = function() { - if (!this.options.dragAndDrop) { - return; - } - this._moveItem(); - this._clear(); - this._removeHover(); - this._removeDropHint(); - this._removeHitAreas(); - this.current_item.$element.removeClass('moving'); + DragAndDropHandler.prototype.mouseStop = function() { + this.moveItem(); + this.clear(); + this.removeHover(); + this.removeDropHint(); + this.removeHitAreas(); + this.current_item.$element.removeClass('jqtree-moving'); + this.is_dragging = false; return false; }; - JqueryWidget.prototype._refreshHitAreas = function() { - this._removeHitAreas(); - return this._generateHitAreas(); + DragAndDropHandler.prototype.getOffsetFromEvent = function(event) { + var element_offset; + element_offset = $(event.target).offset(); + return [event.pageX - element_offset.left, event.pageY - element_offset.top]; }; - JqueryWidget.prototype._generateHitAreas = function() { + DragAndDropHandler.prototype.refreshHitAreas = function() { + this.removeHitAreas(); + return this.generateHitAreas(); + }; + + DragAndDropHandler.prototype.removeHitAreas = function() { + return this.hit_areas = []; + }; + + DragAndDropHandler.prototype.clear = function() { + this.drag_element.remove(); + return this.drag_element = null; + }; + + DragAndDropHandler.prototype.removeDropHint = function() { + if (this.previous_ghost) { + return this.previous_ghost.remove(); + } + }; + + DragAndDropHandler.prototype.removeHover = function() { + return this.hovered_area = null; + }; + + DragAndDropHandler.prototype.generateHitAreas = function() { var addPosition, getTop, groupPositions, handleAfterOpenFolder, handleClosedFolder, handleFirstNode, handleNode, handleOpenFolder, hit_areas, last_top, positions, _this = this; positions = []; last_top = 0; getTop = function($element) { @@ -1110,11 +1777,11 @@ previous_top = position.top; group = []; } group.push(position); } - return handle_group(group, previous_top, _this.element.offset().top + _this.element.height()); + return handle_group(group, previous_top, _this.tree_widget.element.offset().top + _this.tree_widget.element.height()); }; handleNode = function(node, next_node, $element) { var top; top = getTop($element); if (node === _this.current_item.node) { @@ -1159,37 +1826,32 @@ handleFirstNode = function(node, $element) { if (node !== _this.current_item.node) { return addPosition(node, Position.BEFORE, getTop($(node.element))); } }; - this._iterateVisibleNodes(handleNode, handleOpenFolder, handleClosedFolder, handleAfterOpenFolder, handleFirstNode); + this.iterateVisibleNodes(handleNode, handleOpenFolder, handleClosedFolder, handleAfterOpenFolder, handleFirstNode); hit_areas = []; groupPositions(function(positions_in_group, top, bottom) { - var area_height, area_top, position, _i, _len, _results; + var area_height, area_top, position, _i, _len; area_height = (bottom - top) / positions_in_group.length; area_top = top; - _results = []; for (_i = 0, _len = positions_in_group.length; _i < _len; _i++) { position = positions_in_group[_i]; hit_areas.push({ top: area_top, bottom: area_top + area_height, node: position.node, position: position.position }); - _results.push(area_top += area_height); + area_top += area_height; } - return _results; + return null; }); return this.hit_areas = hit_areas; }; - JqueryWidget.prototype._removeHitAreas = function() { - return this.hit_areas = []; - }; - - JqueryWidget.prototype._iterateVisibleNodes = function(handle_node, handle_open_folder, handle_closed_folder, handle_after_open_folder, handle_first_node) { + DragAndDropHandler.prototype.iterateVisibleNodes = function(handle_node, handle_open_folder, handle_closed_folder, handle_after_open_folder, handle_first_node) { var is_first_node, iterate, _this = this; is_first_node = true; iterate = function(node, next_node) { var $element, child, children_length, i, must_iterate_inside, _i, _len, _ref; @@ -1227,23 +1889,17 @@ if (node.is_open) { return handle_after_open_folder(node, next_node, $element); } } }; - return iterate(this.tree); + return iterate(this.tree_widget.tree); }; - JqueryWidget.prototype._getOffsetFromEvent = function(event) { - var element_offset; - element_offset = $(event.target).offset(); - return [event.pageX - element_offset.left, event.pageY - element_offset.top]; - }; - - JqueryWidget.prototype._findHoveredArea = function(x, y) { + DragAndDropHandler.prototype.findHoveredArea = function(x, y) { var area, high, low, mid, tree_offset; - tree_offset = this.element.offset(); - if (x < tree_offset.left || y < tree_offset.top || x > (tree_offset.left + this.element.width()) || y > (tree_offset.top + this.element.height())) { + tree_offset = this.tree_widget.element.offset(); + if (x < tree_offset.left || y < tree_offset.top || x > (tree_offset.left + this.tree_widget.element.width()) || y > (tree_offset.top + this.tree_widget.element.height())) { return null; } low = 0; high = this.hit_areas.length; while (low < high) { @@ -1258,294 +1914,77 @@ } } return null; }; - JqueryWidget.prototype._updateDropHint = function() { + DragAndDropHandler.prototype.updateDropHint = function() { var node, node_element; - this._stopOpenFolderTimer(); + this.stopOpenFolderTimer(); if (!this.hovered_area) { return; } node = this.hovered_area.node; - if (node.hasChildren() && !node.is_open && this.hovered_area.position === Position.INSIDE) { - this._startOpenFolderTimer(node); + if (node.isFolder() && !node.is_open && this.hovered_area.position === Position.INSIDE) { + this.startOpenFolderTimer(node); } - this._removeDropHint(); - node_element = this._getNodeElementForNode(this.hovered_area.node); + this.removeDropHint(); + node_element = this.tree_widget._getNodeElementForNode(this.hovered_area.node); return this.previous_ghost = node_element.addDropHint(this.hovered_area.position); }; - JqueryWidget.prototype._startOpenFolderTimer = function(folder) { + DragAndDropHandler.prototype.startOpenFolderTimer = function(folder) { var openFolder, _this = this; openFolder = function() { - return _this._getNodeElementForNode(folder).open(function() { - _this._refreshHitAreas(); - return _this._updateDropHint(); + return _this.tree_widget._openNode(folder, false, function() { + _this.refreshHitAreas(); + return _this.updateDropHint(); }); }; return this.open_folder_timer = setTimeout(openFolder, 500); }; - JqueryWidget.prototype._stopOpenFolderTimer = function() { + DragAndDropHandler.prototype.stopOpenFolderTimer = function() { if (this.open_folder_timer) { clearTimeout(this.open_folder_timer); return this.open_folder_timer = null; } }; - JqueryWidget.prototype._removeDropHint = function() { - if (this.previous_ghost) { - return this.previous_ghost.remove(); - } - }; - - JqueryWidget.prototype._removeHover = function() { - return this.hovered_area = null; - }; - - JqueryWidget.prototype._moveItem = function() { - var event, moved_node, position, previous_parent, target_node; + DragAndDropHandler.prototype.moveItem = function() { + var doMove, event, moved_node, position, previous_parent, target_node, + _this = this; if (this.hovered_area && this.hovered_area.position !== Position.NONE) { moved_node = this.current_item.node; target_node = this.hovered_area.node; position = this.hovered_area.position; previous_parent = moved_node.parent; - this.tree.moveNode(moved_node, target_node, position); if (position === Position.INSIDE) { this.hovered_area.node.is_open = true; } - event = $.Event('tree.move'); - event.move_info = { - moved_node: moved_node, - target_node: target_node, - position: Position.getName(position), - previous_parent: previous_parent + doMove = function() { + _this.tree_widget.tree.moveNode(moved_node, target_node, position); + _this.tree_widget.element.empty(); + return _this.tree_widget._refreshElements(); }; - this.element.trigger(event); - this.element.empty(); - return this._createDomElements(this.tree); - } - }; - - JqueryWidget.prototype._clear = function() { - this.drag_element.remove(); - return this.drag_element = null; - }; - - return JqueryWidget; - - })(MouseWidget); - - SimpleWidget.register(JqueryWidget, 'tree'); - - GhostDropHint = (function() { - - GhostDropHint.name = 'GhostDropHint'; - - function GhostDropHint(node, $element, position) { - this.$element = $element; - this.node = node; - this.$ghost = $('<li class="ghost"><span class="circle"></span><span class="line"></span></li>'); - if (position === Position.AFTER) { - this.moveAfter(); - } else if (position === Position.BEFORE) { - this.moveBefore(); - } else if (position === Position.INSIDE) { - if (node.hasChildren() && node.is_open) { - this.moveInsideOpenFolder(); - } else { - this.moveInside(); + event = this.tree_widget._triggerEvent('tree.move', { + move_info: { + moved_node: moved_node, + target_node: target_node, + position: Position.getName(position), + previous_parent: previous_parent, + do_move: doMove + } + }); + if (!event.isDefaultPrevented()) { + return doMove(); } } - } - - GhostDropHint.prototype.remove = function() { - return this.$ghost.remove(); }; - GhostDropHint.prototype.moveAfter = function() { - return this.$element.after(this.$ghost); - }; + return DragAndDropHandler; - GhostDropHint.prototype.moveBefore = function() { - return this.$element.before(this.$ghost); - }; - - GhostDropHint.prototype.moveInsideOpenFolder = function() { - return $(this.node.children[0].element).before(this.$ghost); - }; - - GhostDropHint.prototype.moveInside = function() { - this.$element.after(this.$ghost); - return this.$ghost.addClass('inside'); - }; - - return GhostDropHint; - })(); - BorderDropHint = (function() { - - BorderDropHint.name = 'BorderDropHint'; - - function BorderDropHint($element) { - var $div, width; - $div = $element.children('div'); - width = $element.width() - 4; - this.$hint = $('<span class="border"></span>'); - $div.append(this.$hint); - this.$hint.css({ - width: width, - height: $div.height() - 4 - }); - } - - BorderDropHint.prototype.remove = function() { - return this.$hint.remove(); - }; - - return BorderDropHint; - - })(); - - NodeElement = (function() { - - NodeElement.name = 'NodeElement'; - - function NodeElement(node) { - this.init(node); - } - - NodeElement.prototype.init = function(node) { - this.node = node; - return this.$element = $(node.element); - }; - - NodeElement.prototype.getUl = function() { - return this.$element.children('ul:first'); - }; - - NodeElement.prototype.getSpan = function() { - return this.$element.children('div').find('span.title'); - }; - - NodeElement.prototype.getLi = function() { - return this.$element; - }; - - NodeElement.prototype.addDropHint = function(position) { - if (position === Position.INSIDE) { - return new BorderDropHint(this.$element); - } else { - return new GhostDropHint(this.node, this.$element, position); - } - }; - - NodeElement.prototype.select = function() { - return this.getLi().addClass('selected'); - }; - - NodeElement.prototype.deselect = function() { - return this.getLi().removeClass('selected'); - }; - - return NodeElement; - - })(); - - FolderElement = (function(_super) { - - __extends(FolderElement, _super); - - FolderElement.name = 'FolderElement'; - - function FolderElement() { - return FolderElement.__super__.constructor.apply(this, arguments); - } - - FolderElement.prototype.toggle = function(on_finished) { - if (this.node.is_open) { - return this.close(on_finished); - } else { - return this.open(on_finished); - } - }; - - FolderElement.prototype.open = function(on_finished, skip_slide) { - var doOpen, - _this = this; - this.node.is_open = true; - this.getButton().removeClass('closed'); - doOpen = function() { - _this.getLi().removeClass('closed'); - if (on_finished) { - return on_finished(); - } - }; - if (skip_slide) { - this.getUl().show(); - return doOpen(); - } else { - return this.getUl().slideDown('fast', doOpen); - } - }; - - FolderElement.prototype.close = function(on_finished) { - var _this = this; - this.node.is_open = false; - this.getButton().addClass('closed'); - return this.getUl().slideUp('fast', function() { - _this.getLi().addClass('closed'); - if (on_finished) { - return on_finished(); - } - }); - }; - - FolderElement.prototype.getButton = function() { - return this.$element.children('div').find('a.toggler'); - }; - - FolderElement.prototype.addDropHint = function(position) { - if (!this.node.is_open && position === Position.INSIDE) { - return new BorderDropHint(this.$element); - } else { - return new GhostDropHint(this.node, this.$element, position); - } - }; - - return FolderElement; - - })(NodeElement); - - DragElement = (function() { - - DragElement.name = 'DragElement'; - - function DragElement(node, offset_x, offset_y, $tree) { - this.offset_x = offset_x; - this.offset_y = offset_y; - this.$element = $("<span class=\"title tree-dragging\">" + node.name + "</span>"); - this.$element.css("position", "absolute"); - $tree.append(this.$element); - } - - DragElement.prototype.move = function(page_x, page_y) { - return this.$element.offset({ - left: page_x - this.offset_x, - top: page_y - this.offset_y - }); - }; - - DragElement.prototype.remove = function() { - return this.$element.remove(); - }; - - return DragElement; - - })(); - this.Tree.Node = Node; -}).call(this); \ No newline at end of file +}).call(this);