Mercurial > hg > orthanc
diff OrthancServer/OrthancExplorer/libs/tree.jquery.js @ 4044:d25f4c0fa160 framework
splitting code into OrthancFramework and OrthancServer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 10 Jun 2020 20:30:34 +0200 |
parents | OrthancExplorer/libs/tree.jquery.js@4bc019d2f969 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/OrthancExplorer/libs/tree.jquery.js Wed Jun 10 20:30:34 2020 +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, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/'); + }; + + 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 + "\">»</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);