/* * jsTree 0.9.9a * http://jstree.com/ * * Copyright (c) 2009 Ivan Bozhanov (vakata.com) * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * Date: 2009-10-06 * */ (function ($) { // jQuery plugin $.tree = { datastores: {}, plugins: {}, defaults: { data: { async: false, // Are async requests used to load open_branch contents type: "html", // One of included datastores opts: { method: "GET", url: false} // Options passed to datastore }, idprev:'jt_', selected: false, // FALSE or STRING or ARRAY opened: [], // ARRAY OF INITIALLY OPENED NODES languages: [], // ARRAY of string values (which will be used as CSS classes - so they must be valid) ui: { dots: true, // BOOL - dots or no dots animation: 0, // INT - duration of open/close animations in miliseconds scroll_spd: 4, theme_path: false, // Path to the theme CSS file - if set to false and theme_name is not false - will lookup jstree-path-here/themes/theme-name-here/style.css theme_name: "default", // if set to false no theme will be loaded selected_parent_close: "select_parent", // false, "deselect", "select_parent" selected_delete: "select_previous" // false, "select_previous" }, types: { "default": { clickable: true, // can be function renameable: true, // can be function deletable: true, // can be function creatable: true, // can be function draggable: true, // can be function max_children: -1, // -1 - not set, 0 - no children, 1 - one child, etc // can be function max_depth: -1, // -1 - not set, 0 - no children, 1 - one level of children, etc // can be function valid_children: "all", // all, none, array of values // can be function icon: { image: false, position: false } } }, rules: { multiple: false, // FALSE | CTRL | ON - multiple selection off/ with or without holding Ctrl multitree: "none", // all, none, array of tree IDs to accept from type_attr: "rel", // STRING attribute name (where is the type stored as string) createat: "bottom", // STRING (top or bottom) new nodes get inserted at top or bottom drag_copy: "ctrl", // FALSE | CTRL | ON - drag to copy off/ with or without holding Ctrl drag_button: "left", // left, right or both use_max_children: true, use_max_depth: true, max_children: -1, max_depth: -1, valid_children: "all" }, lang: { new_node: "New folder", loading: "Loading ..." }, callback: { beforechange: function (NODE, TREE_OBJ) { return true }, beforeopen: function (NODE, TREE_OBJ) { return true }, beforeclose: function (NODE, TREE_OBJ) { return true }, beforemove: function (NODE, REF_NODE, TYPE, TREE_OBJ) { return true }, beforecreate: function (NODE, REF_NODE, TYPE, TREE_OBJ) { return true }, beforerename: function (NODE, LANG, TREE_OBJ) { return true }, beforedelete: function (NODE, TREE_OBJ) { return true }, beforedata: function (NODE, TREE_OBJ) { return { id: $(NODE).attr("id") || 0} }, // PARAMETERS PASSED TO SERVER ondata: function (DATA, TREE_OBJ) { return DATA; }, // modify data before parsing it onparse: function (STR, TREE_OBJ) { return STR; }, // modify string before visualizing it onhover: function (NODE, TREE_OBJ) { }, // node hovered onselect: function (NODE, TREE_OBJ) { }, // node selected ondeselect: function (NODE, TREE_OBJ) { }, // node deselected onchange: function (NODE, TREE_OBJ) { }, // focus changed onrename: function (NODE, TREE_OBJ, RB) { }, // node renamed onmove: function (NODE, REF_NODE, TYPE, TREE_OBJ, RB) { }, // move completed oncopy: function (NODE, REF_NODE, TYPE, TREE_OBJ, RB) { }, // copy completed oncreate: function (NODE, REF_NODE, TYPE, TREE_OBJ, RB) { }, // node created ondelete: function (NODE, TREE_OBJ, RB) { }, // node deleted onopen: function (NODE, TREE_OBJ) { }, // node opened onopen_all: function (TREE_OBJ) { }, // all nodes opened onclose_all: function (TREE_OBJ) { }, // all nodes closed onclose: function (NODE, TREE_OBJ) { }, // node closed error: function (TEXT, TREE_OBJ) { }, // error occured ondblclk: function (NODE, TREE_OBJ) { TREE_OBJ.toggle_branch.call(TREE_OBJ, NODE); TREE_OBJ.select_branch.call(TREE_OBJ, NODE); }, onrgtclk: function (NODE, TREE_OBJ, EV) { }, // right click - to prevent use: EV.preventDefault(); EV.stopPropagation(); return false onload: function (TREE_OBJ) { }, oninit: function (TREE_OBJ) { }, onfocus: function (TREE_OBJ) { }, ondestroy: function (TREE_OBJ) { }, onsearch: function (NODES, TREE_OBJ) { NODES.addClass("search"); }, ondrop: function (NODE, REF_NODE, TYPE, TREE_OBJ) { }, check: function (RULE, NODE, VALUE, TREE_OBJ) { return VALUE; }, check_move: function (NODE, REF_NODE, TYPE, TREE_OBJ) { return true; } }, plugins: {} }, create: function () { return new tree_component(); }, focused: function () { return tree_component.inst[tree_component.focused]; }, reference: function (obj) { var o = $(obj); if (!o.size()) { obj = obj.replace("#", ""); o = $("#" + obj); } if (!o.size()) return null; o = (o.is(".tree")) ? o.attr("id") : o.parents(".tree:eq(0)").attr("id"); return tree_component.inst[o] || null; }, rollback: function (data) { for (var i in data) { if (!data.hasOwnProperty(i)) continue; var tmp = tree_component.inst[i]; var lock = !tmp.locked; // if not locked - lock the tree if (lock) tmp.lock(true); // Cancel ongoing rename tmp.inp = false; tmp.container.html(data[i].html).find(".dragged").removeClass("dragged").end().find(".hover").removeClass("hover"); if (data[i].selected) { tmp.selected = $("#" + data[i].selected); tmp.selected_arr = []; tmp.container .find("a.clicked").each(function () { tmp.selected_arr.push(tmp.get_node(this)); }); } // if this function set the lock - unlock if (lock) tmp.lock(false); delete lock; delete tmp; } }, drop_mode: function (opts) { opts = $.extend(opts, { show: false, type: "default", str: "Foreign node" }); tree_component.drag_drop.foreign = true; tree_component.drag_drop.isdown = true; tree_component.drag_drop.moving = true; tree_component.drag_drop.appended = false; tree_component.drag_drop.f_type = opts.type; tree_component.drag_drop.f_data = opts; if (!opts.show) { tree_component.drag_drop.drag_help = false; tree_component.drag_drop.drag_node = false; } else { tree_component.drag_drop.drag_help = $("
"); tree_component.drag_drop.drag_node = tree_component.drag_drop.drag_help.find("li:eq(0)"); } if ($.tree.drag_start !== false) $.tree.drag_start.call(null, false); }, drag_start: false, drag: false, drag_end: false }; $.fn.tree = function (opts) { return this.each(function () { var conf = $.extend({}, opts); if (tree_component.inst && tree_component.inst[$(this).attr('id')]) tree_component.inst[$(this).attr('id')].destroy(); if (conf !== false) new tree_component().init(this, conf); }); }; // core function tree_component() { return { cntr: ++tree_component.cntr, settings: $.extend({}, $.tree.defaults), init: function (elem, conf) { var _this = this; this.container = $(elem); if (this.container.size == 0) return false; tree_component.inst[this.cntr] = this; if (!this.container.attr("id")) this.container.attr("id", "jstree_" + this.cntr); tree_component.inst[this.container.attr("id")] = tree_component.inst[this.cntr]; tree_component.focused = this.cntr; this.settings = $.extend(true, {}, this.settings, conf); // DEAL WITH LANGUAGE VERSIONS if (this.settings.languages && this.settings.languages.length) { this.current_lang = this.settings.languages[0]; var st = false; var id = "#" + this.container.attr("id"); for (var ln = 0; ln < this.settings.languages.length; ln++) { st = tree_component.add_css(id + " ." + this.settings.languages[ln]); if (st !== false) st.style.display = (this.settings.languages[ln] == this.current_lang) ? "" : "none"; } } else this.current_lang = false; // THEMES this.container.addClass("tree"); if (this.settings.ui.theme_name !== false) { if (this.settings.ui.theme_path === false) { $("script").each(function () { if (this.src.toString().match(/jquery\.tree.*?js$/)) { _this.settings.ui.theme_path = this.src.toString().replace(/jquery\.tree.*?js$/, "") + "themes/" + _this.settings.ui.theme_name + "/style.css"; return false; } }); } if (this.settings.ui.theme_path != "" && $.inArray(this.settings.ui.theme_path, tree_component.themes) == -1) { tree_component.add_sheet({ url: this.settings.ui.theme_path }); tree_component.themes.push(this.settings.ui.theme_path); } this.container.addClass("tree-" + this.settings.ui.theme_name); } // TYPE ICONS var type_icons = ""; for (var t in this.settings.types) { if (!this.settings.types.hasOwnProperty(t)) continue; if (!this.settings.types[t].icon) continue; if (this.settings.types[t].icon.image || this.settings.types[t].icon.position) { if (t == "default") type_icons += "#" + this.container.attr("id") + " li > a ins { "; else type_icons += "#" + this.container.attr("id") + " li[rel=" + t + "] > a ins { "; if (this.settings.types[t].icon.image) type_icons += " background-image:url(" + this.settings.types[t].icon.image + "); "; if (this.settings.types[t].icon.position) type_icons += " background-position:" + this.settings.types[t].icon.position + "; "; type_icons += "} "; } } if (type_icons != "") tree_component.add_sheet({ str: type_icons }); if (this.settings.rules.multiple) this.selected_arr = []; this.offset = false; this.hovered = false; this.locked = false; if (tree_component.drag_drop.marker === false) tree_component.drag_drop.marker = $("
").attr({ id: "jstree-marker" }).hide().appendTo("body"); this.callback("oninit", [this]); this.refresh(); this.attach_events(); this.focus(); }, refresh: function (obj) { if (this.locked) return this.error("LOCKED"); var _this = this; if (obj && !this.settings.data.async) obj = false; this.is_partial_refresh = obj ? true : false; // SAVE OPENED this.opened = Array(); if (this.settings.opened != false) { $.each(this.settings.opened, function (i, item) { if (this.replace(/^#/, "").length > 0) { _this.opened.push("#" + this.replace(/^#/, "")); } }); this.settings.opened = false; } else { this.container.find("li.open").each(function (i) { if (this.id) { _this.opened.push("#" + this.id); } }); } // SAVE SELECTED if (this.selected) { this.settings.selected = Array(); if (obj) { $(obj).find("li:has(a.clicked)").each(function () { if (this.id) _this.settings.selected.push("#" + this.id); }); } else { if (this.selected_arr) { $.each(this.selected_arr, function () { if (this.attr("id")) _this.settings.selected.push("#" + this.attr("id")); }); } else { if (this.selected.attr("id")) this.settings.selected.push("#" + this.selected.attr("id")); } } } else if (this.settings.selected !== false) { var tmp = Array(); if ((typeof this.settings.selected).toLowerCase() == "object") { $.each(this.settings.selected, function () { if (this.replace(/^#/, "").length > 0) tmp.push("#" + this.replace(/^#/, "")); }); } else { if (this.settings.selected.replace(/^#/, "").length > 0) tmp.push("#" + this.settings.selected.replace(/^#/, "")); } this.settings.selected = tmp; } if (obj && this.settings.data.async) { this.opened = Array(); obj = this.get_node(obj); obj.find("li.open").each(function (i) { _this.opened.push("#" + this.id); }); if (obj.hasClass("open")) obj.removeClass("open").addClass("closed"); if (obj.hasClass("leaf")) obj.removeClass("leaf"); obj.children("ul:eq(0)").html(""); return this.open_branch(obj, true, function () { _this.reselect.apply(_this); }); } var _this = this; var _datastore = new $.tree.datastores[this.settings.data.type](); if (this.container.children("ul").size() == 0) { this.container.html(""); } _datastore.load(this.callback("beforedata", [false, this]), this, this.settings.data.opts, function (data) { data = _this.callback("ondata", [data, _this]); _datastore.parse(data, _this, _this.settings.data.opts, function (str) { str = _this.callback("onparse", [str, _this]); _this.container.empty().append($("