diff PalanthirExplorer/libs/tree.jquery.js @ 45:33d67e1ab173

r
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 05 Sep 2012 13:24:59 +0200
parents PalantirExplorer/libs/tree.jquery.js@3959d33612cc
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PalanthirExplorer/libs/tree.jquery.js	Wed Sep 05 13:24:59 2012 +0200
@@ -0,0 +1,1837 @@
+// Generated by CoffeeScript 1.3.3
+
+/*
+Copyright 2012 Marco Braak
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+(function() {
+  var $, BorderDropHint, DragAndDropHandler, DragElement, FolderElement, GhostDropHint, JqTreeWidget, Json, MouseWidget, Node, NodeElement, Position, SaveStateHandler, SelectNodeHandler, SimpleWidget, Tree, html_escape, indexOf, toJson,
+    __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; };
+
+  $ = this.jQuery;
+
+  SimpleWidget = (function() {
+
+    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();
+    };
+
+    SimpleWidget.prototype._init = function() {
+      return null;
+    };
+
+    SimpleWidget.prototype._deinit = function() {
+      return null;
+    };
+
+    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);
+          }
+        });
+        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 $.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 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.
+  */
+
+
+  MouseWidget = (function(_super) {
+
+    __extends(MouseWidget, _super);
+
+    function MouseWidget() {
+      return MouseWidget.__super__.constructor.apply(this, arguments);
+    }
+
+    MouseWidget.is_mouse_handled = false;
+
+    MouseWidget.prototype._init = function() {
+      this.$el.bind('mousedown.mousewidget', $.proxy(this._mouseDown, this));
+      return this.is_mouse_started = false;
+    };
+
+    MouseWidget.prototype._deinit = function() {
+      var $document;
+      this.$el.unbind('mousedown.mousewidget');
+      $document = $(document);
+      $document.unbind('mousemove.mousewidget');
+      return $document.unbind('mouseup.mousewidget');
+    };
+
+    MouseWidget.prototype._mouseDown = function(e) {
+      var $document;
+      if (MouseWidget.is_mouse_handled) {
+        return;
+      }
+      if (!this.is_mouse_started) {
+        this._mouseUp(e);
+      }
+      if (e.which !== 1) {
+        return;
+      }
+      if (!this._mouseCapture(e)) {
+        return;
+      }
+      this.mouse_down_event = e;
+      $document = $(document);
+      $document.bind('mousemove.mousewidget', $.proxy(this._mouseMove, this));
+      $document.bind('mouseup.mousewidget', $.proxy(this._mouseUp, this));
+      e.preventDefault();
+      this.is_mouse_handled = true;
+      return true;
+    };
+
+    MouseWidget.prototype._mouseMove = function(e) {
+      if (this.is_mouse_started) {
+        this._mouseDrag(e);
+        return e.preventDefault();
+      }
+      this.is_mouse_started = this._mouseStart(this.mouse_down_event) !== false;
+      if (this.is_mouse_started) {
+        this._mouseDrag(e);
+      } else {
+        this._mouseUp(e);
+      }
+      return !this.is_mouse_started;
+    };
+
+    MouseWidget.prototype._mouseUp = function(e) {
+      var $document;
+      $document = $(document);
+      $document.unbind('mousemove.mousewidget');
+      $document.unbind('mouseup.mousewidget');
+      if (this.is_mouse_started) {
+        this.is_mouse_started = false;
+        this._mouseStop(e);
+      }
+      return false;
+    };
+
+    MouseWidget.prototype._mouseCapture = function(e) {
+      return true;
+    };
+
+    MouseWidget.prototype._mouseStart = function(e) {
+      return null;
+    };
+
+    MouseWidget.prototype._mouseDrag = function(e) {
+      return null;
+    };
+
+    MouseWidget.prototype._mouseStop = function(e) {
+      return null;
+    };
+
+    return MouseWidget;
+
+  })(SimpleWidget);
+
+  /*
+  Copyright 2012 Marco Braak
+  
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+  
+      http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  */
+
+
+  this.Tree = {};
+
+  $ = this.jQuery;
+
+  indexOf = function(array, item) {
+    var i, value, _i, _len;
+    if (array.indexOf) {
+      return array.indexOf(item);
+    } else {
+      for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) {
+        value = array[i];
+        if (value === item) {
+          return i;
+        }
+      }
+      return -1;
+    }
+  };
+
+  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];
+    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);
+      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';
+          }
+          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(',') + '}');
+    }
+  };
+
+  toJson = function(value) {
+    return Json.str('', {
+      '': value
+    });
+  };
+
+  this.Tree.toJson = toJson;
+
+  html_escape = function(string) {
+    return ('' + string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g, '&#x2F;');
+  };
+
+  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';
+      }
+    }
+  };
+
+  Position.BEFORE = 1;
+
+  Position.AFTER = 2;
+
+  Position.INSIDE = 3;
+
+  Position.NONE = 4;
+
+  this.Tree.Position = Position;
+
+  Node = (function() {
+
+    function Node(o) {
+      this.setData(o);
+    }
+
+    Node.prototype.setData = function(o) {
+      var key, value;
+      if (typeof o !== 'object') {
+        this.name = o;
+      } else {
+        for (key in o) {
+          value = o[key];
+          if (key === 'label') {
+            this.name = value;
+          } else {
+            this[key] = value;
+          }
+        }
+      }
+      this.children = [];
+      return this.parent = null;
+    };
+
+    Node.prototype.initFromData = function(data) {
+      var addChildren, addNode,
+        _this = this;
+      addNode = function(node_data) {
+        _this.setData(node_data);
+        if (node_data.children) {
+          return addChildren(node_data.children);
+        }
+      };
+      addChildren = function(children_data) {
+        var child, node, _i, _len;
+        for (_i = 0, _len = children_data.length; _i < _len; _i++) {
+          child = children_data[_i];
+          node = new Node('');
+          node.initFromData(child);
+          _this.addChild(node);
+        }
+        return null;
+      };
+      addNode(data);
+      return null;
+    };
+
+    /*
+        Create tree from data.
+    
+        Structure of data is:
+        [
+            {
+                label: 'node1',
+                children: [
+                    { label: 'child1' },
+                    { label: 'child2' }
+                ]
+            },
+            {
+                label: 'node2'
+            }
+        ]
+    */
+
+
+    Node.prototype.loadFromData = function(data) {
+      var node, o, _i, _len;
+      this.children = [];
+      for (_i = 0, _len = data.length; _i < _len; _i++) {
+        o = data[_i];
+        node = new Node(o);
+        this.addChild(node);
+        if (typeof o === 'object' && o.children) {
+          node.loadFromData(o.children);
+        }
+      }
+      return null;
+    };
+
+    /*
+        Add child.
+    
+        tree.addChild(
+            new Node('child1')
+        );
+    */
+
+
+    Node.prototype.addChild = function(node) {
+      this.children.push(node);
+      return node._setParent(this);
+    };
+
+    /*
+        Add child at position. Index starts at 0.
+    
+        tree.addChildAtPosition(
+            new Node('abc'),
+            1
+        );
+    */
+
+
+    Node.prototype.addChildAtPosition = function(node, index) {
+      this.children.splice(index, 0, node);
+      return node._setParent(this);
+    };
+
+    Node.prototype._setParent = function(parent) {
+      this.parent = parent;
+      this.tree = parent.tree;
+      return this.tree.addNodeToIndex(this);
+    };
+
+    /*
+        Remove child.
+    
+        tree.removeChild(tree.children[0]);
+    */
+
+
+    Node.prototype.removeChild = function(node) {
+      this.children.splice(this.getChildIndex(node), 1);
+      return this.tree.removeNodeFromIndex(node);
+    };
+
+    /*
+        Get child index.
+    
+        var index = getChildIndex(node);
+    */
+
+
+    Node.prototype.getChildIndex = function(node) {
+      return $.inArray(node, this.children);
+    };
+
+    /*
+        Does the tree have children?
+    
+        if (tree.hasChildren()) {
+            //
+        }
+    */
+
+
+    Node.prototype.hasChildren = function() {
+      return this.children.length !== 0;
+    };
+
+    /*
+        Iterate over all the nodes in the tree.
+    
+        Calls callback with (node, level).
+    
+        The callback must return true to continue the iteration on current node.
+    
+        tree.iterate(
+            function(node, level) {
+               console.log(node.name);
+    
+               // stop iteration after level 2
+               return (level <= 2);
+            }
+        );
+    */
+
+
+    Node.prototype.iterate = function(callback) {
+      var _iterate,
+        _this = this;
+      _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;
+        }
+      };
+      _iterate(this, 0);
+      return null;
+    };
+
+    /*
+        Move node relative to another node.
+    
+        Argument position: Position.BEFORE, Position.AFTER or Position.Inside
+    
+        // move node1 after node2
+        tree.moveNode(node1, node2, Position.AFTER);
+    */
+
+
+    Node.prototype.moveNode = function(moved_node, target_node, position) {
+      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));
+      } else if (position === Position.INSIDE) {
+        return target_node.addChildAtPosition(moved_node, 0);
+      }
+    };
+
+    /*
+        Get the tree as data.
+    */
+
+
+    Node.prototype.getData = function() {
+      var getDataFromNodes,
+        _this = this;
+      getDataFromNodes = function(nodes) {
+        var data, k, node, tmp_node, v, _i, _len;
+        data = [];
+        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' && k !== 'tree') && Object.prototype.hasOwnProperty.call(node, k)) {
+              tmp_node[k] = v;
+            }
+          }
+          if (node.hasChildren()) {
+            tmp_node.children = getDataFromNodes(node.children);
+          }
+          data.push(tmp_node);
+        }
+        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;
+    };
+
+    return Node;
+
+  })();
+
+  Tree = (function(_super) {
+
+    __extends(Tree, _super);
+
+    function Tree(o) {
+      Tree.__super__.constructor.call(this, o, null, true);
+      this.id_mapping = {};
+      this.tree = this;
+    }
+
+    Tree.prototype.getNodeById = function(node_id) {
+      return this.id_mapping[node_id];
+    };
+
+    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;
+
+  JqTreeWidget = (function(_super) {
+
+    __extends(JqTreeWidget, _super);
+
+    function JqTreeWidget() {
+      return JqTreeWidget.__super__.constructor.apply(this, arguments);
+    }
+
+    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,
+      autoEscape: true,
+      dataUrl: null
+    };
+
+    JqTreeWidget.prototype.toggle = function(node) {
+      if (node.hasChildren()) {
+        new FolderElement(node, this.element).toggle();
+      }
+      return this._saveState();
+    };
+
+    JqTreeWidget.prototype.getTree = function() {
+      return this.tree;
+    };
+
+    JqTreeWidget.prototype.selectNode = function(node, must_open_parents) {
+      return this.select_node_handler.selectNode(node, must_open_parents);
+    };
+
+    JqTreeWidget.prototype.getSelectedNode = function() {
+      return this.selected_node || false;
+    };
+
+    JqTreeWidget.prototype.toJson = function() {
+      return toJson(this.tree.getData());
+    };
+
+    JqTreeWidget.prototype.loadData = function(data, parent_node) {
+      var child, subtree, _i, _len, _ref;
+      if (!parent_node) {
+        this._initTree(data);
+      } else {
+        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);
+        }
+        this._refreshElements(parent_node.parent);
+      }
+      if (this.is_dragging) {
+        return this.dnd_handler.refreshHitAreas();
+      }
+    };
+
+    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) {
+      if (node.hasChildren()) {
+        new FolderElement(node, this.element).open(null, skip_slide);
+        return this._saveState();
+      }
+    };
+
+    JqTreeWidget.prototype.closeNode = function(node, skip_slide) {
+      if (node.hasChildren()) {
+        new FolderElement(node, this.element).close(skip_slide);
+        return this._saveState();
+      }
+    };
+
+    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.hasChildren();
+      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._init = function() {
+      JqTreeWidget.__super__._init.call(this);
+      this.element = this.$el;
+      this._initData();
+      this.element.click($.proxy(this._click, this));
+      return this.element.bind('contextmenu', $.proxy(this._contextmenu, this));
+    };
+
+    JqTreeWidget.prototype._deinit = function() {
+      this.element.empty();
+      this.element.unbind();
+      this.tree = null;
+      return JqTreeWidget.__super__._deinit.call(this);
+    };
+
+    JqTreeWidget.prototype._initData = function() {
+      var data_url,
+        _this = this;
+      if (this.options.data) {
+        return this._initTree(this.options.data);
+      } else {
+        data_url = this.options.dataUrl || this.element.data('url');
+        if (data_url) {
+          return $.ajax({
+            url: data_url,
+            cache: false,
+            success: function(response) {
+              var data;
+              if ($.isArray(response) || typeof response === 'object') {
+                data = response;
+              } else {
+                data = $.parseJSON(response);
+              }
+              return _this._initTree(data);
+            }
+          });
+        }
+      }
+    };
+
+    JqTreeWidget.prototype._initTree = function(data) {
+      var event;
+      this.tree = new Tree();
+      this.tree.loadFromData(data);
+      this.selected_node = null;
+      this.save_state_handler = new SaveStateHandler(this);
+      this.select_node_handler = new SelectNodeHandler(this);
+      this.dnd_handler = new DragAndDropHandler(this);
+      this._openNodes();
+      this._refreshElements();
+      this.select_node_handler.selectCurrentNode();
+      event = $.Event('tree.init');
+      return this.element.trigger(event);
+    };
+
+    JqTreeWidget.prototype._openNodes = function() {
+      var max_level;
+      if (this.options.saveState) {
+        if (this.save_state_handler.restoreState()) {
+          return;
+        }
+      }
+      if (this.options.autoOpen === false) {
+        return;
+      } else if (this.options.autoOpen === true) {
+        max_level = -1;
+      } else {
+        max_level = parseInt(this.options.autoOpen);
+      }
+      return this.tree.iterate(function(node, level) {
+        node.is_open = true;
+        return level !== max_level;
+      });
+    };
+
+    JqTreeWidget.prototype._refreshElements = function(from_node) {
+      var $element, createFolderLi, createLi, createNodeLi, createUl, doCreateDomElements, escapeIfNecessary, is_root_node, node_element,
+        _this = this;
+      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 (is_root_node) {
+          class_string = ' class="tree"';
+        } else {
+          class_string = '';
+        }
+        return $("<ul" + class_string + "></ul>");
+      };
+      createLi = function(node) {
+        var $li;
+        if (node.hasChildren()) {
+          $li = createFolderLi(node);
+        } else {
+          $li = createNodeLi(node);
+        }
+        if (_this.options.onCreateLi) {
+          _this.options.onCreateLi(node, $li);
+        }
+        return $li;
+      };
+      createNodeLi = function(node) {
+        var escaped_name;
+        escaped_name = escapeIfNecessary(node.name);
+        return $("<li><div><span class=\"title\">" + escaped_name + "</span></div></li>");
+      };
+      createFolderLi = function(node) {
+        var button_class, escaped_name, folder_class, getButtonClass, getFolderClass;
+        getButtonClass = function() {
+          var classes;
+          classes = ['toggler'];
+          if (!node.is_open) {
+            classes.push('closed');
+          }
+          return classes.join(' ');
+        };
+        getFolderClass = function() {
+          var classes;
+          classes = ['folder'];
+          if (!node.is_open) {
+            classes.push('closed');
+          }
+          return classes.join(' ');
+        };
+        button_class = getButtonClass();
+        folder_class = getFolderClass();
+        escaped_name = escapeIfNecessary(node.name);
+        return $("<li class=\"" + folder_class + "\"><div><a class=\"" + button_class + "\">&raquo;</a><span class=\"title\">" + escaped_name + "</span></div></li>");
+      };
+      doCreateDomElements = function($element, children, is_root_node, is_open) {
+        var $li, $ul, child, _i, _len;
+        $ul = createUl(is_root_node);
+        $element.append($ul);
+        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()) {
+            doCreateDomElements($li, child.children, false, child.is_open);
+          }
+        }
+        return null;
+      };
+      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();
+        is_root_node = true;
+      }
+      return doCreateDomElements($element, from_node.children, is_root_node, is_root_node);
+    };
+
+    JqTreeWidget.prototype._click = function(e) {
+      var $target, event, node, node_element;
+      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();
+          this._saveState();
+          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);
+          }
+        }
+      }
+    };
+
+    JqTreeWidget.prototype._getNode = function($element) {
+      var $li;
+      $li = $element.closest('li');
+      if ($li.length === 0) {
+        return null;
+      } else {
+        return $li.data('node');
+      }
+    };
+
+    JqTreeWidget.prototype._getNodeElementForNode = function(node) {
+      if (node.hasChildren()) {
+        return new FolderElement(node, this.element);
+      } else {
+        return new NodeElement(node, this.element);
+      }
+    };
+
+    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, 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;
+        }
+      }
+    };
+
+    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 {
+        return false;
+      }
+    };
+
+    JqTreeWidget.prototype._mouseDrag = function(event) {
+      if (this.options.dragAndDrop) {
+        return this.dnd_handler.mouseDrag(event);
+      } else {
+        return false;
+      }
+    };
+
+    JqTreeWidget.prototype._mouseStop = function() {
+      if (this.options.dragAndDrop) {
+        return this.dnd_handler.mouseStop();
+      } else {
+        return false;
+      }
+    };
+
+    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="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();
+        }
+      }
+    }
+
+    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('inside');
+    };
+
+    return GhostDropHint;
+
+  })();
+
+  BorderDropHint = (function() {
+
+    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() {
+
+    function NodeElement(node, tree_element) {
+      this.init(node, tree_element);
+    }
+
+    NodeElement.prototype.init = function(node, tree_element) {
+      this.node = node;
+      this.tree_element = tree_element;
+      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);
+
+    function FolderElement() {
+      return FolderElement.__super__.constructor.apply(this, arguments);
+    }
+
+    FolderElement.prototype.toggle = function() {
+      if (this.node.is_open) {
+        return this.close();
+      } else {
+        return this.open();
+      }
+    };
+
+    FolderElement.prototype.open = function(on_finished, skip_slide) {
+      var doOpen,
+        _this = this;
+      if (!this.node.is_open) {
+        this.node.is_open = true;
+        this.getButton().removeClass('closed');
+        doOpen = function() {
+          var event;
+          _this.getLi().removeClass('closed');
+          if (on_finished) {
+            on_finished();
+          }
+          event = $.Event('tree.open');
+          event.node = _this.node;
+          return _this.tree_element.trigger(event);
+        };
+        if (skip_slide) {
+          return doOpen();
+        } else {
+          return this.getUl().slideDown('fast', doOpen);
+        }
+      }
+    };
+
+    FolderElement.prototype.close = function(skip_slide) {
+      var doClose,
+        _this = this;
+      if (this.node.is_open) {
+        this.node.is_open = false;
+        this.getButton().addClass('closed');
+        doClose = function() {
+          var event;
+          _this.getLi().addClass('closed');
+          event = $.Event('tree.close');
+          event.node = _this.node;
+          return _this.tree_element.trigger(event);
+        };
+        if (skip_slide) {
+          return doClose();
+        } else {
+          return this.getUl().slideUp('fast', doClose);
+        }
+      }
+    };
+
+    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() {
+
+    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;
+
+  })();
+
+  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;
+      if (this.tree_widget.options.onGetStateFromStorage) {
+        state = this.tree_widget.options.onGetStateFromStorage();
+      } else if (typeof localStorage !== "undefined" && localStorage !== null) {
+        state = localStorage.getItem(this.getCookieName());
+      } else if ($.cookie) {
+        state = $.cookie(this.getCookieName(), {
+          path: '/'
+        });
+      } else {
+        state = null;
+      }
+      if (!state) {
+        return false;
+      } else {
+        this.setState(state);
+        return true;
+      }
+    };
+
+    SaveStateHandler.prototype.getState = function() {
+      var open_nodes, selected_node,
+        _this = this;
+      open_nodes = [];
+      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.tree_widget.selected_node) {
+        selected_node = this.tree_widget.selected_node.id;
+      }
+      return toJson({
+        open_nodes: open_nodes,
+        selected_node: selected_node
+      });
+    };
+
+    SaveStateHandler.prototype.setState = function(state) {
+      var data, open_nodes, selected_node_id,
+        _this = this;
+      data = $.parseJSON(state);
+      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;
+        });
+      }
+    };
+
+    SaveStateHandler.prototype.getCookieName = function() {
+      if (typeof this.tree_widget.options.saveState === 'string') {
+        return this.tree_widget.options.saveState;
+      } else {
+        return 'tree';
+      }
+    };
+
+    return SaveStateHandler;
+
+  })();
+
+  SelectNodeHandler = (function() {
+
+    function SelectNodeHandler(tree_widget) {
+      this.tree_widget = tree_widget;
+    }
+
+    SelectNodeHandler.prototype.selectNode = function(node, must_open_parents) {
+      var parent;
+      if (this.tree_widget.options.selectable) {
+        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;
+          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();
+        }
+      }
+    };
+
+    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();
+        }
+      }
+    };
+
+    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;
+      $element = $(event.target);
+      if (this.tree_widget.options.onIsMoveHandle && !this.tree_widget.options.onIsMoveHandle($element)) {
+        return null;
+      }
+      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;
+    };
+
+    DragAndDropHandler.prototype.mouseStart = function(event) {
+      var offsetX, offsetY, _ref;
+      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('moving');
+      return true;
+    };
+
+    DragAndDropHandler.prototype.mouseDrag = function(event) {
+      var area, position_name;
+      this.drag_element.move(event.pageX, event.pageY);
+      area = this.findHoveredArea(event.pageX, event.pageY);
+      if (area && this.tree_widget.options.onCanMoveTo) {
+        position_name = Position.getName(area.position);
+        if (!this.tree_widget.options.onCanMoveTo(this.current_item.node, area.node, position_name)) {
+          area = null;
+        }
+      }
+      if (!area) {
+        this.removeDropHint();
+        this.removeHover();
+        this.stopOpenFolderTimer();
+      } else {
+        if (this.hovered_area !== area) {
+          this.hovered_area = area;
+          this.updateDropHint();
+        }
+      }
+      return true;
+    };
+
+    DragAndDropHandler.prototype.mouseStop = function() {
+      this.moveItem();
+      this.clear();
+      this.removeHover();
+      this.removeDropHint();
+      this.removeHitAreas();
+      this.current_item.$element.removeClass('moving');
+      this.is_dragging = false;
+      return false;
+    };
+
+    DragAndDropHandler.prototype.getOffsetFromEvent = function(event) {
+      var element_offset;
+      element_offset = $(event.target).offset();
+      return [event.pageX - element_offset.left, event.pageY - element_offset.top];
+    };
+
+    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) {
+        return $element.offset().top;
+      };
+      addPosition = function(node, position, top) {
+        positions.push({
+          top: top,
+          node: node,
+          position: position
+        });
+        return last_top = top;
+      };
+      groupPositions = function(handle_group) {
+        var group, position, previous_top, _i, _len;
+        previous_top = -1;
+        group = [];
+        for (_i = 0, _len = positions.length; _i < _len; _i++) {
+          position = positions[_i];
+          if (position.top !== previous_top) {
+            if (group.length) {
+              handle_group(group, previous_top, position.top);
+            }
+            previous_top = position.top;
+            group = [];
+          }
+          group.push(position);
+        }
+        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) {
+          addPosition(node, Position.NONE, top);
+        } else {
+          addPosition(node, Position.INSIDE, top);
+        }
+        if (next_node === _this.current_item.node || node === _this.current_item.node) {
+          return addPosition(node, Position.NONE, top);
+        } else {
+          return addPosition(node, Position.AFTER, top);
+        }
+      };
+      handleOpenFolder = function(node, $element) {
+        if (node === _this.current_item.node) {
+          return false;
+        }
+        if (node.children[0] !== _this.current_item.node) {
+          addPosition(node, Position.INSIDE, getTop($element));
+        }
+        return true;
+      };
+      handleAfterOpenFolder = function(node, next_node, $element) {
+        if (node === _this.current_item.node || next_node === _this.current_item.node) {
+          return addPosition(node, Position.NONE, last_top);
+        } else {
+          return addPosition(node, Position.AFTER, last_top);
+        }
+      };
+      handleClosedFolder = function(node, next_node, $element) {
+        var top;
+        top = getTop($element);
+        if (node === _this.current_item.node) {
+          return addPosition(node, Position.NONE, top);
+        } else {
+          addPosition(node, Position.INSIDE, top);
+          if (next_node !== _this.current_item.node) {
+            return addPosition(node, Position.AFTER, top);
+          }
+        }
+      };
+      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);
+      hit_areas = [];
+      groupPositions(function(positions_in_group, top, bottom) {
+        var area_height, area_top, position, _i, _len;
+        area_height = (bottom - top) / positions_in_group.length;
+        area_top = top;
+        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
+          });
+          area_top += area_height;
+        }
+        return null;
+      });
+      return this.hit_areas = hit_areas;
+    };
+
+    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;
+        must_iterate_inside = (node.is_open || !node.element) && node.hasChildren();
+        if (node.element) {
+          $element = $(node.element);
+          if (!$element.is(':visible')) {
+            return;
+          }
+          if (is_first_node) {
+            handle_first_node(node, $element);
+            is_first_node = false;
+          }
+          if (!node.hasChildren()) {
+            handle_node(node, next_node, $element);
+          } else if (node.is_open) {
+            if (!handle_open_folder(node, $element)) {
+              must_iterate_inside = false;
+            }
+          } else {
+            handle_closed_folder(node, next_node, $element);
+          }
+        }
+        if (must_iterate_inside) {
+          children_length = node.children.length;
+          _ref = node.children;
+          for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
+            child = _ref[i];
+            if (i === (children_length - 1)) {
+              iterate(node.children[i], null);
+            } else {
+              iterate(node.children[i], node.children[i + 1]);
+            }
+          }
+          if (node.is_open) {
+            return handle_after_open_folder(node, next_node, $element);
+          }
+        }
+      };
+      return iterate(this.tree_widget.tree);
+    };
+
+    DragAndDropHandler.prototype.findHoveredArea = function(x, y) {
+      var area, high, low, mid, tree_offset;
+      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) {
+        mid = (low + high) >> 1;
+        area = this.hit_areas[mid];
+        if (y < area.top) {
+          high = mid;
+        } else if (y > area.bottom) {
+          low = mid + 1;
+        } else {
+          return area;
+        }
+      }
+      return null;
+    };
+
+    DragAndDropHandler.prototype.updateDropHint = function() {
+      var node, node_element;
+      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);
+      }
+      this.removeDropHint();
+      node_element = this.tree_widget._getNodeElementForNode(this.hovered_area.node);
+      return this.previous_ghost = node_element.addDropHint(this.hovered_area.position);
+    };
+
+    DragAndDropHandler.prototype.startOpenFolderTimer = function(folder) {
+      var openFolder,
+        _this = this;
+      openFolder = function() {
+        return _this.tree_widget._getNodeElementForNode(folder).open(function() {
+          _this.refreshHitAreas();
+          return _this.updateDropHint();
+        });
+      };
+      return this.open_folder_timer = setTimeout(openFolder, 500);
+    };
+
+    DragAndDropHandler.prototype.stopOpenFolderTimer = function() {
+      if (this.open_folder_timer) {
+        clearTimeout(this.open_folder_timer);
+        return this.open_folder_timer = null;
+      }
+    };
+
+    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;
+        if (position === Position.INSIDE) {
+          this.hovered_area.node.is_open = true;
+        }
+        doMove = function() {
+          _this.tree_widget.tree.moveNode(moved_node, target_node, position);
+          _this.tree_widget.element.empty();
+          return _this.tree_widget._refreshElements();
+        };
+        event = $.Event('tree.move');
+        event.move_info = {
+          moved_node: moved_node,
+          target_node: target_node,
+          position: Position.getName(position),
+          previous_parent: previous_parent,
+          do_move: doMove
+        };
+        this.tree_widget.element.trigger(event);
+        if (!event.isDefaultPrevented()) {
+          return doMove();
+        }
+      }
+    };
+
+    return DragAndDropHandler;
+
+  })();
+
+  this.Tree.Node = Node;
+
+}).call(this);