Subject: [Pkg-cacti-maint] Bug#679980: Discuss possible ways of fixing license issue in cacti, RC bug 679980

From: Paul Gevers <[email-masked]>
Date: Sun, 25 Nov 2012 13:53:15 +0100

Hi release team,

Cacti has a nearly 5 months old standing RC bug [1] filed against it
about files with a non-DFSG license (distribution is possible, but
others can not use the copy for other purposes, they need to get their
own free copy). I was hoping that cacti upstream would create the code
needed to provide the functionality [2] that would be removed by
removing the files in question. I have now given up on that happening
soon, so I have created a patch [3] to do that. Before implementing this
in the Debian cacti package, I request your opinion on what is
acceptable for wheezy.

I see several options:

1) Ignore this bug for wheezy as these files are shipped already for so
long and distribution is still allowed (I would prefer we don't choose
this option).

2) Remove the problematic files from source, leaving the cacti package
slightly crippled. The functionality in question is not needed for cacti
to work, but if you monitor lots of systems with cacti, your ability to
locate the proper graphs easily is decreased. (I would rather prefer 1)).

3) Remove the problematic files from source, and apply the patch I
attached to bug 679980 [3], but DON'T add the needed jstree code to the
package. As my patch, in contrast to the current tree, generates a
visible (but non-collapsing) HTML tree, this option is already better
than 1). However, the tree would be enormous for large sites, still
making it hardly useful for them. This option will be better than 2),
even more so for small sites.

4) Same as 3) but also embed jstree in the package [4]. As the jquery
and jquery-cookies dependency can be satisfied by packages already in
Debian, only jstree is needed to be in cacti. It should be clear that I
prefer this solution (that is why I did the work) but I can imagine that
the release team finds it too intrusive in this stage of the release cycle.

So my request is that you state how you want this bug resolved for
wheezy. If needed, I can prepare the preferred option in experimental
first, so you can postpone the final decision. But the main change will
be the patch [3] and the inclusion of jstee [5] and it's css and
pictures [6].

With kind regards,
Paul

By the way, I would still like to include the changes in the unblock bug
683684, as I already see questions popping up on the upstream forum
(mostly Ubuntu users of current version 0.8.8.a-3).

[1] http://bugs.debian.org/679980
[2] The functionality being that you have a tree on every page with
graphs which you can expand or collapse to navigate through all possible
(groups of) graphs.
[3]
http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=27;filename=replace_treeview_by_jquery.jstree.patch;att=1;bug=679980
[4] I have already filed a wish-list bug against jsquery-goodies to
create a package for jstree: http://bugs.debian.org/694313
[5]
http://svn.cacti.net/viewvc/cacti/branches/0.8.9/include/js/jquery/jquery.jstree.js?revision=7218&content-type=text%2Fplain
[6]
http://svn.cacti.net/viewvc/cacti/branches/main/include/js/jquery/themes/default/
[7] http://bugs.debian.org/683684

---

From: Paul Gevers <[email-masked]>
Date: Wed, 12 Dec 2012 22:02:53 +0100

On 10-12-12 10:02, Niels Thykier wrote:
> How difficult would it be to add some "simple collapsing" code for
> Wheezy?

Maybe not so difficult for people with experience doing those kind of
things, but this actually was my first time ever doing javascript, so I
am much more comfortable doing it with such a "library".

> The problem I have with 2) and 3) is that it is a regression
> for people using cacti already.

Agreed.

> I'd recommend uploading 4) to experimental, compile a debdiff and send
> it our way.  We may have to back down 3) or 1) once we see the debdiff, but

I have just uploaded cacti version 0.8.8a+dfsg-1 to experimental. Please
find the debdiffs against the dsc and deb files attached.

>>> (mostly Ubuntu users of current version 0.8.8.a-3).

I have included the (nearly only documentation) changes to that bug in
this debdiff. If you don't accept these, please let me know and I will
remove those changes again.

Paul
diff -Nru cacti-0.8.8a/debian/cacti.install cacti-0.8.8a+dfsg/debian/cacti.install
--- cacti-0.8.8a/debian/cacti.install	2012-04-30 20:18:03.000000000 +0200
+++ cacti-0.8.8a+dfsg/debian/cacti.install	2012-12-10 21:02:55.000000000 +0100
@@ -4,5 +4,7 @@
 include   usr/share/cacti/site
 install   usr/share/cacti/site
 lib       usr/share/cacti/site
+plugins   usr/share/cacti/site
 resource  usr/share/cacti
 scripts   usr/share/cacti/site
+debian/js usr/share/cacti/site/include
diff -Nru cacti-0.8.8a/debian/cacti.links cacti-0.8.8a+dfsg/debian/cacti.links
--- cacti-0.8.8a/debian/cacti.links	2012-05-04 07:55:53.000000000 +0200
+++ cacti-0.8.8a+dfsg/debian/cacti.links	2012-09-15 07:35:11.000000000 +0200
@@ -1,5 +1,5 @@
-/usr/local/share/cacti/plugins	/usr/share/cacti/site/plugins
 /usr/share/cacti/resource	/usr/share/cacti/site/resource
+/usr/share/doc/cacti/README.Plugins /usr/share/cacti/site/plugins/README.Plugins
 /usr/share/doc/cacti/html	/usr/share/cacti/site/docs/html
 /usr/share/dbconfig-common/data/cacti/install/mysql /usr/share/doc/cacti/cacti.sql
 /etc/cacti/debian.php		/usr/share/cacti/site/include/config.php
diff -Nru cacti-0.8.8a/debian/changelog cacti-0.8.8a+dfsg/debian/changelog
--- cacti-0.8.8a/debian/changelog	2012-06-08 19:30:01.000000000 +0200
+++ cacti-0.8.8a+dfsg/debian/changelog	2012-12-11 20:36:43.000000000 +0100
@@ -1,3 +1,23 @@
+cacti (0.8.8a+dfsg-1) experimental; urgency=low
+
+  * Removed non-dfsg-free treeview code from the upstream source (Closes:
+    #679980)
+  * Add jquery.jstree.js and four jstree theme files to the package to replace
+    the treeview functionality
+  * Update d/copyright to reflect above changes
+  * Add patches to use the jstree code
+    - replace_treeview_by_jquery.jstree.patch
+    - use_jquery_for_debian.patch
+  * Add libjs-jquery and libjs-jquery-cookie to recommends as they are needed by
+    jstree.
+  * Remove the logic to install plugins in /usr/local/share/cacti/plugins as the
+    implementation of chdir in php resolves symlinks (Closes: #681558).
+    - Update README.Debian and add NEWS.Debian and README.Plugins
+    - Update d/cacti.links and d/cacti.install
+  * Update my e-mail address to [email-masked]
+
+ -- Paul Gevers <[email-masked]>  Mon, 10 Dec 2012 22:48:48 +0100
+
 cacti (0.8.8a-3) unstable; urgency=low
 
   * Update postrm with new debconf answers (Closes: #673764)
diff -Nru cacti-0.8.8a/debian/control cacti-0.8.8a+dfsg/debian/control
--- cacti-0.8.8a/debian/control	2012-05-20 20:20:58.000000000 +0200
+++ cacti-0.8.8a+dfsg/debian/control	2012-12-10 21:49:51.000000000 +0100
@@ -4,7 +4,7 @@
 Maintainer: Cacti Maintainer <[email-masked]>
 Uploaders: Sean Finney <[email-masked]>,
            Mahyuddin Susanto <[email-masked]>,
-           Paul Gevers <[email-masked]>
+           Paul Gevers <[email-masked]>
 DM-Upload-Allowed: yes
 Build-Depends: debhelper (>= 7.0.50~),
                po-debconf
@@ -30,6 +30,8 @@
 Recommends: apache2 | lighttpd | nginx | httpd,
             inetutils-ping | iputils-ping,
             logrotate,
+            libjs-query,
+            libjs-query-cookie,
             mysql-server
 Suggests: php5-ldap,
 	  moreutils,
diff -Nru cacti-0.8.8a/debian/copyright cacti-0.8.8a+dfsg/debian/copyright
--- cacti-0.8.8a/debian/copyright	2012-05-17 12:19:24.000000000 +0200
+++ cacti-0.8.8a+dfsg/debian/copyright	2012-12-11 20:22:23.000000000 +0100
@@ -2,6 +2,8 @@
 Upstream-Name: cacti
 Upstream-Contact: Ian Berry <[email-masked]>
 Source: http://www.cacti.net/
+Comment: the files in include/treeview are removed from the upstream sourse as
+ its license is not considered Debian free (see bts: #679980).
 
 Files: *
 Copyright: 2004-2007, The Cacti Group
@@ -49,179 +51,6 @@
  On Debian GNU/Linux systems, the complete text of the GNU Lesser General
  Public License version 2 can be found in `/usr/share/common-licenses/LGPL-2'.
 
-Files: include/treeview/*
-Copyright: 2006, Conor O'Mahony <[email-masked]>
-Comment: Action started to figure out compatibility
- http://lists.debian.org/debian-legal/2012/05/msg00019.html
- http://bugs.cacti.net/view.php?id=2228
-License: Custom
- TreeView License: Distributor's License
- .
- This License For Customer Use of GubuSoft TreeView Software ("LICENSE")
- is the agreement which governs use of the TreeView software by GubuSoft
- (“GUBUSOFT”) downloadable herefrom, including computer software and
- associated documentation ("SOFTWARE"). By downloading, installing,
- copying, or otherwise using the SOFTWARE, you agree to be bound by the
- terms of this LICENSE. If you do not agree to the terms of this LICENSE,
- do not use the SOFTWARE.
- .
- GUBUSOFT grants Customer a royalty-free, perpetual license to use
- SOFTWARE with unlimited server CPUs and internet domains. An unlimited
- number of end users may access and use the SOFTWARE. Customer may
- redistribute SOFTWARE subject to limitations. GUBUSOFT grants Customer
- rights to modify the source code, for use within their application.
- .
- 1. DEFINITIONS
- .
- 1.1 Customer. Customer means the entity or individual that downloads the
- SOFTWARE.
- .
- 2. GRANT OF LICENSE
- .
- 2.1 GUBUSOFT hereby grants Customer the following non-exclusive,
- non-transferable right to use the SOFTWARE.
- .
- 2.1.3 LIMITATIONS
- .
- Customer may not rent, lease, or transfer the rights to the SOFTWARE to
- someone else.
- .
- Customer may redistribute and use SOFTWARE in source code form provided
- (a) Customer Applications of SOFTWARE add primary and substantial
- functionality, and are not merely a set or subset of any of the
- functionality of the SOFTWARE, or a set or subset of any of the code or
- other files of the SOFTWARE; (b) the source code retains all source code
- comments, including all copyright notices, without modification; (c)
- Customer includes a valid copyright notice on their Application; and (d)
- Customer agrees to indemnify, hold harmless, and defend GubuSoft from
- and against any claims or lawsuits, including attorneys' fees, that
- arise or result from the use or distribution of Customer's Application.
- .
- Customer may redistribute and use SOFTWARE in binary form provided (a)
- Customer Applications of SOFTWARE add primary and substantial
- functionality, and are not merely a set or subset of any of the
- functionality of the SOFTWARE, or a set or subset of any of the code or
- other files of the SOFTWARE; (b) Customer agrees to indemnify, hold
- harmless, and defend GubuSoft from and against any claims or lawsuits,
- including attorneys' fees, that arise or result from the use or
- distribution of Customer's Application; and (c) the following notices
- are included in the documentation and/or other materials provided with
- the Customer's Application:
- .
-     Copyright (C) 2006 Conor O'Mahony ([email-masked])
- .
-     All rights reserved.
- .
-     This application includes the TreeView script.
- .
-     You are not authorized to download and/or use the TreeView source
- code from this application for your own purposes. For your own FREE copy
- of the TreeView script, please visit the http://www.treeview.net Web site.
- .
-     THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
- WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- .
- If Customer is using the free version of SOFTWARE, Customer must ensure
- that the "JavaScript Tree Menu" link at the top of the TreeView is
- visible and readable in their Web page or application.
- .
- Customer may not harm the GUBUSOFT intellectual property rights using
- any media or via any electronic or other method now known or later
- discovered.
- .
- Customer may not use the GubuSoft name, the name of the TreeView author,
- or the names of any source code contributors to endorse or promote
- products derived from this SOFTWARE without specific prior written
- permission.
- .
- Customer may not utilize the SOFTWARE in a manner which is disparaging
- to GUBUSOFT.
- .
- 3. TERMINATION
- .
- This LICENSE will automatically terminate if Customer fails to comply
- with any of the terms and conditions hereof. In such event, Customer
- must destroy all copies of the SOFTWARE and all of its component parts.
- .
- Defensive Suspension. If Customer commences or participates in any legal
- proceeding against GUBUSOFT, then GUBUSOFT may, in its sole discretion,
- suspend or terminate all license grants and any other rights provided
- under this LICENSE during the pendency of such legal proceedings.
- .
- 4. COPYRIGHT
- .
- All title and copyrights in and to the SOFTWARE (including but not
- limited to all images, photographs, animations, video, audio, music,
- text, and other information incorporated into the SOFTWARE), the
- accompanying printed materials, and any copies of the SOFTWARE, are
- owned by GUBUSOFT. The SOFTWARE is protected by copyright laws and
- international treaty provisions. Accordingly, Customer is required to
- treat the SOFTWARE like any other copyrighted material, except as
- otherwise allowed pursuant to this LICENSE and that it may make one copy
- of the SOFTWARE solely for backup or archive purposes.
- .
- 5. APPLICABLE LAW
- .
- This LICENSE shall be deemed to have been made in, and shall be
- construed pursuant to, the laws of the State of California. The United
- Nations Convention on Contracts for the International Sale of Goods is
- specifically disclaimed.
- .
- 6. DISCLAIMER OF WARRANTIES AND LIMITATION ON LIABILITY
- .
- 6.1 No Warranties. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
- THE SOFTWARE IS PROVIDED "AS IS" AND GUBUSOFT AND ITS SUPPLIERS DISCLAIM
- ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED
- TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE.
- .
- 6.2 No Liability for Consequential Damages. TO THE MAXIMUM EXTENT
- PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL GUBUSOFT BE LIABLE FOR
- ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER
- (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
- BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER
- PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THE
- SOFTWARE, EVEN IF GUBUSOFT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- DAMAGES.
- .
- 7. MISCELLANEOUS
- .
- If any provision of this LICENSE is inconsistent with, or cannot be
- fully enforced under, the law, such provision will be construed as
- limited to the extent necessary to be consistent with and fully
- enforceable under the law. This LICENSE is the final, complete and
- exclusive agreement between the parties relating to the subject matter
- hereof, and supersedes all prior or contemporaneous understandings and
- agreements relating to such subject matter, whether oral or written.
- This LICENSE may only be modified in writing signed by an authorized
- officer of GUBUSOFT.
- .
- 8. ASSIGNMENT
- .
- GUBUSOFT may assign or otherwise transfer any of its rights or
- obligations under this LICENSE agreement.
-
-Files: include/treeview/ua.js
-Copyright: 2001, Netscape Corporation
-License: MPL-1.1 or GPL-2+ or LGPL-2.1+
- Licensed under Version: MPL 1.1/GPL 2.0/LGPL 2.1
- Full Terms at http://bclary.com/lib/js/license/mpl-tri-license.txt
- .
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
- .
- The Original Code is Netscape code.
- .
- The Initial Developer of the Original Code is
- Netscape Corporation.
- Portions created by the Initial Developer are Copyright (C) 2001
- the Initial Developer. All Rights Reserved.
- .
- Contributor(s): Bob Clary <[email-masked]>
-
 Files: include/zoom.js
 Copyright: 2004, Eric Steffen
 License: GPL-2+
@@ -234,6 +63,38 @@
            2012, Paul Gevers <[email-masked]>
 License: GPL-2+
 
+Files: debian/js/*
+Copyright: 2010-2011, Ivan Bozhanov <vakata.com>
+Comment: http://www.jstree.com/
+License: GPL-2 or expat
+ Licensed same as jquery - under the terms of either the MIT License or the GPL
+ Version 2 License
+ http://www.opensource.org/licenses/mit-license.php
+ http://www.gnu.org/licenses/gpl.html
+ .
+ On Debian GNU/Linux systems, the complete text of the GNU General
+ Public License Version 2 can be found in
+ `/usr/share/common-licenses/GPL-2'.
+
+License: expat
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+ .
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
 License: GPL-2+
  This package is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
diff -Nru cacti-0.8.8a/debian/dirs cacti-0.8.8a+dfsg/debian/dirs
--- cacti-0.8.8a/debian/dirs	2012-05-06 15:20:06.000000000 +0200
+++ cacti-0.8.8a+dfsg/debian/dirs	2012-09-15 07:35:11.000000000 +0200
@@ -1,7 +1,6 @@
 etc/cacti
 var/log/cacti
 var/lib/cacti/rra
-usr/local/share/cacti/plugins
 usr/local/share/cacti/resource/script_queries
 usr/local/share/cacti/resource/script_server
 usr/local/share/cacti/resource/snmp_queries
diff -Nru cacti-0.8.8a/debian/docs cacti-0.8.8a+dfsg/debian/docs
--- cacti-0.8.8a/debian/docs	2012-05-04 07:45:44.000000000 +0200
+++ cacti-0.8.8a+dfsg/debian/docs	2012-09-15 07:35:11.000000000 +0200
@@ -5,3 +5,4 @@
 debian/cacti.apache.conf
 debian/cacti.lighttpd.conf
 debian/debian.php.dist
+debian/README.Plugins
diff -Nru cacti-0.8.8a/debian/js/jquery/jquery.jstree.js cacti-0.8.8a+dfsg/debian/js/jquery/jquery.jstree.js
--- cacti-0.8.8a/debian/js/jquery/jquery.jstree.js	1970-01-01 01:00:00.000000000 +0100
+++ cacti-0.8.8a+dfsg/debian/js/jquery/jquery.jstree.js	2012-11-25 12:29:50.000000000 +0100
@@ -0,0 +1,4551 @@
+/*
+ * jsTree 1.0-rc3
+ * http://jstree.com/
+ *
+ * Copyright (c) 2010 Ivan Bozhanov (vakata.com)
+ *
+ * Licensed same as jquery - under the terms of either the MIT License or the GPL Version 2 License
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * $Date: 2011-02-09 01:17:14 +0200 (ср, 09 февр 2011) $
+ * $Revision: 236 $
+ */
+
+/*jslint browser: true, onevar: true, undef: true, bitwise: true, strict: true */
+/*global window : false, clearInterval: false, clearTimeout: false, document: false, setInterval: false, setTimeout: false, jQuery: false, navigator: false, XSLTProcessor: false, DOMParser: false, XMLSerializer: false*/
+
+"use strict";
+
+// top wrapper to prevent multiple inclusion (is this OK?)
+(function () { if(jQuery && jQuery.jstree) { return; }
+	var is_ie6 = false, is_ie7 = false, is_ff2 = false;
+
+/* 
+ * jsTree core
+ */
+(function ($) {
+	// Common functions not related to jsTree 
+	// decided to move them to a `vakata` "namespace"
+	$.vakata = {};
+	// CSS related functions
+	$.vakata.css = {
+		get_css : function(rule_name, delete_flag, sheet) {
+			rule_name = rule_name.toLowerCase();
+			var css_rules = sheet.cssRules || sheet.rules,
+				j = 0;
+			do {
+				if(css_rules.length && j > css_rules.length + 5) { return false; }
+				if(css_rules[j].selectorText && css_rules[j].selectorText.toLowerCase() == rule_name) {
+					if(delete_flag === true) {
+						if(sheet.removeRule) { sheet.removeRule(j); }
+						if(sheet.deleteRule) { sheet.deleteRule(j); }
+						return true;
+					}
+					else { return css_rules[j]; }
+				}
+			}
+			while (css_rules[++j]);
+			return false;
+		},
+		add_css : function(rule_name, sheet) {
+			if($.jstree.css.get_css(rule_name, false, sheet)) { return false; }
+			if(sheet.insertRule) { sheet.insertRule(rule_name + ' { }', 0); } else { sheet.addRule(rule_name, null, 0); }
+			return $.vakata.css.get_css(rule_name);
+		},
+		remove_css : function(rule_name, sheet) { 
+			return $.vakata.css.get_css(rule_name, true, sheet); 
+		},
+		add_sheet : function(opts) {
+			var tmp = false, is_new = true;
+			if(opts.str) {
+				if(opts.title) { tmp = $("style[id='" + opts.title + "-stylesheet']")[0]; }
+				if(tmp) { is_new = false; }
+				else {
+					tmp = document.createElement("style");
+					tmp.setAttribute('type',"text/css");
+					if(opts.title) { tmp.setAttribute("id", opts.title + "-stylesheet"); }
+				}
+				if(tmp.styleSheet) {
+					if(is_new) { 
+						document.getElementsByTagName("head")[0].appendChild(tmp); 
+						tmp.styleSheet.cssText = opts.str; 
+					}
+					else {
+						tmp.styleSheet.cssText = tmp.styleSheet.cssText + " " + opts.str; 
+					}
+				}
+				else {
+					tmp.appendChild(document.createTextNode(opts.str));
+					document.getElementsByTagName("head")[0].appendChild(tmp);
+				}
+				return tmp.sheet || tmp.styleSheet;
+			}
+			if(opts.url) {
+				if(document.createStyleSheet) {
+					try { tmp = document.createStyleSheet(opts.url); } catch (e) { }
+				}
+				else {
+					tmp			= document.createElement('link');
+					tmp.rel		= 'stylesheet';
+					tmp.type	= 'text/css';
+					tmp.media	= "all";
+					tmp.href	= opts.url;
+					document.getElementsByTagName("head")[0].appendChild(tmp);
+					return tmp.styleSheet;
+				}
+			}
+		}
+	};
+
+	// private variables 
+	var instances = [],			// instance array (used by $.jstree.reference/create/focused)
+		focused_instance = -1,	// the index in the instance array of the currently focused instance
+		plugins = {},			// list of included plugins
+		prepared_move = {};		// for the move_node function
+
+	// jQuery plugin wrapper (thanks to jquery UI widget function)
+	$.fn.jstree = function (settings) {
+		var isMethodCall = (typeof settings == 'string'), // is this a method call like $().jstree("open_node")
+			args = Array.prototype.slice.call(arguments, 1), 
+			returnValue = this;
+
+		// if a method call execute the method on all selected instances
+		if(isMethodCall) {
+			if(settings.substring(0, 1) == '_') { return returnValue; }
+			this.each(function() {
+				var instance = instances[$.data(this, "jstree_instance_id")],
+					methodValue = (instance && $.isFunction(instance[settings])) ? instance[settings].apply(instance, args) : instance;
+					if(typeof methodValue !== "undefined" && (settings.indexOf("is_") === 0 || (methodValue !== true && methodValue !== false))) { returnValue = methodValue; return false; }
+			});
+		}
+		else {
+			this.each(function() {
+				// extend settings and allow for multiple hashes and $.data
+				var instance_id = $.data(this, "jstree_instance_id"),
+					a = [],
+					b = settings ? $.extend({}, true, settings) : {},
+					c = $(this), 
+					s = false, 
+					t = [];
+				a = a.concat(args);
+				if(c.data("jstree")) { a.push(c.data("jstree")); }
+				b = a.length ? $.extend.apply(null, [true, b].concat(a)) : b;
+
+				// if an instance already exists, destroy it first
+				if(typeof instance_id !== "undefined" && instances[instance_id]) { instances[instance_id].destroy(); }
+				// push a new empty object to the instances array
+				instance_id = parseInt(instances.push({}),10) - 1;
+				// store the jstree instance id to the container element
+				$.data(this, "jstree_instance_id", instance_id);
+				// clean up all plugins
+				b.plugins = $.isArray(b.plugins) ? b.plugins : $.jstree.defaults.plugins.slice();
+				b.plugins.unshift("core");
+				// only unique plugins
+				b.plugins = b.plugins.sort().join(",,").replace(/(,|^)([^,]+)(,,\2)+(,|$)/g,"$1$2$4").replace(/,,+/g,",").replace(/,$/,"").split(",");
+
+				// extend defaults with passed data
+				s = $.extend(true, {}, $.jstree.defaults, b);
+				s.plugins = b.plugins;
+				$.each(plugins, function (i, val) { 
+					if($.inArray(i, s.plugins) === -1) { s[i] = null; delete s[i]; } 
+					else { t.push(i); }
+				});
+				s.plugins = t;
+
+				// push the new object to the instances array (at the same time set the default classes to the container) and init
+				instances[instance_id] = new $.jstree._instance(instance_id, $(this).addClass("jstree jstree-" + instance_id), s); 
+				// init all activated plugins for this instance
+				$.each(instances[instance_id]._get_settings().plugins, function (i, val) { instances[instance_id].data[val] = {}; });
+				$.each(instances[instance_id]._get_settings().plugins, function (i, val) { if(plugins[val]) { plugins[val].__init.apply(instances[instance_id]); } });
+				// initialize the instance
+				setTimeout(function() { if(instances[instance_id]) { instances[instance_id].init(); } }, 0);
+			});
+		}
+		// return the jquery selection (or if it was a method call that returned a value - the returned value)
+		return returnValue;
+	};
+	// object to store exposed functions and objects
+	$.jstree = {
+		defaults : {
+			plugins : []
+		},
+		_focused : function () { return instances[focused_instance] || null; },
+		_reference : function (needle) { 
+			// get by instance id
+			if(instances[needle]) { return instances[needle]; }
+			// get by DOM (if still no luck - return null
+			var o = $(needle); 
+			if(!o.length && typeof needle === "string") { o = $("#" + needle); }
+			if(!o.length) { return null; }
+			return instances[o.closest(".jstree").data("jstree_instance_id")] || null; 
+		},
+		_instance : function (index, container, settings) { 
+			// for plugins to store data in
+			this.data = { core : {} };
+			this.get_settings	= function () { return $.extend(true, {}, settings); };
+			this._get_settings	= function () { return settings; };
+			this.get_index		= function () { return index; };
+			this.get_container	= function () { return container; };
+			this.get_container_ul = function () { return container.children("ul:eq(0)"); };
+			this._set_settings	= function (s) { 
+				settings = $.extend(true, {}, settings, s);
+			};
+		},
+		_fn : { },
+		plugin : function (pname, pdata) {
+			pdata = $.extend({}, {
+				__init		: $.noop, 
+				__destroy	: $.noop,
+				_fn			: {},
+				defaults	: false
+			}, pdata);
+			plugins[pname] = pdata;
+
+			$.jstree.defaults[pname] = pdata.defaults;
+			$.each(pdata._fn, function (i, val) {
+				val.plugin		= pname;
+				val.old			= $.jstree._fn[i];
+				$.jstree._fn[i] = function () {
+					var rslt,
+						func = val,
+						args = Array.prototype.slice.call(arguments),
+						evnt = new $.Event("before.jstree"),
+						rlbk = false;
+
+					if(this.data.core.locked === true && i !== "unlock" && i !== "is_locked") { return; }
+
+					// Check if function belongs to the included plugins of this instance
+					do {
+						if(func && func.plugin && $.inArray(func.plugin, this._get_settings().plugins) !== -1) { break; }
+						func = func.old;
+					} while(func);
+					if(!func) { return; }
+
+					// context and function to trigger events, then finally call the function
+					if(i.indexOf("_") === 0) {
+						rslt = func.apply(this, args);
+					}
+					else {
+						rslt = this.get_container().triggerHandler(evnt, { "func" : i, "inst" : this, "args" : args, "plugin" : func.plugin });
+						if(rslt === false) { return; }
+						if(typeof rslt !== "undefined") { args = rslt; }
+
+						rslt = func.apply(
+							$.extend({}, this, { 
+								__callback : function (data) { 
+									this.get_container().triggerHandler( i + '.jstree', { "inst" : this, "args" : args, "rslt" : data, "rlbk" : rlbk });
+								},
+								__rollback : function () { 
+									rlbk = this.get_rollback();
+									return rlbk;
+								},
+								__call_old : function (replace_arguments) {
+									return func.old.apply(this, (replace_arguments ? Array.prototype.slice.call(arguments, 1) : args ) );
+								}
+							}), args);
+					}
+
+					// return the result
+					return rslt;
+				};
+				$.jstree._fn[i].old = val.old;
+				$.jstree._fn[i].plugin = pname;
+			});
+		},
+		rollback : function (rb) {
+			if(rb) {
+				if(!$.isArray(rb)) { rb = [ rb ]; }
+				$.each(rb, function (i, val) {
+					instances[val.i].set_rollback(val.h, val.d);
+				});
+			}
+		}
+	};
+	// set the prototype for all instances
+	$.jstree._fn = $.jstree._instance.prototype = {};
+
+	// load the css when DOM is ready
+	$(function() {
+		// code is copied from jQuery ($.browser is deprecated + there is a bug in IE)
+		var u = navigator.userAgent.toLowerCase(),
+			v = (u.match( /.+?(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
+			css_string = '' + 
+				'.jstree ul, .jstree li { display:block; margin:0 0 0 0; padding:0 0 0 0; list-style-type:none; } ' + 
+				'.jstree li { display:block; min-height:18px; line-height:18px; white-space:nowrap; margin-left:18px; min-width:18px; } ' + 
+				'.jstree-rtl li { margin-left:0; margin-right:18px; } ' + 
+				'.jstree > ul > li { margin-left:0px; } ' + 
+				'.jstree-rtl > ul > li { margin-right:0px; } ' + 
+				'.jstree ins { display:inline-block; text-decoration:none; width:18px; height:18px; margin:0 0 0 0; padding:0; } ' + 
+				'.jstree a { display:inline-block; line-height:16px; height:16px; color:black; white-space:nowrap; text-decoration:none; padding:1px 2px; margin:0; } ' + 
+				'.jstree a:focus { outline: none; } ' + 
+				'.jstree a > ins { height:16px; width:16px; } ' + 
+				'.jstree a > .jstree-icon { margin-right:3px; } ' + 
+				'.jstree-rtl a > .jstree-icon { margin-left:3px; margin-right:0; } ' + 
+				'li.jstree-open > ul { display:block; } ' + 
+				'li.jstree-closed > ul { display:none; } ';
+		// Correct IE 6 (does not support the > CSS selector)
+		if(/msie/.test(u) && parseInt(v, 10) == 6) { 
+			is_ie6 = true;
+
+			// fix image flicker and lack of caching
+			try {
+				document.execCommand("BackgroundImageCache", false, true);
+			} catch (err) { }
+
+			css_string += '' + 
+				'.jstree li { height:18px; margin-left:0; margin-right:0; } ' + 
+				'.jstree li li { margin-left:18px; } ' + 
+				'.jstree-rtl li li { margin-left:0px; margin-right:18px; } ' + 
+				'li.jstree-open ul { display:block; } ' + 
+				'li.jstree-closed ul { display:none !important; } ' + 
+				'.jstree li a { display:inline; border-width:0 !important; padding:0px 2px !important; } ' + 
+				'.jstree li a ins { height:16px; width:16px; margin-right:3px; } ' + 
+				'.jstree-rtl li a ins { margin-right:0px; margin-left:3px; } ';
+		}
+		// Correct IE 7 (shifts anchor nodes onhover)
+		if(/msie/.test(u) && parseInt(v, 10) == 7) { 
+			is_ie7 = true;
+			css_string += '.jstree li a { border-width:0 !important; padding:0px 2px !important; } ';
+		}
+		// correct ff2 lack of display:inline-block
+		if(!/compatible/.test(u) && /mozilla/.test(u) && parseFloat(v, 10) < 1.9) {
+			is_ff2 = true;
+			css_string += '' + 
+				'.jstree ins { display:-moz-inline-box; } ' + 
+				'.jstree li { line-height:12px; } ' + // WHY??
+				'.jstree a { display:-moz-inline-box; } ' + 
+				'.jstree .jstree-no-icons .jstree-checkbox { display:-moz-inline-stack !important; } ';
+				/* this shouldn't be here as it is theme specific */
+		}
+		// the default stylesheet
+		$.vakata.css.add_sheet({ str : css_string, title : "jstree" });
+	});
+
+	// core functions (open, close, create, update, delete)
+	$.jstree.plugin("core", {
+		__init : function () {
+			this.data.core.locked = false;
+			this.data.core.to_open = this.get_settings().core.initially_open;
+			this.data.core.to_load = this.get_settings().core.initially_load;
+		},
+		defaults : { 
+			html_titles	: false,
+			animation	: 500,
+			initially_open : [],
+			initially_load : [],
+			open_parents : true,
+			notify_plugins : true,
+			rtl			: false,
+			load_open	: false,
+			strings		: {
+				loading		: "Loading ...",
+				new_node	: "New node",
+				multiple_selection : "Multiple selection"
+			}
+		},
+		_fn : { 
+			init	: function () { 
+				this.set_focus(); 
+				if(this._get_settings().core.rtl) {
+					this.get_container().addClass("jstree-rtl").css("direction", "rtl");
+				}
+				this.get_container().html("<ul><li class='jstree-last jstree-leaf'><ins>&#160;</ins><a class='jstree-loading' href='#'><ins class='jstree-icon'>&#160;</ins>" + this._get_string("loading") + "</a></li></ul>");
+				this.data.core.li_height = this.get_container_ul().find("li.jstree-closed, li.jstree-leaf").eq(0).height() || 18;
+
+				this.get_container()
+					.delegate("li > ins", "click.jstree", $.proxy(function (event) {
+							var trgt = $(event.target);
+							// if(trgt.is("ins") && event.pageY - trgt.offset().top < this.data.core.li_height) { this.toggle_node(trgt); }
+							this.toggle_node(trgt);
+						}, this))
+					.bind("mousedown.jstree", $.proxy(function () { 
+							this.set_focus(); // This used to be setTimeout(set_focus,0) - why?
+						}, this))
+					.bind("dblclick.jstree", function (event) { 
+						var sel;
+						if(document.selection && document.selection.empty) { document.selection.empty(); }
+						else {
+							if(window.getSelection) {
+								sel = window.getSelection();
+								try { 
+									sel.removeAllRanges();
+									sel.collapse();
+								} catch (err) { }
+							}
+						}
+					});
+				if(this._get_settings().core.notify_plugins) {
+					this.get_container()
+						.bind("load_node.jstree", $.proxy(function (e, data) { 
+								var o = this._get_node(data.rslt.obj),
+									t = this;
+								if(o === -1) { o = this.get_container_ul(); }
+								if(!o.length) { return; }
+								o.find("li").each(function () {
+									var th = $(this);
+									if(th.data("jstree")) {
+										$.each(th.data("jstree"), function (plugin, values) {
+											if(t.data[plugin] && $.isFunction(t["_" + plugin + "_notify"])) {
+												t["_" + plugin + "_notify"].call(t, th, values);
+											}
+										});
+									}
+								});
+							}, this));
+				}
+				if(this._get_settings().core.load_open) {
+					this.get_container()
+						.bind("load_node.jstree", $.proxy(function (e, data) { 
+								var o = this._get_node(data.rslt.obj),
+									t = this;
+								if(o === -1) { o = this.get_container_ul(); }
+								if(!o.length) { return; }
+								o.find("li.jstree-open:not(:has(ul))").each(function () {
+									t.load_node(this, $.noop, $.noop);
+								});
+							}, this));
+				}
+				this.__callback();
+				this.load_node(-1, function () { this.loaded(); this.reload_nodes(); });
+			},
+			destroy	: function () { 
+				var i,
+					n = this.get_index(),
+					s = this._get_settings(),
+					_this = this;
+
+				$.each(s.plugins, function (i, val) {
+					try { plugins[val].__destroy.apply(_this); } catch(err) { }
+				});
+				this.__callback();
+				// set focus to another instance if this one is focused
+				if(this.is_focused()) { 
+					for(i in instances) { 
+						if(instances.hasOwnProperty(i) && i != n) { 
+							instances[i].set_focus(); 
+							break; 
+						} 
+					}
+				}
+				// if no other instance found
+				if(n === focused_instance) { focused_instance = -1; }
+				// remove all traces of jstree in the DOM (only the ones set using jstree*) and cleans all events
+				this.get_container()
+					.unbind(".jstree")
+					.undelegate(".jstree")
+					.removeData("jstree_instance_id")
+					.find("[class^='jstree']")
+						.andSelf()
+						.attr("class", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); });
+				$(document)
+					.unbind(".jstree-" + n)
+					.undelegate(".jstree-" + n);
+				// remove the actual data
+				instances[n] = null;
+				delete instances[n];
+			},
+
+			_core_notify : function (n, data) {
+				if(data.opened) {
+					this.open_node(n, false, true);
+				}
+			},
+
+			lock : function () {
+				this.data.core.locked = true;
+				this.get_container().children("ul").addClass("jstree-locked").css("opacity","0.7");
+				this.__callback({});
+			},
+			unlock : function () {
+				this.data.core.locked = false;
+				this.get_container().children("ul").removeClass("jstree-locked").css("opacity","1");
+				this.__callback({});
+			},
+			is_locked : function () { return this.data.core.locked; },
+			save_opened : function () {
+				var _this = this;
+				this.data.core.to_open = [];
+				this.get_container_ul().find("li.jstree-open").each(function () { 
+					if(this.id) { _this.data.core.to_open.push("#" + this.id.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:")); }
+				});
+				this.__callback(_this.data.core.to_open);
+			},
+			save_loaded : function () { },
+			reload_nodes : function (is_callback) {
+				var _this = this,
+					done = true,
+					current = [],
+					remaining = [];
+				if(!is_callback) { 
+					this.data.core.reopen = false; 
+					this.data.core.refreshing = true; 
+					this.data.core.to_open = $.map($.makeArray(this.data.core.to_open), function (n) { return "#" + n.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:"); });
+					this.data.core.to_load = $.map($.makeArray(this.data.core.to_load), function (n) { return "#" + n.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:"); });
+					if(this.data.core.to_open.length) {
+						this.data.core.to_load = this.data.core.to_load.concat(this.data.core.to_open);
+					}
+				}
+				if(this.data.core.to_load.length) {
+					$.each(this.data.core.to_load, function (i, val) {
+						if(val == "#") { return true; }
+						if($(val).length) { current.push(val); }
+						else { remaining.push(val); }
+					});
+					if(current.length) {
+						this.data.core.to_load = remaining;
+						$.each(current, function (i, val) { 
+							if(!_this._is_loaded(val)) {
+								_this.load_node(val, function () { _this.reload_nodes(true); }, function () { _this.reload_nodes(true); });
+								done = false;
+							}
+						});
+					}
+				}
+				if(this.data.core.to_open.length) {
+					$.each(this.data.core.to_open, function (i, val) {
+						_this.open_node(val, false, true); 
+					});
+				}
+				if(done) { 
+					// TODO: find a more elegant approach to syncronizing returning requests
+					if(this.data.core.reopen) { clearTimeout(this.data.core.reopen); }
+					this.data.core.reopen = setTimeout(function () { _this.__callback({}, _this); }, 50);
+					this.data.core.refreshing = false;
+					this.reopen();
+				}
+			},
+			reopen : function () {
+				var _this = this;
+				if(this.data.core.to_open.length) {
+					$.each(this.data.core.to_open, function (i, val) {
+						_this.open_node(val, false, true); 
+					});
+				}
+				this.__callback({});
+			},
+			refresh : function (obj) {
+				var _this = this;
+				this.save_opened();
+				if(!obj) { obj = -1; }
+				obj = this._get_node(obj);
+				if(!obj) { obj = -1; }
+				if(obj !== -1) { obj.children("UL").remove(); }
+				else { this.get_container_ul().empty(); }
+				this.load_node(obj, function () { _this.__callback({ "obj" : obj}); _this.reload_nodes(); });
+			},
+			// Dummy function to fire after the first load (so that there is a jstree.loaded event)
+			loaded	: function () { 
+				this.__callback(); 
+			},
+			// deal with focus
+			set_focus	: function () { 
+				if(this.is_focused()) { return; }
+				var f = $.jstree._focused();
+				if(f) { f.unset_focus(); }
+
+				this.get_container().addClass("jstree-focused"); 
+				focused_instance = this.get_index(); 
+				this.__callback();
+			},
+			is_focused	: function () { 
+				return focused_instance == this.get_index(); 
+			},
+			unset_focus	: function () {
+				if(this.is_focused()) {
+					this.get_container().removeClass("jstree-focused"); 
+					focused_instance = -1; 
+				}
+				this.__callback();
+			},
+
+			// traverse
+			_get_node		: function (obj) { 
+				var $obj = $(obj, this.get_container()); 
+				if($obj.is(".jstree") || obj == -1) { return -1; } 
+				$obj = $obj.closest("li", this.get_container()); 
+				return $obj.length ? $obj : false; 
+			},
+			_get_next		: function (obj, strict) {
+				obj = this._get_node(obj);
+				if(obj === -1) { return this.get_container().find("> ul > li:first-child"); }
+				if(!obj.length) { return false; }
+				if(strict) { return (obj.nextAll("li").size() > 0) ? obj.nextAll("li:eq(0)") : false; }
+
+				if(obj.hasClass("jstree-open")) { return obj.find("li:eq(0)"); }
+				else if(obj.nextAll("li").size() > 0) { return obj.nextAll("li:eq(0)"); }
+				else { return obj.parentsUntil(".jstree","li").next("li").eq(0); }
+			},
+			_get_prev		: function (obj, strict) {
+				obj = this._get_node(obj);
+				if(obj === -1) { return this.get_container().find("> ul > li:last-child"); }
+				if(!obj.length) { return false; }
+				if(strict) { return (obj.prevAll("li").length > 0) ? obj.prevAll("li:eq(0)") : false; }
+
+				if(obj.prev("li").length) {
+					obj = obj.prev("li").eq(0);
+					while(obj.hasClass("jstree-open")) { obj = obj.children("ul:eq(0)").children("li:last"); }
+					return obj;
+				}
+				else { var o = obj.parentsUntil(".jstree","li:eq(0)"); return o.length ? o : false; }
+			},
+			_get_parent		: function (obj) {
+				obj = this._get_node(obj);
+				if(obj == -1 || !obj.length) { return false; }
+				var o = obj.parentsUntil(".jstree", "li:eq(0)");
+				return o.length ? o : -1;
+			},
+			_get_children	: function (obj) {
+				obj = this._get_node(obj);
+				if(obj === -1) { return this.get_container().children("ul:eq(0)").children("li"); }
+				if(!obj.length) { return false; }
+				return obj.children("ul:eq(0)").children("li");
+			},
+			get_path		: function (obj, id_mode) {
+				var p = [],
+					_this = this;
+				obj = this._get_node(obj);
+				if(obj === -1 || !obj || !obj.length) { return false; }
+				obj.parentsUntil(".jstree", "li").each(function () {
+					p.push( id_mode ? this.id : _this.get_text(this) );
+				});
+				p.reverse();
+				p.push( id_mode ? obj.attr("id") : this.get_text(obj) );
+				return p;
+			},
+
+			// string functions
+			_get_string : function (key) {
+				return this._get_settings().core.strings[key] || key;
+			},
+
+			is_open		: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-open"); },
+			is_closed	: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-closed"); },
+			is_leaf		: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-leaf"); },
+			correct_state	: function (obj) {
+				obj = this._get_node(obj);
+				if(!obj || obj === -1) { return false; }
+				obj.removeClass("jstree-closed jstree-open").addClass("jstree-leaf").children("ul").remove();
+				this.__callback({ "obj" : obj });
+			},
+			// open/close
+			open_node	: function (obj, callback, skip_animation) {
+				obj = this._get_node(obj);
+				if(!obj.length) { return false; }
+				if(!obj.hasClass("jstree-closed")) { if(callback) { callback.call(); } return false; }
+				var s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation,
+					t = this;
+				if(!this._is_loaded(obj)) {
+					obj.children("a").addClass("jstree-loading");
+					this.load_node(obj, function () { t.open_node(obj, callback, skip_animation); }, callback);
+				}
+				else {
+					if(this._get_settings().core.open_parents) {
+						obj.parentsUntil(".jstree",".jstree-closed").each(function () {
+							t.open_node(this, false, true);
+						});
+					}
+					if(s) { obj.children("ul").css("display","none"); }
+					obj.removeClass("jstree-closed").addClass("jstree-open").children("a").removeClass("jstree-loading");
+					if(s) { obj.children("ul").stop(true, true).slideDown(s, function () { this.style.display = ""; t.after_open(obj); }); }
+					else { t.after_open(obj); }
+					this.__callback({ "obj" : obj });
+					if(callback) { callback.call(); }
+				}
+			},
+			after_open	: function (obj) { this.__callback({ "obj" : obj }); },
+			close_node	: function (obj, skip_animation) {
+				obj = this._get_node(obj);
+				var s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation,
+					t = this;
+				if(!obj.length || !obj.hasClass("jstree-open")) { return false; }
+				if(s) { obj.children("ul").attr("style","display:block !important"); }
+				obj.removeClass("jstree-open").addClass("jstree-closed");
+				if(s) { obj.children("ul").stop(true, true).slideUp(s, function () { this.style.display = ""; t.after_close(obj); }); }
+				else { t.after_close(obj); }
+				this.__callback({ "obj" : obj });
+			},
+			after_close	: function (obj) { this.__callback({ "obj" : obj }); },
+			toggle_node	: function (obj) {
+				obj = this._get_node(obj);
+				if(obj.hasClass("jstree-closed")) { return this.open_node(obj); }
+				if(obj.hasClass("jstree-open")) { return this.close_node(obj); }
+			},
+			open_all	: function (obj, do_animation, original_obj) {
+				obj = obj ? this._get_node(obj) : -1;
+				if(!obj || obj === -1) { obj = this.get_container_ul(); }
+				if(original_obj) { 
+					obj = obj.find("li.jstree-closed");
+				}
+				else {
+					original_obj = obj;
+					if(obj.is(".jstree-closed")) { obj = obj.find("li.jstree-closed").andSelf(); }
+					else { obj = obj.find("li.jstree-closed"); }
+				}
+				var _this = this;
+				obj.each(function () { 
+					var __this = this; 
+					if(!_this._is_loaded(this)) { _this.open_node(this, function() { _this.open_all(__this, do_animation, original_obj); }, !do_animation); }
+					else { _this.open_node(this, false, !do_animation); }
+				});
+				// so that callback is fired AFTER all nodes are open
+				if(original_obj.find('li.jstree-closed').length === 0) { this.__callback({ "obj" : original_obj }); }
+			},
+			close_all	: function (obj, do_animation) {
+				var _this = this;
+				obj = obj ? this._get_node(obj) : this.get_container();
+				if(!obj || obj === -1) { obj = this.get_container_ul(); }
+				obj.find("li.jstree-open").andSelf().each(function () { _this.close_node(this, !do_animation); });
+				this.__callback({ "obj" : obj });
+			},
+			clean_node	: function (obj) {
+				obj = obj && obj != -1 ? $(obj) : this.get_container_ul();
+				obj = obj.is("li") ? obj.find("li").andSelf() : obj.find("li");
+				obj.removeClass("jstree-last")
+					.filter("li:last-child").addClass("jstree-last").end()
+					.filter(":has(li)")
+						.not(".jstree-open").removeClass("jstree-leaf").addClass("jstree-closed");
+				obj.not(".jstree-open, .jstree-closed").addClass("jstree-leaf").children("ul").remove();
+				this.__callback({ "obj" : obj });
+			},
+			// rollback
+			get_rollback : function () { 
+				this.__callback();
+				return { i : this.get_index(), h : this.get_container().children("ul").clone(true), d : this.data }; 
+			},
+			set_rollback : function (html, data) {
+				this.get_container().empty().append(html);
+				this.data = data;
+				this.__callback();
+			},
+			// Dummy functions to be overwritten by any datastore plugin included
+			load_node	: function (obj, s_call, e_call) { this.__callback({ "obj" : obj }); },
+			_is_loaded	: function (obj) { return true; },
+
+			// Basic operations: create
+			create_node	: function (obj, position, js, callback, is_loaded) {
+				obj = this._get_node(obj);
+				position = typeof position === "undefined" ? "last" : position;
+				var d = $("<li />"),
+					s = this._get_settings().core,
+					tmp;
+
+				if(obj !== -1 && !obj.length) { return false; }
+				if(!is_loaded && !this._is_loaded(obj)) { this.load_node(obj, function () { this.create_node(obj, position, js, callback, true); }); return false; }
+
+				this.__rollback();
+
+				if(typeof js === "string") { js = { "data" : js }; }
+				if(!js) { js = {}; }
+				if(js.attr) { d.attr(js.attr); }
+				if(js.metadata) { d.data(js.metadata); }
+				if(js.state) { d.addClass("jstree-" + js.state); }
+				if(!js.data) { js.data = this._get_string("new_node"); }
+				if(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); }
+				$.each(js.data, function (i, m) {
+					tmp = $("<a />");
+					if($.isFunction(m)) { m = m.call(this, js); }
+					if(typeof m == "string") { tmp.attr('href','#')[ s.html_titles ? "html" : "text" ](m); }
+					else {
+						if(!m.attr) { m.attr = {}; }
+						if(!m.attr.href) { m.attr.href = '#'; }
+						tmp.attr(m.attr)[ s.html_titles ? "html" : "text" ](m.title);
+						if(m.language) { tmp.addClass(m.language); }
+					}
+					tmp.prepend("<ins class='jstree-icon'>&#160;</ins>");
+					if(!m.icon && js.icon) { m.icon = js.icon; }
+					if(m.icon) { 
+						if(m.icon.indexOf("/") === -1) { tmp.children("ins").addClass(m.icon); }
+						else { tmp.children("ins").css("background","url('" + m.icon + "') center center no-repeat"); }
+					}
+					d.append(tmp);
+				});
+				d.prepend("<ins class='jstree-icon'>&#160;</ins>");
+				if(obj === -1) {
+					obj = this.get_container();
+					if(position === "before") { position = "first"; }
+					if(position === "after") { position = "last"; }
+				}
+				switch(position) {
+					case "before": obj.before(d); tmp = this._get_parent(obj); break;
+					case "after" : obj.after(d);  tmp = this._get_parent(obj); break;
+					case "inside":
+					case "first" :
+						if(!obj.children("ul").length) { obj.append("<ul />"); }
+						obj.children("ul").prepend(d);
+						tmp = obj;
+						break;
+					case "last":
+						if(!obj.children("ul").length) { obj.append("<ul />"); }
+						obj.children("ul").append(d);
+						tmp = obj;
+						break;
+					default:
+						if(!obj.children("ul").length) { obj.append("<ul />"); }
+						if(!position) { position = 0; }
+						tmp = obj.children("ul").children("li").eq(position);
+						if(tmp.length) { tmp.before(d); }
+						else { obj.children("ul").append(d); }
+						tmp = obj;
+						break;
+				}
+				if(tmp === -1 || tmp.get(0) === this.get_container().get(0)) { tmp = -1; }
+				this.clean_node(tmp);
+				this.__callback({ "obj" : d, "parent" : tmp });
+				if(callback) { callback.call(this, d); }
+				return d;
+			},
+			// Basic operations: rename (deal with text)
+			get_text	: function (obj) {
+				obj = this._get_node(obj);
+				if(!obj.length) { return false; }
+				var s = this._get_settings().core.html_titles;
+				obj = obj.children("a:eq(0)");
+				if(s) {
+					obj = obj.clone();
+					obj.children("INS").remove();
+					return obj.html();
+				}
+				else {
+					obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];
+					return obj.nodeValue;
+				}
+			},
+			set_text	: function (obj, val) {
+				obj = this._get_node(obj);
+				if(!obj.length) { return false; }
+				obj = obj.children("a:eq(0)");
+				if(this._get_settings().core.html_titles) {
+					var tmp = obj.children("INS").clone();
+					obj.html(val).prepend(tmp);
+					this.__callback({ "obj" : obj, "name" : val });
+					return true;
+				}
+				else {
+					obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];
+					this.__callback({ "obj" : obj, "name" : val });
+					return (obj.nodeValue = val);
+				}
+			},
+			rename_node : function (obj, val) {
+				obj = this._get_node(obj);
+				this.__rollback();
+				if(obj && obj.length && this.set_text.apply(this, Array.prototype.slice.call(arguments))) { this.__callback({ "obj" : obj, "name" : val }); }
+			},
+			// Basic operations: deleting nodes
+			delete_node : function (obj) {
+				obj = this._get_node(obj);
+				if(!obj.length) { return false; }
+				this.__rollback();
+				var p = this._get_parent(obj), prev = $([]), t = this;
+				obj.each(function () {
+					prev = prev.add(t._get_prev(this));
+				});
+				obj = obj.detach();
+				if(p !== -1 && p.find("> ul > li").length === 0) {
+					p.removeClass("jstree-open jstree-closed").addClass("jstree-leaf");
+				}
+				this.clean_node(p);
+				this.__callback({ "obj" : obj, "prev" : prev, "parent" : p });
+				return obj;
+			},
+			prepare_move : function (o, r, pos, cb, is_cb) {
+				var p = {};
+
+				p.ot = $.jstree._reference(o) || this;
+				p.o = p.ot._get_node(o);
+				p.r = r === - 1 ? -1 : this._get_node(r);
+				p.p = (typeof pos === "undefined" || pos === false) ? "last" : pos; // TODO: move to a setting
+				if(!is_cb && prepared_move.o && prepared_move.o[0] === p.o[0] && prepared_move.r[0] === p.r[0] && prepared_move.p === p.p) {
+					this.__callback(prepared_move);
+					if(cb) { cb.call(this, prepared_move); }
+					return;
+				}
+				p.ot = $.jstree._reference(p.o) || this;
+				p.rt = $.jstree._reference(p.r) || this; // r === -1 ? p.ot : $.jstree._reference(p.r) || this
+				if(p.r === -1 || !p.r) {
+					p.cr = -1;
+					switch(p.p) {
+						case "first":
+						case "before":
+						case "inside":
+							p.cp = 0; 
+							break;
+						case "after":
+						case "last":
+							p.cp = p.rt.get_container().find(" > ul > li").length; 
+							break;
+						default:
+							p.cp = p.p;
+							break;
+					}
+				}
+				else {
+					if(!/^(before|after)$/.test(p.p) && !this._is_loaded(p.r)) {
+						return this.load_node(p.r, function () { this.prepare_move(o, r, pos, cb, true); });
+					}
+					switch(p.p) {
+						case "before":
+							p.cp = p.r.index();
+							p.cr = p.rt._get_parent(p.r);
+							break;
+						case "after":
+							p.cp = p.r.index() + 1;
+							p.cr = p.rt._get_parent(p.r);
+							break;
+						case "inside":
+						case "first":
+							p.cp = 0;
+							p.cr = p.r;
+							break;
+						case "last":
+							p.cp = p.r.find(" > ul > li").length; 
+							p.cr = p.r;
+							break;
+						default: 
+							p.cp = p.p;
+							p.cr = p.r;
+							break;
+					}
+				}
+				p.np = p.cr == -1 ? p.rt.get_container() : p.cr;
+				p.op = p.ot._get_parent(p.o);
+				p.cop = p.o.index();
+				if(p.op === -1) { p.op = p.ot ? p.ot.get_container() : this.get_container(); }
+				if(!/^(before|after)$/.test(p.p) && p.op && p.np && p.op[0] === p.np[0] && p.o.index() < p.cp) { p.cp++; }
+				//if(p.p === "before" && p.op && p.np && p.op[0] === p.np[0] && p.o.index() < p.cp) { p.cp--; }
+				p.or = p.np.find(" > ul > li:nth-child(" + (p.cp + 1) + ")");
+				prepared_move = p;
+				this.__callback(prepared_move);
+				if(cb) { cb.call(this, prepared_move); }
+			},
+			check_move : function () {
+				var obj = prepared_move, ret = true, r = obj.r === -1 ? this.get_container() : obj.r;
+				if(!obj || !obj.o || obj.or[0] === obj.o[0]) { return false; }
+				if(obj.op && obj.np && obj.op[0] === obj.np[0] && obj.cp - 1 === obj.o.index()) { return false; }
+				obj.o.each(function () { 
+					if(r.parentsUntil(".jstree", "li").andSelf().index(this) !== -1) { ret = false; return false; }
+				});
+				return ret;
+			},
+			move_node : function (obj, ref, position, is_copy, is_prepared, skip_check) {
+				if(!is_prepared) { 
+					return this.prepare_move(obj, ref, position, function (p) {
+						this.move_node(p, false, false, is_copy, true, skip_check);
+					});
+				}
+				if(is_copy) { 
+					prepared_move.cy = true;
+				}
+				if(!skip_check && !this.check_move()) { return false; }
+
+				this.__rollback();
+				var o = false;
+				if(is_copy) {
+					o = obj.o.clone(true);
+					o.find("*[id]").andSelf().each(function () {
+						if(this.id) { this.id = "copy_" + this.id; }
+					});
+				}
+				else { o = obj.o; }
+
+				if(obj.or.length) { obj.or.before(o); }
+				else { 
+					if(!obj.np.children("ul").length) { $("<ul />").appendTo(obj.np); }
+					obj.np.children("ul:eq(0)").append(o); 
+				}
+
+				try { 
+					obj.ot.clean_node(obj.op);
+					obj.rt.clean_node(obj.np);
+					if(!obj.op.find("> ul > li").length) {
+						obj.op.removeClass("jstree-open jstree-closed").addClass("jstree-leaf").children("ul").remove();
+					}
+				} catch (e) { }
+
+				if(is_copy) { 
+					prepared_move.cy = true;
+					prepared_move.oc = o; 
+				}
+				this.__callback(prepared_move);
+				return prepared_move;
+			},
+			_get_move : function () { return prepared_move; }
+		}
+	});
+})(jQuery);
+//*/
+
+/* 
+ * jsTree ui plugin
+ * This plugins handles selecting/deselecting/hovering/dehovering nodes
+ */
+(function ($) {
+	var scrollbar_width, e1, e2;
+	$(function() {
+		if (/msie/.test(navigator.userAgent.toLowerCase())) {
+			e1 = $('<textarea cols="10" rows="2"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body');
+			e2 = $('<textarea cols="10" rows="2" style="overflow: hidden;"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body');
+			scrollbar_width = e1.width() - e2.width();
+			e1.add(e2).remove();
+		} 
+		else {
+			e1 = $('<div />').css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: 0 })
+					.prependTo('body').append('<div />').find('div').css({ width: '100%', height: 200 });
+			scrollbar_width = 100 - e1.width();
+			e1.parent().remove();
+		}
+	});
+	$.jstree.plugin("ui", {
+		__init : function () { 
+			this.data.ui.selected = $(); 
+			this.data.ui.last_selected = false; 
+			this.data.ui.hovered = null;
+			this.data.ui.to_select = this.get_settings().ui.initially_select;
+
+			this.get_container()
+				.delegate("a", "click.jstree", $.proxy(function (event) {
+						event.preventDefault();
+						event.currentTarget.blur();
+						if(!$(event.currentTarget).hasClass("jstree-loading")) {
+							this.select_node(event.currentTarget, true, event);
+						}
+					}, this))
+				.delegate("a", "mouseenter.jstree", $.proxy(function (event) {
+						if(!$(event.currentTarget).hasClass("jstree-loading")) {
+							this.hover_node(event.target);
+						}
+					}, this))
+				.delegate("a", "mouseleave.jstree", $.proxy(function (event) {
+						if(!$(event.currentTarget).hasClass("jstree-loading")) {
+							this.dehover_node(event.target);
+						}
+					}, this))
+				.bind("reopen.jstree", $.proxy(function () { 
+						this.reselect();
+					}, this))
+				.bind("get_rollback.jstree", $.proxy(function () { 
+						this.dehover_node();
+						this.save_selected();
+					}, this))
+				.bind("set_rollback.jstree", $.proxy(function () { 
+						this.reselect();
+					}, this))
+				.bind("close_node.jstree", $.proxy(function (event, data) { 
+						var s = this._get_settings().ui,
+							obj = this._get_node(data.rslt.obj),
+							clk = (obj && obj.length) ? obj.children("ul").find("a.jstree-clicked") : $(),
+							_this = this;
+						if(s.selected_parent_close === false || !clk.length) { return; }
+						clk.each(function () { 
+							_this.deselect_node(this);
+							if(s.selected_parent_close === "select_parent") { _this.select_node(obj); }
+						});
+					}, this))
+				.bind("delete_node.jstree", $.proxy(function (event, data) { 
+						var s = this._get_settings().ui.select_prev_on_delete,
+							obj = this._get_node(data.rslt.obj),
+							clk = (obj && obj.length) ? obj.find("a.jstree-clicked") : [],
+							_this = this;
+						clk.each(function () { _this.deselect_node(this); });
+						if(s && clk.length) { 
+							data.rslt.prev.each(function () { 
+								if(this.parentNode) { _this.select_node(this); return false; /* if return false is removed all prev nodes will be selected */}
+							});
+						}
+					}, this))
+				.bind("move_node.jstree", $.proxy(function (event, data) { 
+						if(data.rslt.cy) { 
+							data.rslt.oc.find("a.jstree-clicked").removeClass("jstree-clicked");
+						}
+					}, this));
+		},
+		defaults : {
+			select_limit : -1, // 0, 1, 2 ... or -1 for unlimited
+			select_multiple_modifier : "ctrl", // on, or ctrl, shift, alt
+			select_range_modifier : "shift",
+			selected_parent_close : "select_parent", // false, "deselect", "select_parent"
+			selected_parent_open : true,
+			select_prev_on_delete : true,
+			disable_selecting_children : false,
+			initially_select : []
+		},
+		_fn : { 
+			_get_node : function (obj, allow_multiple) {
+				if(typeof obj === "undefined" || obj === null) { return allow_multiple ? this.data.ui.selected : this.data.ui.last_selected; }
+				var $obj = $(obj, this.get_container()); 
+				if($obj.is(".jstree") || obj == -1) { return -1; } 
+				$obj = $obj.closest("li", this.get_container()); 
+				return $obj.length ? $obj : false; 
+			},
+			_ui_notify : function (n, data) {
+				if(data.selected) {
+					this.select_node(n, false);
+				}
+			},
+			save_selected : function () {
+				var _this = this;
+				this.data.ui.to_select = [];
+				this.data.ui.selected.each(function () { if(this.id) { _this.data.ui.to_select.push("#" + this.id.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:")); } });
+				this.__callback(this.data.ui.to_select);
+			},
+			reselect : function () {
+				var _this = this,
+					s = this.data.ui.to_select;
+				s = $.map($.makeArray(s), function (n) { return "#" + n.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:"); });
+				// this.deselect_all(); WHY deselect, breaks plugin state notifier?
+				$.each(s, function (i, val) { if(val && val !== "#") { _this.select_node(val); } });
+				this.data.ui.selected = this.data.ui.selected.filter(function () { return this.parentNode; });
+				this.__callback();
+			},
+			refresh : function (obj) {
+				this.save_selected();
+				return this.__call_old();
+			},
+			hover_node : function (obj) {
+				obj = this._get_node(obj);
+				if(!obj.length) { return false; }
+				//if(this.data.ui.hovered && obj.get(0) === this.data.ui.hovered.get(0)) { return; }
+				if(!obj.hasClass("jstree-hovered")) { this.dehover_node(); }
+				this.data.ui.hovered = obj.children("a").addClass("jstree-hovered").parent();
+				this._fix_scroll(obj);
+				this.__callback({ "obj" : obj });
+			},
+			dehover_node : function () {
+				var obj = this.data.ui.hovered, p;
+				if(!obj || !obj.length) { return false; }
+				p = obj.children("a").removeClass("jstree-hovered").parent();
+				if(this.data.ui.hovered[0] === p[0]) { this.data.ui.hovered = null; }
+				this.__callback({ "obj" : obj });
+			},
+			select_node : function (obj, check, e) {
+				obj = this._get_node(obj);
+				if(obj == -1 || !obj || !obj.length) { return false; }
+				var s = this._get_settings().ui,
+					is_multiple = (s.select_multiple_modifier == "on" || (s.select_multiple_modifier !== false && e && e[s.select_multiple_modifier + "Key"])),
+					is_range = (s.select_range_modifier !== false && e && e[s.select_range_modifier + "Key"] && this.data.ui.last_selected && this.data.ui.last_selected[0] !== obj[0] && this.data.ui.last_selected.parent()[0] === obj.parent()[0]),
+					is_selected = this.is_selected(obj),
+					proceed = true,
+					t = this;
+				if(check) {
+					if(s.disable_selecting_children && is_multiple && 
+						(
+							(obj.parentsUntil(".jstree","li").children("a.jstree-clicked").length) ||
+							(obj.children("ul").find("a.jstree-clicked:eq(0)").length)
+						)
+					) {
+						return false;
+					}
+					proceed = false;
+					switch(!0) {
+						case (is_range):
+							this.data.ui.last_selected.addClass("jstree-last-selected");
+							obj = obj[ obj.index() < this.data.ui.last_selected.index() ? "nextUntil" : "prevUntil" ](".jstree-last-selected").andSelf();
+							if(s.select_limit == -1 || obj.length < s.select_limit) {
+								this.data.ui.last_selected.removeClass("jstree-last-selected");
+								this.data.ui.selected.each(function () {
+									if(this !== t.data.ui.last_selected[0]) { t.deselect_node(this); }
+								});
+								is_selected = false;
+								proceed = true;
+							}
+							else {
+								proceed = false;
+							}
+							break;
+						case (is_selected && !is_multiple): 
+							this.deselect_all();
+							is_selected = false;
+							proceed = true;
+							break;
+						case (!is_selected && !is_multiple): 
+							if(s.select_limit == -1 || s.select_limit > 0) {
+								this.deselect_all();
+								proceed = true;
+							}
+							break;
+						case (is_selected && is_multiple): 
+							this.deselect_node(obj);
+							break;
+						case (!is_selected && is_multiple): 
+							if(s.select_limit == -1 || this.data.ui.selected.length + 1 <= s.select_limit) { 
+								proceed = true;
+							}
+							break;
+					}
+				}
+				if(proceed && !is_selected) {
+					if(!is_range) { this.data.ui.last_selected = obj; }
+					obj.children("a").addClass("jstree-clicked");
+					if(s.selected_parent_open) {
+						obj.parents(".jstree-closed").each(function () { t.open_node(this, false, true); });
+					}
+					this.data.ui.selected = this.data.ui.selected.add(obj);
+					this._fix_scroll(obj.eq(0));
+					this.__callback({ "obj" : obj, "e" : e });
+				}
+			},
+			_fix_scroll : function (obj) {
+				var c = this.get_container()[0], t;
+				if(c.scrollHeight > c.offsetHeight) {
+					obj = this._get_node(obj);
+					if(!obj || obj === -1 || !obj.length || !obj.is(":visible")) { return; }
+					t = obj.offset().top - this.get_container().offset().top;
+					if(t < 0) { 
+						c.scrollTop = c.scrollTop + t - 1; 
+					}
+					if(t + this.data.core.li_height + (c.scrollWidth > c.offsetWidth ? scrollbar_width : 0) > c.offsetHeight) { 
+						c.scrollTop = c.scrollTop + (t - c.offsetHeight + this.data.core.li_height + 1 + (c.scrollWidth > c.offsetWidth ? scrollbar_width : 0)); 
+					}
+				}
+			},
+			deselect_node : function (obj) {
+				obj = this._get_node(obj);
+				if(!obj.length) { return false; }
+				if(this.is_selected(obj)) {
+					obj.children("a").removeClass("jstree-clicked");
+					this.data.ui.selected = this.data.ui.selected.not(obj);
+					if(this.data.ui.last_selected.get(0) === obj.get(0)) { this.data.ui.last_selected = this.data.ui.selected.eq(0); }
+					this.__callback({ "obj" : obj });
+				}
+			},
+			toggle_select : function (obj) {
+				obj = this._get_node(obj);
+				if(!obj.length) { return false; }
+				if(this.is_selected(obj)) { this.deselect_node(obj); }
+				else { this.select_node(obj); }
+			},
+			is_selected : function (obj) { return this.data.ui.selected.index(this._get_node(obj)) >= 0; },
+			get_selected : function (context) { 
+				return context ? $(context).find("a.jstree-clicked").parent() : this.data.ui.selected; 
+			},
+			deselect_all : function (context) {
+				var ret = context ? $(context).find("a.jstree-clicked").parent() : this.get_container().find("a.jstree-clicked").parent();
+				ret.children("a.jstree-clicked").removeClass("jstree-clicked");
+				this.data.ui.selected = $([]);
+				this.data.ui.last_selected = false;
+				this.__callback({ "obj" : ret });
+			}
+		}
+	});
+	// include the selection plugin by default
+	$.jstree.defaults.plugins.push("ui");
+})(jQuery);
+//*/
+
+/* 
+ * jsTree CRRM plugin
+ * Handles creating/renaming/removing/moving nodes by user interaction.
+ */
+(function ($) {
+	$.jstree.plugin("crrm", { 
+		__init : function () {
+			this.get_container()
+				.bind("move_node.jstree", $.proxy(function (e, data) {
+					if(this._get_settings().crrm.move.open_onmove) {
+						var t = this;
+						data.rslt.np.parentsUntil(".jstree").andSelf().filter(".jstree-closed").each(function () {
+							t.open_node(this, false, true);
+						});
+					}
+				}, this));
+		},
+		defaults : {
+			input_width_limit : 200,
+			move : {
+				always_copy			: false, // false, true or "multitree"
+				open_onmove			: true,
+				default_position	: "last",
+				check_move			: function (m) { return true; }
+			}
+		},
+		_fn : {
+			_show_input : function (obj, callback) {
+				obj = this._get_node(obj);
+				var rtl = this._get_settings().core.rtl,
+					w = this._get_settings().crrm.input_width_limit,
+					w1 = obj.children("ins").width(),
+					w2 = obj.find("> a:visible > ins").width() * obj.find("> a:visible > ins").length,
+					t = this.get_text(obj),
+					h1 = $("<div />", { css : { "position" : "absolute", "top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility" : "hidden" } }).appendTo("body"),
+					h2 = obj.css("position","relative").append(
+					$("<input />", { 
+						"value" : t,
+						"class" : "jstree-rename-input",
+						// "size" : t.length,
+						"css" : {
+							"padding" : "0",
+							"border" : "1px solid silver",
+							"position" : "absolute",
+							"left"  : (rtl ? "auto" : (w1 + w2 + 4) + "px"),
+							"right" : (rtl ? (w1 + w2 + 4) + "px" : "auto"),
+							"top" : "0px",
+							"height" : (this.data.core.li_height - 2) + "px",
+							"lineHeight" : (this.data.core.li_height - 2) + "px",
+							"width" : "150px" // will be set a bit further down
+						},
+						"blur" : $.proxy(function () {
+							var i = obj.children(".jstree-rename-input"),
+								v = i.val();
+							if(v === "") { v = t; }
+							h1.remove();
+							i.remove(); // rollback purposes
+							this.set_text(obj,t); // rollback purposes
+							this.rename_node(obj, v);
+							callback.call(this, obj, v, t);
+							obj.css("position","");
+						}, this),
+						"keyup" : function (event) {
+							var key = event.keyCode || event.which;
+							if(key == 27) { this.value = t; this.blur(); return; }
+							else if(key == 13) { this.blur(); return; }
+							else {
+								h2.width(Math.min(h1.text("pW" + this.value).width(),w));
+							}
+						},
+						"keypress" : function(event) {
+							var key = event.keyCode || event.which;
+							if(key == 13) { return false; }
+						}
+					})
+				).children(".jstree-rename-input"); 
+				this.set_text(obj, "");
+				h1.css({
+						fontFamily		: h2.css('fontFamily')		|| '',
+						fontSize		: h2.css('fontSize')		|| '',
+						fontWeight		: h2.css('fontWeight')		|| '',
+						fontStyle		: h2.css('fontStyle')		|| '',
+						fontStretch		: h2.css('fontStretch')		|| '',
+						fontVariant		: h2.css('fontVariant')		|| '',
+						letterSpacing	: h2.css('letterSpacing')	|| '',
+						wordSpacing		: h2.css('wordSpacing')		|| ''
+				});
+				h2.width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select();
+			},
+			rename : function (obj) {
+				obj = this._get_node(obj);
+				this.__rollback();
+				var f = this.__callback;
+				this._show_input(obj, function (obj, new_name, old_name) { 
+					f.call(this, { "obj" : obj, "new_name" : new_name, "old_name" : old_name });
+				});
+			},
+			create : function (obj, position, js, callback, skip_rename) {
+				var t, _this = this;
+				obj = this._get_node(obj);
+				if(!obj) { obj = -1; }
+				this.__rollback();
+				t = this.create_node(obj, position, js, function (t) {
+					var p = this._get_parent(t),
+						pos = $(t).index();
+					if(callback) { callback.call(this, t); }
+					if(p.length && p.hasClass("jstree-closed")) { this.open_node(p, false, true); }
+					if(!skip_rename) { 
+						this._show_input(t, function (obj, new_name, old_name) { 
+							_this.__callback({ "obj" : obj, "name" : new_name, "parent" : p, "position" : pos });
+						});
+					}
+					else { _this.__callback({ "obj" : t, "name" : this.get_text(t), "parent" : p, "position" : pos }); }
+				});
+				return t;
+			},
+			remove : function (obj) {
+				obj = this._get_node(obj, true);
+				var p = this._get_parent(obj), prev = this._get_prev(obj);
+				this.__rollback();
+				obj = this.delete_node(obj);
+				if(obj !== false) { this.__callback({ "obj" : obj, "prev" : prev, "parent" : p }); }
+			},
+			check_move : function () {
+				if(!this.__call_old()) { return false; }
+				var s = this._get_settings().crrm.move;
+				if(!s.check_move.call(this, this._get_move())) { return false; }
+				return true;
+			},
+			move_node : function (obj, ref, position, is_copy, is_prepared, skip_check) {
+				var s = this._get_settings().crrm.move;
+				if(!is_prepared) { 
+					if(typeof position === "undefined") { position = s.default_position; }
+					if(position === "inside" && !s.default_position.match(/^(before|after)$/)) { position = s.default_position; }
+					return this.__call_old(true, obj, ref, position, is_copy, false, skip_check);
+				}
+				// if the move is already prepared
+				if(s.always_copy === true || (s.always_copy === "multitree" && obj.rt.get_index() !== obj.ot.get_index() )) {
+					is_copy = true;
+				}
+				this.__call_old(true, obj, ref, position, is_copy, true, skip_check);
+			},
+
+			cut : function (obj) {
+				obj = this._get_node(obj, true);
+				if(!obj || !obj.length) { return false; }
+				this.data.crrm.cp_nodes = false;
+				this.data.crrm.ct_nodes = obj;
+				this.__callback({ "obj" : obj });
+			},
+			copy : function (obj) {
+				obj = this._get_node(obj, true);
+				if(!obj || !obj.length) { return false; }
+				this.data.crrm.ct_nodes = false;
+				this.data.crrm.cp_nodes = obj;
+				this.__callback({ "obj" : obj });
+			},
+			paste : function (obj) { 
+				obj = this._get_node(obj);
+				if(!obj || !obj.length) { return false; }
+				var nodes = this.data.crrm.ct_nodes ? this.data.crrm.ct_nodes : this.data.crrm.cp_nodes;
+				if(!this.data.crrm.ct_nodes && !this.data.crrm.cp_nodes) { return false; }
+				if(this.data.crrm.ct_nodes) { this.move_node(this.data.crrm.ct_nodes, obj); this.data.crrm.ct_nodes = false; }
+				if(this.data.crrm.cp_nodes) { this.move_node(this.data.crrm.cp_nodes, obj, false, true); }
+				this.__callback({ "obj" : obj, "nodes" : nodes });
+			}
+		}
+	});
+	// include the crr plugin by default
+	// $.jstree.defaults.plugins.push("crrm");
+})(jQuery);
+//*/
+
+/* 
+ * jsTree themes plugin
+ * Handles loading and setting themes, as well as detecting path to themes, etc.
+ */
+(function ($) {
+	var themes_loaded = [];
+	// this variable stores the path to the themes folder - if left as false - it will be autodetected
+	$.jstree._themes = false;
+	$.jstree.plugin("themes", {
+		__init : function () { 
+			this.get_container()
+				.bind("init.jstree", $.proxy(function () {
+						var s = this._get_settings().themes;
+						this.data.themes.dots = s.dots; 
+						this.data.themes.icons = s.icons; 
+						this.set_theme(s.theme, s.url);
+					}, this))
+				.bind("loaded.jstree", $.proxy(function () {
+						// bound here too, as simple HTML tree's won't honor dots & icons otherwise
+						if(!this.data.themes.dots) { this.hide_dots(); }
+						else { this.show_dots(); }
+						if(!this.data.themes.icons) { this.hide_icons(); }
+						else { this.show_icons(); }
+					}, this));
+		},
+		defaults : { 
+			theme : "default", 
+			url : false,
+			dots : true,
+			icons : true
+		},
+		_fn : {
+			set_theme : function (theme_name, theme_url) {
+				if(!theme_name) { return false; }
+				if(!theme_url) { theme_url = $.jstree._themes + theme_name + '/style.css'; }
+				if($.inArray(theme_url, themes_loaded) == -1) {
+					$.vakata.css.add_sheet({ "url" : theme_url });
+					themes_loaded.push(theme_url);
+				}
+				if(this.data.themes.theme != theme_name) {
+					this.get_container().removeClass('jstree-' + this.data.themes.theme);
+					this.data.themes.theme = theme_name;
+				}
+				this.get_container().addClass('jstree-' + theme_name);
+				if(!this.data.themes.dots) { this.hide_dots(); }
+				else { this.show_dots(); }
+				if(!this.data.themes.icons) { this.hide_icons(); }
+				else { this.show_icons(); }
+				this.__callback();
+			},
+			get_theme	: function () { return this.data.themes.theme; },
+
+			show_dots	: function () { this.data.themes.dots = true; this.get_container().children("ul").removeClass("jstree-no-dots"); },
+			hide_dots	: function () { this.data.themes.dots = false; this.get_container().children("ul").addClass("jstree-no-dots"); },
+			toggle_dots	: function () { if(this.data.themes.dots) { this.hide_dots(); } else { this.show_dots(); } },
+
+			show_icons	: function () { this.data.themes.icons = true; this.get_container().children("ul").removeClass("jstree-no-icons"); },
+			hide_icons	: function () { this.data.themes.icons = false; this.get_container().children("ul").addClass("jstree-no-icons"); },
+			toggle_icons: function () { if(this.data.themes.icons) { this.hide_icons(); } else { this.show_icons(); } }
+		}
+	});
+	// autodetect themes path
+	$(function () {
+		if($.jstree._themes === false) {
+			$("script").each(function () { 
+				if(this.src.toString().match(/jquery\.jstree[^\/]*?\.js(\?.*)?$/)) { 
+					$.jstree._themes = this.src.toString().replace(/jquery\.jstree[^\/]*?\.js(\?.*)?$/, "") + 'themes/'; 
+					return false; 
+				}
+			});
+		}
+		if($.jstree._themes === false) { $.jstree._themes = "themes/"; }
+	});
+	// include the themes plugin by default
+	$.jstree.defaults.plugins.push("themes");
+})(jQuery);
+//*/
+
+/*
+ * jsTree hotkeys plugin
+ * Enables keyboard navigation for all tree instances
+ * Depends on the jstree ui & jquery hotkeys plugins
+ */
+(function ($) {
+	var bound = [];
+	function exec(i, event) {
+		var f = $.jstree._focused(), tmp;
+		if(f && f.data && f.data.hotkeys && f.data.hotkeys.enabled) { 
+			tmp = f._get_settings().hotkeys[i];
+			if(tmp) { return tmp.call(f, event); }
+		}
+	}
+	$.jstree.plugin("hotkeys", {
+		__init : function () {
+			if(typeof $.hotkeys === "undefined") { throw "jsTree hotkeys: jQuery hotkeys plugin not included."; }
+			if(!this.data.ui) { throw "jsTree hotkeys: jsTree UI plugin not included."; }
+			$.each(this._get_settings().hotkeys, function (i, v) {
+				if(v !== false && $.inArray(i, bound) == -1) {
+					$(document).bind("keydown", i, function (event) { return exec(i, event); });
+					bound.push(i);
+				}
+			});
+			this.get_container()
+				.bind("lock.jstree", $.proxy(function () {
+						if(this.data.hotkeys.enabled) { this.data.hotkeys.enabled = false; this.data.hotkeys.revert = true; }
+					}, this))
+				.bind("unlock.jstree", $.proxy(function () {
+						if(this.data.hotkeys.revert) { this.data.hotkeys.enabled = true; }
+					}, this));
+			this.enable_hotkeys();
+		},
+		defaults : {
+			"up" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected || -1;
+				this.hover_node(this._get_prev(o));
+				return false; 
+			},
+			"ctrl+up" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected || -1;
+				this.hover_node(this._get_prev(o));
+				return false; 
+			},
+			"shift+up" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected || -1;
+				this.hover_node(this._get_prev(o));
+				return false; 
+			},
+			"down" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected || -1;
+				this.hover_node(this._get_next(o));
+				return false;
+			},
+			"ctrl+down" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected || -1;
+				this.hover_node(this._get_next(o));
+				return false;
+			},
+			"shift+down" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected || -1;
+				this.hover_node(this._get_next(o));
+				return false;
+			},
+			"left" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected;
+				if(o) {
+					if(o.hasClass("jstree-open")) { this.close_node(o); }
+					else { this.hover_node(this._get_prev(o)); }
+				}
+				return false;
+			},
+			"ctrl+left" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected;
+				if(o) {
+					if(o.hasClass("jstree-open")) { this.close_node(o); }
+					else { this.hover_node(this._get_prev(o)); }
+				}
+				return false;
+			},
+			"shift+left" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected;
+				if(o) {
+					if(o.hasClass("jstree-open")) { this.close_node(o); }
+					else { this.hover_node(this._get_prev(o)); }
+				}
+				return false;
+			},
+			"right" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected;
+				if(o && o.length) {
+					if(o.hasClass("jstree-closed")) { this.open_node(o); }
+					else { this.hover_node(this._get_next(o)); }
+				}
+				return false;
+			},
+			"ctrl+right" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected;
+				if(o && o.length) {
+					if(o.hasClass("jstree-closed")) { this.open_node(o); }
+					else { this.hover_node(this._get_next(o)); }
+				}
+				return false;
+			},
+			"shift+right" : function () { 
+				var o = this.data.ui.hovered || this.data.ui.last_selected;
+				if(o && o.length) {
+					if(o.hasClass("jstree-closed")) { this.open_node(o); }
+					else { this.hover_node(this._get_next(o)); }
+				}
+				return false;
+			},
+			"space" : function () { 
+				if(this.data.ui.hovered) { this.data.ui.hovered.children("a:eq(0)").click(); } 
+				return false; 
+			},
+			"ctrl+space" : function (event) { 
+				event.type = "click";
+				if(this.data.ui.hovered) { this.data.ui.hovered.children("a:eq(0)").trigger(event); } 
+				return false; 
+			},
+			"shift+space" : function (event) { 
+				event.type = "click";
+				if(this.data.ui.hovered) { this.data.ui.hovered.children("a:eq(0)").trigger(event); } 
+				return false; 
+			},
+			"f2" : function () { this.rename(this.data.ui.hovered || this.data.ui.last_selected); },
+			"del" : function () { this.remove(this.data.ui.hovered || this._get_node(null)); }
+		},
+		_fn : {
+			enable_hotkeys : function () {
+				this.data.hotkeys.enabled = true;
+			},
+			disable_hotkeys : function () {
+				this.data.hotkeys.enabled = false;
+			}
+		}
+	});
+})(jQuery);
+//*/
+
+/* 
+ * jsTree JSON plugin
+ * The JSON data store. Datastores are build by overriding the `load_node` and `_is_loaded` functions.
+ */
+(function ($) {
+	$.jstree.plugin("json_data", {
+		__init : function() {
+			var s = this._get_settings().json_data;
+			if(s.progressive_unload) {
+				this.get_container().bind("after_close.jstree", function (e, data) {
+					data.rslt.obj.children("ul").remove();
+				});
+			}
+		},
+		defaults : { 
+			// `data` can be a function:
+			//  * accepts two arguments - node being loaded and a callback to pass the result to
+			//  * will be executed in the current tree's scope & ajax won't be supported
+			data : false, 
+			ajax : false,
+			correct_state : true,
+			progressive_render : false,
+			progressive_unload : false
+		},
+		_fn : {
+			load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_json(obj, function () { _this.__callback({ "obj" : _this._get_node(obj) }); s_call.call(this); }, e_call); },
+			_is_loaded : function (obj) { 
+				var s = this._get_settings().json_data;
+				obj = this._get_node(obj); 
+				return obj == -1 || !obj || (!s.ajax && !s.progressive_render && !$.isFunction(s.data)) || obj.is(".jstree-open, .jstree-leaf") || obj.children("ul").children("li").length > 0;
+			},
+			refresh : function (obj) {
+				obj = this._get_node(obj);
+				var s = this._get_settings().json_data;
+				if(obj && obj !== -1 && s.progressive_unload && ($.isFunction(s.data) || !!s.ajax)) {
+					obj.removeData("jstree_children");
+				}
+				return this.__call_old();
+			},
+			load_node_json : function (obj, s_call, e_call) {
+				var s = this.get_settings().json_data, d,
+					error_func = function () {},
+					success_func = function () {};
+				obj = this._get_node(obj);
+
+				if(obj && obj !== -1 && (s.progressive_render || s.progressive_unload) && !obj.is(".jstree-open, .jstree-leaf") && obj.children("ul").children("li").length === 0 && obj.data("jstree_children")) {
+					d = this._parse_json(obj.data("jstree_children"), obj);
+					if(d) {
+						obj.append(d);
+						if(!s.progressive_unload) { obj.removeData("jstree_children"); }
+					}
+					this.clean_node(obj);
+					if(s_call) { s_call.call(this); }
+					return;
+				}
+
+				if(obj && obj !== -1) {
+					if(obj.data("jstree_is_loading")) { return; }
+					else { obj.data("jstree_is_loading",true); }
+				}
+				switch(!0) {
+					case (!s.data && !s.ajax): throw "Neither data nor ajax settings supplied.";
+					// function option added here for easier model integration (also supporting async - see callback)
+					case ($.isFunction(s.data)):
+						s.data.call(this, obj, $.proxy(function (d) {
+							d = this._parse_json(d, obj);
+							if(!d) { 
+								if(obj === -1 || !obj) {
+									if(s.correct_state) { this.get_container().children("ul").empty(); }
+								}
+								else {
+									obj.children("a.jstree-loading").removeClass("jstree-loading");
+									obj.removeData("jstree_is_loading");
+									if(s.correct_state) { this.correct_state(obj); }
+								}
+								if(e_call) { e_call.call(this); }
+							}
+							else {
+								if(obj === -1 || !obj) { this.get_container().children("ul").empty().append(d.children()); }
+								else { obj.append(d).children("a.jstree-loading").removeClass("jstree-loading"); obj.removeData("jstree_is_loading"); }
+								this.clean_node(obj);
+								if(s_call) { s_call.call(this); }
+							}
+						}, this));
+						break;
+					case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):
+						if(!obj || obj == -1) {
+							d = this._parse_json(s.data, obj);
+							if(d) {
+								this.get_container().children("ul").empty().append(d.children());
+								this.clean_node();
+							}
+							else { 
+								if(s.correct_state) { this.get_container().children("ul").empty(); }
+							}
+						}
+						if(s_call) { s_call.call(this); }
+						break;
+					case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):
+						error_func = function (x, t, e) {
+							var ef = this.get_settings().json_data.ajax.error; 
+							if(ef) { ef.call(this, x, t, e); }
+							if(obj != -1 && obj.length) {
+								obj.children("a.jstree-loading").removeClass("jstree-loading");
+								obj.removeData("jstree_is_loading");
+								if(t === "success" && s.correct_state) { this.correct_state(obj); }
+							}
+							else {
+								if(t === "success" && s.correct_state) { this.get_container().children("ul").empty(); }
+							}
+							if(e_call) { e_call.call(this); }
+						};
+						success_func = function (d, t, x) {
+							var sf = this.get_settings().json_data.ajax.success; 
+							if(sf) { d = sf.call(this,d,t,x) || d; }
+							if(d === "" || (d && d.toString && d.toString().replace(/^[\s\n]+$/,"") === "") || (!$.isArray(d) && !$.isPlainObject(d))) {
+								return error_func.call(this, x, t, "");
+							}
+							d = this._parse_json(d, obj);
+							if(d) {
+								if(obj === -1 || !obj) { this.get_container().children("ul").empty().append(d.children()); }
+								else { obj.append(d).children("a.jstree-loading").removeClass("jstree-loading"); obj.removeData("jstree_is_loading"); }
+								this.clean_node(obj);
+								if(s_call) { s_call.call(this); }
+							}
+							else {
+								if(obj === -1 || !obj) {
+									if(s.correct_state) { 
+										this.get_container().children("ul").empty(); 
+										if(s_call) { s_call.call(this); }
+									}
+								}
+								else {
+									obj.children("a.jstree-loading").removeClass("jstree-loading");
+									obj.removeData("jstree_is_loading");
+									if(s.correct_state) { 
+										this.correct_state(obj);
+										if(s_call) { s_call.call(this); } 
+									}
+								}
+							}
+						};
+						s.ajax.context = this;
+						s.ajax.error = error_func;
+						s.ajax.success = success_func;
+						if(!s.ajax.dataType) { s.ajax.dataType = "json"; }
+						if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }
+						if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }
+						$.ajax(s.ajax);
+						break;
+				}
+			},
+			_parse_json : function (js, obj, is_callback) {
+				var d = false, 
+					p = this._get_settings(),
+					s = p.json_data,
+					t = p.core.html_titles,
+					tmp, i, j, ul1, ul2;
+
+				if(!js) { return d; }
+				if(s.progressive_unload && obj && obj !== -1) { 
+					obj.data("jstree_children", d);
+				}
+				if($.isArray(js)) {
+					d = $();
+					if(!js.length) { return false; }
+					for(i = 0, j = js.length; i < j; i++) {
+						tmp = this._parse_json(js[i], obj, true);
+						if(tmp.length) { d = d.add(tmp); }
+					}
+				}
+				else {
+					if(typeof js == "string") { js = { data : js }; }
+					if(!js.data && js.data !== "") { return d; }
+					d = $("<li />");
+					if(js.attr) { d.attr(js.attr); }
+					if(js.metadata) { d.data(js.metadata); }
+					if(js.state) { d.addClass("jstree-" + js.state); }
+					if(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); }
+					$.each(js.data, function (i, m) {
+						tmp = $("<a />");
+						if($.isFunction(m)) { m = m.call(this, js); }
+						if(typeof m == "string") { tmp.attr('href','#')[ t ? "html" : "text" ](m); }
+						else {
+							if(!m.attr) { m.attr = {}; }
+							if(!m.attr.href) { m.attr.href = '#'; }
+							tmp.attr(m.attr)[ t ? "html" : "text" ](m.title);
+							if(m.language) { tmp.addClass(m.language); }
+						}
+						tmp.prepend("<ins class='jstree-icon'>&#160;</ins>");
+						if(!m.icon && js.icon) { m.icon = js.icon; }
+						if(m.icon) { 
+							if(m.icon.indexOf("/") === -1) { tmp.children("ins").addClass(m.icon); }
+							else { tmp.children("ins").css("background","url('" + m.icon + "') center center no-repeat"); }
+						}
+						d.append(tmp);
+					});
+					d.prepend("<ins class='jstree-icon'>&#160;</ins>");
+					if(js.children) { 
+						if(s.progressive_render && js.state !== "open") {
+							d.addClass("jstree-closed").data("jstree_children", js.children);
+						}
+						else {
+							if(s.progressive_unload) { d.data("jstree_children", js.children); }
+							if($.isArray(js.children) && js.children.length) {
+								tmp = this._parse_json(js.children, obj, true);
+								if(tmp.length) {
+									ul2 = $("<ul />");
+									ul2.append(tmp);
+									d.append(ul2);
+								}
+							}
+						}
+					}
+				}
+				if(!is_callback) {
+					ul1 = $("<ul />");
+					ul1.append(d);
+					d = ul1;
+				}
+				return d;
+			},
+			get_json : function (obj, li_attr, a_attr, is_callback) {
+				var result = [], 
+					s = this._get_settings(), 
+					_this = this,
+					tmp1, tmp2, li, a, t, lang;
+				obj = this._get_node(obj);
+				if(!obj || obj === -1) { obj = this.get_container().find("> ul > li"); }
+				li_attr = $.isArray(li_attr) ? li_attr : [ "id", "class" ];
+				if(!is_callback && this.data.types) { li_attr.push(s.types.type_attr); }
+				a_attr = $.isArray(a_attr) ? a_attr : [ ];
+
+				obj.each(function () {
+					li = $(this);
+					tmp1 = { data : [] };
+					if(li_attr.length) { tmp1.attr = { }; }
+					$.each(li_attr, function (i, v) { 
+						tmp2 = li.attr(v); 
+						if(tmp2 && tmp2.length && tmp2.replace(/jstree[^ ]*/ig,'').length) {
+							tmp1.attr[v] = (" " + tmp2).replace(/ jstree[^ ]*/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,""); 
+						}
+					});
+					if(li.hasClass("jstree-open")) { tmp1.state = "open"; }
+					if(li.hasClass("jstree-closed")) { tmp1.state = "closed"; }
+					if(li.data()) { tmp1.metadata = li.data(); }
+					a = li.children("a");
+					a.each(function () {
+						t = $(this);
+						if(
+							a_attr.length || 
+							$.inArray("languages", s.plugins) !== -1 || 
+							t.children("ins").get(0).style.backgroundImage.length || 
+							(t.children("ins").get(0).className && t.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').length)
+						) { 
+							lang = false;
+							if($.inArray("languages", s.plugins) !== -1 && $.isArray(s.languages) && s.languages.length) {
+								$.each(s.languages, function (l, lv) {
+									if(t.hasClass(lv)) {
+										lang = lv;
+										return false;
+									}
+								});
+							}
+							tmp2 = { attr : { }, title : _this.get_text(t, lang) }; 
+							$.each(a_attr, function (k, z) {
+								tmp2.attr[z] = (" " + (t.attr(z) || "")).replace(/ jstree[^ ]*/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,"");
+							});
+							if($.inArray("languages", s.plugins) !== -1 && $.isArray(s.languages) && s.languages.length) {
+								$.each(s.languages, function (k, z) {
+									if(t.hasClass(z)) { tmp2.language = z; return true; }
+								});
+							}
+							if(t.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\s+$/ig,"").length) {
+								tmp2.icon = t.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,"");
+							}
+							if(t.children("ins").get(0).style.backgroundImage.length) {
+								tmp2.icon = t.children("ins").get(0).style.backgroundImage.replace("url(","").replace(")","");
+							}
+						}
+						else {
+							tmp2 = _this.get_text(t);
+						}
+						if(a.length > 1) { tmp1.data.push(tmp2); }
+						else { tmp1.data = tmp2; }
+					});
+					li = li.find("> ul > li");
+					if(li.length) { tmp1.children = _this.get_json(li, li_attr, a_attr, true); }
+					result.push(tmp1);
+				});
+				return result;
+			}
+		}
+	});
+})(jQuery);
+//*/
+
+/* 
+ * jsTree languages plugin
+ * Adds support for multiple language versions in one tree
+ * This basically allows for many titles coexisting in one node, but only one of them being visible at any given time
+ * This is useful for maintaining the same structure in many languages (hence the name of the plugin)
+ */
+(function ($) {
+	$.jstree.plugin("languages", {
+		__init : function () { this._load_css();  },
+		defaults : [],
+		_fn : {
+			set_lang : function (i) { 
+				var langs = this._get_settings().languages,
+					st = false,
+					selector = ".jstree-" + this.get_index() + ' a';
+				if(!$.isArray(langs) || langs.length === 0) { return false; }
+				if($.inArray(i,langs) == -1) {
+					if(!!langs[i]) { i = langs[i]; }
+					else { return false; }
+				}
+				if(i == this.data.languages.current_language) { return true; }
+				st = $.vakata.css.get_css(selector + "." + this.data.languages.current_language, false, this.data.languages.language_css);
+				if(st !== false) { st.style.display = "none"; }
+				st = $.vakata.css.get_css(selector + "." + i, false, this.data.languages.language_css);
+				if(st !== false) { st.style.display = ""; }
+				this.data.languages.current_language = i;
+				this.__callback(i);
+				return true;
+			},
+			get_lang : function () {
+				return this.data.languages.current_language;
+			},
+			_get_string : function (key, lang) {
+				var langs = this._get_settings().languages,
+					s = this._get_settings().core.strings;
+				if($.isArray(langs) && langs.length) {
+					lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;
+				}
+				if(s[lang] && s[lang][key]) { return s[lang][key]; }
+				if(s[key]) { return s[key]; }
+				return key;
+			},
+			get_text : function (obj, lang) {
+				obj = this._get_node(obj) || this.data.ui.last_selected;
+				if(!obj.size()) { return false; }
+				var langs = this._get_settings().languages,
+					s = this._get_settings().core.html_titles;
+				if($.isArray(langs) && langs.length) {
+					lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;
+					obj = obj.children("a." + lang);
+				}
+				else { obj = obj.children("a:eq(0)"); }
+				if(s) {
+					obj = obj.clone();
+					obj.children("INS").remove();
+					return obj.html();
+				}
+				else {
+					obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];
+					return obj.nodeValue;
+				}
+			},
+			set_text : function (obj, val, lang) {
+				obj = this._get_node(obj) || this.data.ui.last_selected;
+				if(!obj.size()) { return false; }
+				var langs = this._get_settings().languages,
+					s = this._get_settings().core.html_titles,
+					tmp;
+				if($.isArray(langs) && langs.length) {
+					lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language;
+					obj = obj.children("a." + lang);
+				}
+				else { obj = obj.children("a:eq(0)"); }
+				if(s) {
+					tmp = obj.children("INS").clone();
+					obj.html(val).prepend(tmp);
+					this.__callback({ "obj" : obj, "name" : val, "lang" : lang });
+					return true;
+				}
+				else {
+					obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];
+					this.__callback({ "obj" : obj, "name" : val, "lang" : lang });
+					return (obj.nodeValue = val);
+				}
+			},
+			_load_css : function () {
+				var langs = this._get_settings().languages,
+					str = "/* languages css */",
+					selector = ".jstree-" + this.get_index() + ' a',
+					ln;
+				if($.isArray(langs) && langs.length) {
+					this.data.languages.current_language = langs[0];
+					for(ln = 0; ln < langs.length; ln++) {
+						str += selector + "." + langs[ln] + " {";
+						if(langs[ln] != this.data.languages.current_language) { str += " display:none; "; }
+						str += " } ";
+					}
+					this.data.languages.language_css = $.vakata.css.add_sheet({ 'str' : str, 'title' : "jstree-languages" });
+				}
+			},
+			create_node : function (obj, position, js, callback) {
+				var t = this.__call_old(true, obj, position, js, function (t) {
+					var langs = this._get_settings().languages,
+						a = t.children("a"),
+						ln;
+					if($.isArray(langs) && langs.length) {
+						for(ln = 0; ln < langs.length; ln++) {
+							if(!a.is("." + langs[ln])) {
+								t.append(a.eq(0).clone().removeClass(langs.join(" ")).addClass(langs[ln]));
+							}
+						}
+						a.not("." + langs.join(", .")).remove();
+					}
+					if(callback) { callback.call(this, t); }
+				});
+				return t;
+			}
+		}
+	});
+})(jQuery);
+//*/
+
+/*
+ * jsTree cookies plugin
+ * Stores the currently opened/selected nodes in a cookie and then restores them
+ * Depends on the jquery.cookie plugin
+ */
+(function ($) {
+	$.jstree.plugin("cookies", {
+		__init : function () {
+			if(typeof $.cookie === "undefined") { throw "jsTree cookie: jQuery cookie plugin not included."; }
+
+			var s = this._get_settings().cookies,
+				tmp;
+			if(!!s.save_loaded) {
+				tmp = $.cookie(s.save_loaded);
+				if(tmp && tmp.length) { this.data.core.to_load = tmp.split(","); }
+			}
+			if(!!s.save_opened) {
+				tmp = $.cookie(s.save_opened);
+				if(tmp && tmp.length) { this.data.core.to_open = tmp.split(","); }
+			}
+			if(!!s.save_selected) {
+				tmp = $.cookie(s.save_selected);
+				if(tmp && tmp.length && this.data.ui) { this.data.ui.to_select = tmp.split(","); }
+			}
+			this.get_container()
+				.one( ( this.data.ui ? "reselect" : "reopen" ) + ".jstree", $.proxy(function () {
+					this.get_container()
+						.bind("open_node.jstree close_node.jstree select_node.jstree deselect_node.jstree", $.proxy(function (e) { 
+								if(this._get_settings().cookies.auto_save) { this.save_cookie((e.handleObj.namespace + e.handleObj.type).replace("jstree","")); }
+							}, this));
+				}, this));
+		},
+		defaults : {
+			save_loaded		: "jstree_load",
+			save_opened		: "jstree_open",
+			save_selected	: "jstree_select",
+			auto_save		: true,
+			cookie_options	: {}
+		},
+		_fn : {
+			save_cookie : function (c) {
+				if(this.data.core.refreshing) { return; }
+				var s = this._get_settings().cookies;
+				if(!c) { // if called manually and not by event
+					if(s.save_loaded) {
+						this.save_loaded();
+						$.cookie(s.save_loaded, this.data.core.to_load.join(","), s.cookie_options);
+					}
+					if(s.save_opened) {
+						this.save_opened();
+						$.cookie(s.save_opened, this.data.core.to_open.join(","), s.cookie_options);
+					}
+					if(s.save_selected && this.data.ui) {
+						this.save_selected();
+						$.cookie(s.save_selected, this.data.ui.to_select.join(","), s.cookie_options);
+					}
+					return;
+				}
+				switch(c) {
+					case "open_node":
+					case "close_node":
+						if(!!s.save_opened) { 
+							this.save_opened(); 
+							$.cookie(s.save_opened, this.data.core.to_open.join(","), s.cookie_options); 
+						}
+						if(!!s.save_loaded) { 
+							this.save_loaded(); 
+							$.cookie(s.save_loaded, this.data.core.to_load.join(","), s.cookie_options); 
+						}
+						break;
+					case "select_node":
+					case "deselect_node":
+						if(!!s.save_selected && this.data.ui) { 
+							this.save_selected(); 
+							$.cookie(s.save_selected, this.data.ui.to_select.join(","), s.cookie_options); 
+						}
+						break;
+				}
+			}
+		}
+	});
+	// include cookies by default
+	// $.jstree.defaults.plugins.push("cookies");
+})(jQuery);
+//*/
+
+/*
+ * jsTree sort plugin
+ * Sorts items alphabetically (or using any other function)
+ */
+(function ($) {
+	$.jstree.plugin("sort", {
+		__init : function () {
+			this.get_container()
+				.bind("load_node.jstree", $.proxy(function (e, data) {
+						var obj = this._get_node(data.rslt.obj);
+						obj = obj === -1 ? this.get_container().children("ul") : obj.children("ul");
+						this.sort(obj);
+					}, this))
+				.bind("rename_node.jstree create_node.jstree create.jstree", $.proxy(function (e, data) {
+						this.sort(data.rslt.obj.parent());
+					}, this))
+				.bind("move_node.jstree", $.proxy(function (e, data) {
+						var m = data.rslt.np == -1 ? this.get_container() : data.rslt.np;
+						this.sort(m.children("ul"));
+					}, this));
+		},
+		defaults : function (a, b) { return this.get_text(a) > this.get_text(b) ? 1 : -1; },
+		_fn : {
+			sort : function (obj) {
+				var s = this._get_settings().sort,
+					t = this;
+				obj.append($.makeArray(obj.children("li")).sort($.proxy(s, t)));
+				obj.find("> li > ul").each(function() { t.sort($(this)); });
+				this.clean_node(obj);
+			}
+		}
+	});
+})(jQuery);
+//*/
+
+/*
+ * jsTree DND plugin
+ * Drag and drop plugin for moving/copying nodes
+ */
+(function ($) {
+	var o = false,
+		r = false,
+		m = false,
+		ml = false,
+		sli = false,
+		sti = false,
+		dir1 = false,
+		dir2 = false,
+		last_pos = false;
+	$.vakata.dnd = {
+		is_down : false,
+		is_drag : false,
+		helper : false,
+		scroll_spd : 10,
+		init_x : 0,
+		init_y : 0,
+		threshold : 5,
+		helper_left : 5,
+		helper_top : 10,
+		user_data : {},
+
+		drag_start : function (e, data, html) { 
+			if($.vakata.dnd.is_drag) { $.vakata.drag_stop({}); }
+			try {
+				e.currentTarget.unselectable = "on";
+				e.currentTarget.onselectstart = function() { return false; };
+				if(e.currentTarget.style) { e.currentTarget.style.MozUserSelect = "none"; }
+			} catch(err) { }
+			$.vakata.dnd.init_x = e.pageX;
+			$.vakata.dnd.init_y = e.pageY;
+			$.vakata.dnd.user_data = data;
+			$.vakata.dnd.is_down = true;
+			$.vakata.dnd.helper = $("<div id='vakata-dragged' />").html(html); //.fadeTo(10,0.25);
+			$(document).bind("mousemove", $.vakata.dnd.drag);
+			$(document).bind("mouseup", $.vakata.dnd.drag_stop);
+			return false;
+		},
+		drag : function (e) { 
+			if(!$.vakata.dnd.is_down) { return; }
+			if(!$.vakata.dnd.is_drag) {
+				if(Math.abs(e.pageX - $.vakata.dnd.init_x) > 5 || Math.abs(e.pageY - $.vakata.dnd.init_y) > 5) { 
+					$.vakata.dnd.helper.appendTo("body");
+					$.vakata.dnd.is_drag = true;
+					$(document).triggerHandler("drag_start.vakata", { "event" : e, "data" : $.vakata.dnd.user_data });
+				}
+				else { return; }
+			}
+
+			// maybe use a scrolling parent element instead of document?
+			if(e.type === "mousemove") { // thought of adding scroll in order to move the helper, but mouse poisition is n/a
+				var d = $(document), t = d.scrollTop(), l = d.scrollLeft();
+				if(e.pageY - t < 20) { 
+					if(sti && dir1 === "down") { clearInterval(sti); sti = false; }
+					if(!sti) { dir1 = "up"; sti = setInterval(function () { $(document).scrollTop($(document).scrollTop() - $.vakata.dnd.scroll_spd); }, 150); }
+				}
+				else { 
+					if(sti && dir1 === "up") { clearInterval(sti); sti = false; }
+				}
+				if($(window).height() - (e.pageY - t) < 20) {
+					if(sti && dir1 === "up") { clearInterval(sti); sti = false; }
+					if(!sti) { dir1 = "down"; sti = setInterval(function () { $(document).scrollTop($(document).scrollTop() + $.vakata.dnd.scroll_spd); }, 150); }
+				}
+				else { 
+					if(sti && dir1 === "down") { clearInterval(sti); sti = false; }
+				}
+
+				if(e.pageX - l < 20) {
+					if(sli && dir2 === "right") { clearInterval(sli); sli = false; }
+					if(!sli) { dir2 = "left"; sli = setInterval(function () { $(document).scrollLeft($(document).scrollLeft() - $.vakata.dnd.scroll_spd); }, 150); }
+				}
+				else { 
+					if(sli && dir2 === "left") { clearInterval(sli); sli = false; }
+				}
+				if($(window).width() - (e.pageX - l) < 20) {
+					if(sli && dir2 === "left") { clearInterval(sli); sli = false; }
+					if(!sli) { dir2 = "right"; sli = setInterval(function () { $(document).scrollLeft($(document).scrollLeft() + $.vakata.dnd.scroll_spd); }, 150); }
+				}
+				else { 
+					if(sli && dir2 === "right") { clearInterval(sli); sli = false; }
+				}
+			}
+
+			$.vakata.dnd.helper.css({ left : (e.pageX + $.vakata.dnd.helper_left) + "px", top : (e.pageY + $.vakata.dnd.helper_top) + "px" });
+			$(document).triggerHandler("drag.vakata", { "event" : e, "data" : $.vakata.dnd.user_data });
+		},
+		drag_stop : function (e) {
+			if(sli) { clearInterval(sli); }
+			if(sti) { clearInterval(sti); }
+			$(document).unbind("mousemove", $.vakata.dnd.drag);
+			$(document).unbind("mouseup", $.vakata.dnd.drag_stop);
+			$(document).triggerHandler("drag_stop.vakata", { "event" : e, "data" : $.vakata.dnd.user_data });
+			$.vakata.dnd.helper.remove();
+			$.vakata.dnd.init_x = 0;
+			$.vakata.dnd.init_y = 0;
+			$.vakata.dnd.user_data = {};
+			$.vakata.dnd.is_down = false;
+			$.vakata.dnd.is_drag = false;
+		}
+	};
+	$(function() {
+		var css_string = '#vakata-dragged { display:block; margin:0 0 0 0; padding:4px 4px 4px 24px; position:absolute; top:-2000px; line-height:16px; z-index:10000; } ';
+		$.vakata.css.add_sheet({ str : css_string, title : "vakata" });
+	});
+
+	$.jstree.plugin("dnd", {
+		__init : function () {
+			this.data.dnd = {
+				active : false,
+				after : false,
+				inside : false,
+				before : false,
+				off : false,
+				prepared : false,
+				w : 0,
+				to1 : false,
+				to2 : false,
+				cof : false,
+				cw : false,
+				ch : false,
+				i1 : false,
+				i2 : false,
+				mto : false
+			};
+			this.get_container()
+				.bind("mouseenter.jstree", $.proxy(function (e) {
+						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
+							if(this.data.themes) {
+								m.attr("class", "jstree-" + this.data.themes.theme); 
+								if(ml) { ml.attr("class", "jstree-" + this.data.themes.theme); }
+								$.vakata.dnd.helper.attr("class", "jstree-dnd-helper jstree-" + this.data.themes.theme);
+							}
+							//if($(e.currentTarget).find("> ul > li").length === 0) {
+							if(e.currentTarget === e.target && $.vakata.dnd.user_data.obj && $($.vakata.dnd.user_data.obj).length && $($.vakata.dnd.user_data.obj).parents(".jstree:eq(0)")[0] !== e.target) { // node should not be from the same tree
+								var tr = $.jstree._reference(e.target), dc;
+								if(tr.data.dnd.foreign) {
+									dc = tr._get_settings().dnd.drag_check.call(this, { "o" : o, "r" : tr.get_container(), is_root : true });
+									if(dc === true || dc.inside === true || dc.before === true || dc.after === true) {
+										$.vakata.dnd.helper.children("ins").attr("class","jstree-ok");
+									}
+								}
+								else {
+									tr.prepare_move(o, tr.get_container(), "last");
+									if(tr.check_move()) {
+										$.vakata.dnd.helper.children("ins").attr("class","jstree-ok");
+									}
+								}
+							}
+						}
+					}, this))
+				.bind("mouseup.jstree", $.proxy(function (e) {
+						//if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && $(e.currentTarget).find("> ul > li").length === 0) {
+						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && e.currentTarget === e.target && $.vakata.dnd.user_data.obj && $($.vakata.dnd.user_data.obj).length && $($.vakata.dnd.user_data.obj).parents(".jstree:eq(0)")[0] !== e.target) { // node should not be from the same tree
+							var tr = $.jstree._reference(e.currentTarget), dc;
+							if(tr.data.dnd.foreign) {
+								dc = tr._get_settings().dnd.drag_check.call(this, { "o" : o, "r" : tr.get_container(), is_root : true });
+								if(dc === true || dc.inside === true || dc.before === true || dc.after === true) {
+									tr._get_settings().dnd.drag_finish.call(this, { "o" : o, "r" : tr.get_container(), is_root : true });
+								}
+							}
+							else {
+								tr.move_node(o, tr.get_container(), "last", e[tr._get_settings().dnd.copy_modifier + "Key"]);
+							}
+						}
+					}, this))
+				.bind("mouseleave.jstree", $.proxy(function (e) {
+						if(e.relatedTarget && e.relatedTarget.id && e.relatedTarget.id === "jstree-marker-line") {
+							return false; 
+						}
+						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
+							if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }
+							if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }
+							if(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); }
+							if(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); }
+							if($.vakata.dnd.helper.children("ins").hasClass("jstree-ok")) {
+								$.vakata.dnd.helper.children("ins").attr("class","jstree-invalid");
+							}
+						}
+					}, this))
+				.bind("mousemove.jstree", $.proxy(function (e) {
+						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
+							var cnt = this.get_container()[0];
+
+							// Horizontal scroll
+							if(e.pageX + 24 > this.data.dnd.cof.left + this.data.dnd.cw) {
+								if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }
+								this.data.dnd.i1 = setInterval($.proxy(function () { this.scrollLeft += $.vakata.dnd.scroll_spd; }, cnt), 100);
+							}
+							else if(e.pageX - 24 < this.data.dnd.cof.left) {
+								if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }
+								this.data.dnd.i1 = setInterval($.proxy(function () { this.scrollLeft -= $.vakata.dnd.scroll_spd; }, cnt), 100);
+							}
+							else {
+								if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }
+							}
+
+							// Vertical scroll
+							if(e.pageY + 24 > this.data.dnd.cof.top + this.data.dnd.ch) {
+								if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }
+								this.data.dnd.i2 = setInterval($.proxy(function () { this.scrollTop += $.vakata.dnd.scroll_spd; }, cnt), 100);
+							}
+							else if(e.pageY - 24 < this.data.dnd.cof.top) {
+								if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }
+								this.data.dnd.i2 = setInterval($.proxy(function () { this.scrollTop -= $.vakata.dnd.scroll_spd; }, cnt), 100);
+							}
+							else {
+								if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }
+							}
+
+						}
+					}, this))
+				.bind("scroll.jstree", $.proxy(function (e) { 
+						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && m && ml) {
+							m.hide();
+							ml.hide();
+						}
+					}, this))
+				.delegate("a", "mousedown.jstree", $.proxy(function (e) { 
+						if(e.which === 1) {
+							this.start_drag(e.currentTarget, e);
+							return false;
+						}
+					}, this))
+				.delegate("a", "mouseenter.jstree", $.proxy(function (e) { 
+						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
+							this.dnd_enter(e.currentTarget);
+						}
+					}, this))
+				.delegate("a", "mousemove.jstree", $.proxy(function (e) { 
+						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
+							if(!r || !r.length || r.children("a")[0] !== e.currentTarget) {
+								this.dnd_enter(e.currentTarget);
+							}
+							if(typeof this.data.dnd.off.top === "undefined") { this.data.dnd.off = $(e.target).offset(); }
+							this.data.dnd.w = (e.pageY - (this.data.dnd.off.top || 0)) % this.data.core.li_height;
+							if(this.data.dnd.w < 0) { this.data.dnd.w += this.data.core.li_height; }
+							this.dnd_show();
+						}
+					}, this))
+				.delegate("a", "mouseleave.jstree", $.proxy(function (e) { 
+						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
+							if(e.relatedTarget && e.relatedTarget.id && e.relatedTarget.id === "jstree-marker-line") {
+								return false; 
+							}
+								if(m) { m.hide(); }
+								if(ml) { ml.hide(); }
+							/*
+							var ec = $(e.currentTarget).closest("li"), 
+								er = $(e.relatedTarget).closest("li");
+							if(er[0] !== ec.prev()[0] && er[0] !== ec.next()[0]) {
+								if(m) { m.hide(); }
+								if(ml) { ml.hide(); }
+							}
+							*/
+							this.data.dnd.mto = setTimeout( 
+								(function (t) { return function () { t.dnd_leave(e); }; })(this),
+							0);
+						}
+					}, this))
+				.delegate("a", "mouseup.jstree", $.proxy(function (e) { 
+						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) {
+							this.dnd_finish(e);
+						}
+					}, this));
+
+			$(document)
+				.bind("drag_stop.vakata", $.proxy(function () {
+						if(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); }
+						if(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); }
+						if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); }
+						if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); }
+						this.data.dnd.after		= false;
+						this.data.dnd.before	= false;
+						this.data.dnd.inside	= false;
+						this.data.dnd.off		= false;
+						this.data.dnd.prepared	= false;
+						this.data.dnd.w			= false;
+						this.data.dnd.to1		= false;
+						this.data.dnd.to2		= false;
+						this.data.dnd.i1		= false;
+						this.data.dnd.i2		= false;
+						this.data.dnd.active	= false;
+						this.data.dnd.foreign	= false;
+						if(m) { m.css({ "top" : "-2000px" }); }
+						if(ml) { ml.css({ "top" : "-2000px" }); }
+					}, this))
+				.bind("drag_start.vakata", $.proxy(function (e, data) {
+						if(data.data.jstree) { 
+							var et = $(data.event.target);
+							if(et.closest(".jstree").hasClass("jstree-" + this.get_index())) {
+								this.dnd_enter(et);
+							}
+						}
+					}, this));
+				/*
+				.bind("keydown.jstree-" + this.get_index() + " keyup.jstree-" + this.get_index(), $.proxy(function(e) {
+						if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && !this.data.dnd.foreign) {
+							var h = $.vakata.dnd.helper.children("ins");
+							if(e[this._get_settings().dnd.copy_modifier + "Key"] && h.hasClass("jstree-ok")) {
+								h.parent().html(h.parent().html().replace(/ \(Copy\)$/, "") + " (Copy)");
+							} 
+							else {
+								h.parent().html(h.parent().html().replace(/ \(Copy\)$/, ""));
+							}
+						}
+					}, this)); */
+
+
+
+			var s = this._get_settings().dnd;
+			if(s.drag_target) {
+				$(document)
+					.delegate(s.drag_target, "mousedown.jstree-" + this.get_index(), $.proxy(function (e) {
+						o = e.target;
+						$.vakata.dnd.drag_start(e, { jstree : true, obj : e.target }, "<ins class='jstree-icon'></ins>" + $(e.target).text() );
+						if(this.data.themes) { 
+							if(m) { m.attr("class", "jstree-" + this.data.themes.theme); }
+							if(ml) { ml.attr("class", "jstree-" + this.data.themes.theme); }
+							$.vakata.dnd.helper.attr("class", "jstree-dnd-helper jstree-" + this.data.themes.theme); 
+						}
+						$.vakata.dnd.helper.children("ins").attr("class","jstree-invalid");
+						var cnt = this.get_container();
+						this.data.dnd.cof = cnt.offset();
+						this.data.dnd.cw = parseInt(cnt.width(),10);
+						this.data.dnd.ch = parseInt(cnt.height(),10);
+						this.data.dnd.foreign = true;
+						e.preventDefault();
+					}, this));
+			}
+			if(s.drop_target) {
+				$(document)
+					.delegate(s.drop_target, "mouseenter.jstree-" + this.get_index(), $.proxy(function (e) {
+							if(this.data.dnd.active && this._get_settings().dnd.drop_check.call(this, { "o" : o, "r" : $(e.target), "e" : e })) {
+								$.vakata.dnd.helper.children("ins").attr("class","jstree-ok");
+							}
+						}, this))
+					.delegate(s.drop_target, "mouseleave.jstree-" + this.get_index(), $.proxy(function (e) {
+							if(this.data.dnd.active) {
+								$.vakata.dnd.helper.children("ins").attr("class","jstree-invalid");
+							}
+						}, this))
+					.delegate(s.drop_target, "mouseup.jstree-" + this.get_index(), $.proxy(function (e) {
+							if(this.data.dnd.active && $.vakata.dnd.helper.children("ins").hasClass("jstree-ok")) {
+								this._get_settings().dnd.drop_finish.call(this, { "o" : o, "r" : $(e.target), "e" : e });
+							}
+						}, this));
+			}
+		},
+		defaults : {
+			copy_modifier	: "ctrl",
+			check_timeout	: 100,
+			open_timeout	: 500,
+			drop_target		: ".jstree-drop",
+			drop_check		: function (data) { return true; },
+			drop_finish		: $.noop,
+			drag_target		: ".jstree-draggable",
+			drag_finish		: $.noop,
+			drag_check		: function (data) { return { after : false, before : false, inside : true }; }
+		},
+		_fn : {
+			dnd_prepare : function () {
+				if(!r || !r.length) { return; }
+				this.data.dnd.off = r.offset();
+				if(this._get_settings().core.rtl) {
+					this.data.dnd.off.right = this.data.dnd.off.left + r.width();
+				}
+				if(this.data.dnd.foreign) {
+					var a = this._get_settings().dnd.drag_check.call(this, { "o" : o, "r" : r });
+					this.data.dnd.after = a.after;
+					this.data.dnd.before = a.before;
+					this.data.dnd.inside = a.inside;
+					this.data.dnd.prepared = true;
+					return this.dnd_show();
+				}
+				this.prepare_move(o, r, "before");
+				this.data.dnd.before = this.check_move();
+				this.prepare_move(o, r, "after");
+				this.data.dnd.after = this.check_move();
+				if(this._is_loaded(r)) {
+					this.prepare_move(o, r, "inside");
+					this.data.dnd.inside = this.check_move();
+				}
+				else {
+					this.data.dnd.inside = false;
+				}
+				this.data.dnd.prepared = true;
+				return this.dnd_show();
+			},
+			dnd_show : function () {
+				if(!this.data.dnd.prepared) { return; }
+				var o = ["before","inside","after"],
+					r = false,
+					rtl = this._get_settings().core.rtl,
+					pos;
+				if(this.data.dnd.w < this.data.core.li_height/3) { o = ["before","inside","after"]; }
+				else if(this.data.dnd.w <= this.data.core.li_height*2/3) {
+					o = this.data.dnd.w < this.data.core.li_height/2 ? ["inside","before","after"] : ["inside","after","before"];
+				}
+				else { o = ["after","inside","before"]; }
+				$.each(o, $.proxy(function (i, val) { 
+					if(this.data.dnd[val]) {
+						$.vakata.dnd.helper.children("ins").attr("class","jstree-ok");
+						r = val;
+						return false;
+					}
+				}, this));
+				if(r === false) { $.vakata.dnd.helper.children("ins").attr("class","jstree-invalid"); }
+				
+				pos = rtl ? (this.data.dnd.off.right - 18) : (this.data.dnd.off.left + 10);
+				switch(r) {
+					case "before":
+						m.css({ "left" : pos + "px", "top" : (this.data.dnd.off.top - 6) + "px" }).show();
+						if(ml) { ml.css({ "left" : (pos + 8) + "px", "top" : (this.data.dnd.off.top - 1) + "px" }).show(); }
+						break;
+					case "after":
+						m.css({ "left" : pos + "px", "top" : (this.data.dnd.off.top + this.data.core.li_height - 6) + "px" }).show();
+						if(ml) { ml.css({ "left" : (pos + 8) + "px", "top" : (this.data.dnd.off.top + this.data.core.li_height - 1) + "px" }).show(); }
+						break;
+					case "inside":
+						m.css({ "left" : pos + ( rtl ? -4 : 4) + "px", "top" : (this.data.dnd.off.top + this.data.core.li_height/2 - 5) + "px" }).show();
+						if(ml) { ml.hide(); }
+						break;
+					default:
+						m.hide();
+						if(ml) { ml.hide(); }
+						break;
+				}
+				last_pos = r;
+				return r;
+			},
+			dnd_open : function () {
+				this.data.dnd.to2 = false;
+				this.open_node(r, $.proxy(this.dnd_prepare,this), true);
+			},
+			dnd_finish : function (e) {
+				if(this.data.dnd.foreign) {
+					if(this.data.dnd.after || this.data.dnd.before || this.data.dnd.inside) {
+						this._get_settings().dnd.drag_finish.call(this, { "o" : o, "r" : r, "p" : last_pos });
+					}
+				}
+				else {
+					this.dnd_prepare();
+					this.move_node(o, r, last_pos, e[this._get_settings().dnd.copy_modifier + "Key"]);
+				}
+				o = false;
+				r = false;
+				m.hide();
+				if(ml) { ml.hide(); }
+			},
+			dnd_enter : function (obj) {
+				if(this.data.dnd.mto) { 
+					clearTimeout(this.data.dnd.mto);
+					this.data.dnd.mto = false;
+				}
+				var s = this._get_settings().dnd;
+				this.data.dnd.prepared = false;
+				r = this._get_node(obj);
+				if(s.check_timeout) { 
+					// do the calculations after a minimal timeout (users tend to drag quickly to the desired location)
+					if(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); }
+					this.data.dnd.to1 = setTimeout($.proxy(this.dnd_prepare, this), s.check_timeout); 
+				}
+				else { 
+					this.dnd_prepare(); 
+				}
+				if(s.open_timeout) { 
+					if(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); }
+					if(r && r.length && r.hasClass("jstree-closed")) { 
+						// if the node is closed - open it, then recalculate
+						this.data.dnd.to2 = setTimeout($.proxy(this.dnd_open, this), s.open_timeout);
+					}
+				}
+				else {
+					if(r && r.length && r.hasClass("jstree-closed")) { 
+						this.dnd_open();
+					}
+				}
+			},
+			dnd_leave : function (e) {
+				this.data.dnd.after		= false;
+				this.data.dnd.before	= false;
+				this.data.dnd.inside	= false;
+				$.vakata.dnd.helper.children("ins").attr("class","jstree-invalid");
+				m.hide();
+				if(ml) { ml.hide(); }
+				if(r && r[0] === e.target.parentNode) {
+					if(this.data.dnd.to1) {
+						clearTimeout(this.data.dnd.to1);
+						this.data.dnd.to1 = false;
+					}
+					if(this.data.dnd.to2) {
+						clearTimeout(this.data.dnd.to2);
+						this.data.dnd.to2 = false;
+					}
+				}
+			},
+			start_drag : function (obj, e) {
+				o = this._get_node(obj);
+				if(this.data.ui && this.is_selected(o)) { o = this._get_node(null, true); }
+				var dt = o.length > 1 ? this._get_string("multiple_selection") : this.get_text(o),
+					cnt = this.get_container();
+				if(!this._get_settings().core.html_titles) { dt = dt.replace(/</ig,"&lt;").replace(/>/ig,"&gt;"); }
+				$.vakata.dnd.drag_start(e, { jstree : true, obj : o }, "<ins class='jstree-icon'></ins>" + dt );
+				if(this.data.themes) { 
+					if(m) { m.attr("class", "jstree-" + this.data.themes.theme); }
+					if(ml) { ml.attr("class", "jstree-" + this.data.themes.theme); }
+					$.vakata.dnd.helper.attr("class", "jstree-dnd-helper jstree-" + this.data.themes.theme); 
+				}
+				this.data.dnd.cof = cnt.offset();
+				this.data.dnd.cw = parseInt(cnt.width(),10);
+				this.data.dnd.ch = parseInt(cnt.height(),10);
+				this.data.dnd.active = true;
+			}
+		}
+	});
+	$(function() {
+		var css_string = '' + 
+			'#vakata-dragged ins { display:block; text-decoration:none; width:16px; height:16px; margin:0 0 0 0; padding:0; position:absolute; top:4px; left:4px; ' + 
+			' -moz-border-radius:4px; border-radius:4px; -webkit-border-radius:4px; ' +
+			'} ' + 
+			'#vakata-dragged .jstree-ok { background:green; } ' + 
+			'#vakata-dragged .jstree-invalid { background:red; } ' + 
+			'#jstree-marker { padding:0; margin:0; font-size:12px; overflow:hidden; height:12px; width:8px; position:absolute; top:-30px; z-index:10001; background-repeat:no-repeat; display:none; background-color:transparent; text-shadow:1px 1px 1px white; color:black; line-height:10px; } ' + 
+			'#jstree-marker-line { padding:0; margin:0; line-height:0%; font-size:1px; overflow:hidden; height:1px; width:100px; position:absolute; top:-30px; z-index:10000; background-repeat:no-repeat; display:none; background-color:#456c43; ' + 
+			' cursor:pointer; border:1px solid #eeeeee; border-left:0; -moz-box-shadow: 0px 0px 2px #666; -webkit-box-shadow: 0px 0px 2px #666; box-shadow: 0px 0px 2px #666; ' + 
+			' -moz-border-radius:1px; border-radius:1px; -webkit-border-radius:1px; ' +
+			'}' + 
+			'';
+		$.vakata.css.add_sheet({ str : css_string, title : "jstree" });
+		m = $("<div />").attr({ id : "jstree-marker" }).hide().html("&raquo;")
+			.bind("mouseleave mouseenter", function (e) { 
+				m.hide();
+				ml.hide();
+				e.preventDefault(); 
+				e.stopImmediatePropagation(); 
+				return false; 
+			})
+			.appendTo("body");
+		ml = $("<div />").attr({ id : "jstree-marker-line" }).hide()
+			.bind("mouseup", function (e) { 
+				if(r && r.length) { 
+					r.children("a").trigger(e); 
+					e.preventDefault(); 
+					e.stopImmediatePropagation(); 
+					return false; 
+				} 
+			})
+			.bind("mouseleave", function (e) { 
+				var rt = $(e.relatedTarget);
+				if(rt.is(".jstree") || rt.closest(".jstree").length === 0) {
+					if(r && r.length) { 
+						r.children("a").trigger(e); 
+						m.hide();
+						ml.hide();
+						e.preventDefault(); 
+						e.stopImmediatePropagation(); 
+						return false; 
+					}
+				}
+			})
+			.appendTo("body");
+		$(document).bind("drag_start.vakata", function (e, data) {
+			if(data.data.jstree) { m.show(); if(ml) { ml.show(); } }
+		});
+		$(document).bind("drag_stop.vakata", function (e, data) {
+			if(data.data.jstree) { m.hide(); if(ml) { ml.hide(); } }
+		});
+	});
+})(jQuery);
+//*/
+
+/*
+ * jsTree checkbox plugin
+ * Inserts checkboxes in front of every node
+ * Depends on the ui plugin
+ * DOES NOT WORK NICELY WITH MULTITREE DRAG'N'DROP
+ */
+(function ($) {
+	$.jstree.plugin("checkbox", {
+		__init : function () {
+			this.data.checkbox.noui = this._get_settings().checkbox.override_ui;
+			if(this.data.ui && this.data.checkbox.noui) {
+				this.select_node = this.deselect_node = this.deselect_all = $.noop;
+				this.get_selected = this.get_checked;
+			}
+
+			this.get_container()
+				.bind("open_node.jstree create_node.jstree clean_node.jstree refresh.jstree", $.proxy(function (e, data) { 
+						this._prepare_checkboxes(data.rslt.obj);
+					}, this))
+				.bind("loaded.jstree", $.proxy(function (e) {
+						this._prepare_checkboxes();
+					}, this))
+				.delegate( (this.data.ui && this.data.checkbox.noui ? "a" : "ins.jstree-checkbox") , "click.jstree", $.proxy(function (e) {
+						e.preventDefault();
+						if(this._get_node(e.target).hasClass("jstree-checked")) { this.uncheck_node(e.target); }
+						else { this.check_node(e.target); }
+						if(this.data.ui && this.data.checkbox.noui) {
+							this.save_selected();
+							if(this.data.cookies) { this.save_cookie("select_node"); }
+						}
+						else {
+							e.stopImmediatePropagation();
+							return false;
+						}
+					}, this));
+		},
+		defaults : {
+			override_ui : false,
+			two_state : false,
+			real_checkboxes : false,
+			checked_parent_open : true,
+			real_checkboxes_names : function (n) { return [ ("check_" + (n[0].id || Math.ceil(Math.random() * 10000))) , 1]; }
+		},
+		__destroy : function () {
+			this.get_container()
+				.find("input.jstree-real-checkbox").removeClass("jstree-real-checkbox").end()
+				.find("ins.jstree-checkbox").remove();
+		},
+		_fn : {
+			_checkbox_notify : function (n, data) {
+				if(data.checked) {
+					this.check_node(n, false);
+				}
+			},
+			_prepare_checkboxes : function (obj) {
+				obj = !obj || obj == -1 ? this.get_container().find("> ul > li") : this._get_node(obj);
+				if(obj === false) { return; } // added for removing root nodes
+				var c, _this = this, t, ts = this._get_settings().checkbox.two_state, rc = this._get_settings().checkbox.real_checkboxes, rcn = this._get_settings().checkbox.real_checkboxes_names;
+				obj.each(function () {
+					t = $(this);
+					c = t.is("li") && (t.hasClass("jstree-checked") || (rc && t.children(":checked").length)) ? "jstree-checked" : "jstree-unchecked";
+					t.find("li").andSelf().each(function () {
+						var $t = $(this), nm;
+						$t.children("a" + (_this.data.languages ? "" : ":eq(0)") ).not(":has(.jstree-checkbox)").prepend("<ins class='jstree-checkbox'>&#160;</ins>").parent().not(".jstree-checked, .jstree-unchecked").addClass( ts ? "jstree-unchecked" : c );
+						if(rc) {
+							if(!$t.children(":checkbox").length) {
+								nm = rcn.call(_this, $t);
+								$t.prepend("<input type='checkbox' class='jstree-real-checkbox' id='" + nm[0] + "' name='" + nm[0] + "' value='" + nm[1] + "' />");
+							}
+							else {
+								$t.children(":checkbox").addClass("jstree-real-checkbox");
+							}
+						}
+						if(!ts) {
+							if(c === "jstree-checked" || $t.hasClass("jstree-checked") || $t.children(':checked').length) {
+								$t.find("li").andSelf().addClass("jstree-checked").children(":checkbox").prop("checked", true);
+							}
+						}
+						else {
+							if($t.hasClass("jstree-checked") || $t.children(':checked').length) {
+								$t.addClass("jstree-checked").children(":checkbox").prop("checked", true);
+							}
+						}
+					});
+				});
+				if(!ts) {
+					obj.find(".jstree-checked").parent().parent().each(function () { _this._repair_state(this); }); 
+				}
+			},
+			change_state : function (obj, state) {
+				obj = this._get_node(obj);
+				var coll = false, rc = this._get_settings().checkbox.real_checkboxes;
+				if(!obj || obj === -1) { return false; }
+				state = (state === false || state === true) ? state : obj.hasClass("jstree-checked");
+				if(this._get_settings().checkbox.two_state) {
+					if(state) { 
+						obj.removeClass("jstree-checked").addClass("jstree-unchecked"); 
+						if(rc) { obj.children(":checkbox").prop("checked", false); }
+					}
+					else { 
+						obj.removeClass("jstree-unchecked").addClass("jstree-checked"); 
+						if(rc) { obj.children(":checkbox").prop("checked", true); }
+					}
+				}
+				else {
+					if(state) { 
+						coll = obj.find("li").andSelf();
+						if(!coll.filter(".jstree-checked, .jstree-undetermined").length) { return false; }
+						coll.removeClass("jstree-checked jstree-undetermined").addClass("jstree-unchecked"); 
+						if(rc) { coll.children(":checkbox").prop("checked", false); }
+					}
+					else { 
+						coll = obj.find("li").andSelf();
+						if(!coll.filter(".jstree-unchecked, .jstree-undetermined").length) { return false; }
+						coll.removeClass("jstree-unchecked jstree-undetermined").addClass("jstree-checked"); 
+						if(rc) { coll.children(":checkbox").prop("checked", true); }
+						if(this.data.ui) { this.data.ui.last_selected = obj; }
+						this.data.checkbox.last_selected = obj;
+					}
+					obj.parentsUntil(".jstree", "li").each(function () {
+						var $this = $(this);
+						if(state) {
+							if($this.children("ul").children("li.jstree-checked, li.jstree-undetermined").length) {
+								$this.parentsUntil(".jstree", "li").andSelf().removeClass("jstree-checked jstree-unchecked").addClass("jstree-undetermined");
+								if(rc) { $this.parentsUntil(".jstree", "li").andSelf().children(":checkbox").prop("checked", false); }
+								return false;
+							}
+							else {
+								$this.removeClass("jstree-checked jstree-undetermined").addClass("jstree-unchecked");
+								if(rc) { $this.children(":checkbox").prop("checked", false); }
+							}
+						}
+						else {
+							if($this.children("ul").children("li.jstree-unchecked, li.jstree-undetermined").length) {
+								$this.parentsUntil(".jstree", "li").andSelf().removeClass("jstree-checked jstree-unchecked").addClass("jstree-undetermined");
+								if(rc) { $this.parentsUntil(".jstree", "li").andSelf().children(":checkbox").prop("checked", false); }
+								return false;
+							}
+							else {
+								$this.removeClass("jstree-unchecked jstree-undetermined").addClass("jstree-checked");
+								if(rc) { $this.children(":checkbox").prop("checked", true); }
+							}
+						}
+					});
+				}
+				if(this.data.ui && this.data.checkbox.noui) { this.data.ui.selected = this.get_checked(); }
+				this.__callback(obj);
+				return true;
+			},
+			check_node : function (obj) {
+				if(this.change_state(obj, false)) { 
+					obj = this._get_node(obj);
+					if(this._get_settings().checkbox.checked_parent_open) {
+						var t = this;
+						obj.parents(".jstree-closed").each(function () { t.open_node(this, false, true); });
+					}
+					this.__callback({ "obj" : obj }); 
+				}
+			},
+			uncheck_node : function (obj) {
+				if(this.change_state(obj, true)) { this.__callback({ "obj" : this._get_node(obj) }); }
+			},
+			check_all : function () {
+				var _this = this, 
+					coll = this._get_settings().checkbox.two_state ? this.get_container_ul().find("li") : this.get_container_ul().children("li");
+				coll.each(function () {
+					_this.change_state(this, false);
+				});
+				this.__callback();
+			},
+			uncheck_all : function () {
+				var _this = this,
+					coll = this._get_settings().checkbox.two_state ? this.get_container_ul().find("li") : this.get_container_ul().children("li");
+				coll.each(function () {
+					_this.change_state(this, true);
+				});
+				this.__callback();
+			},
+
+			is_checked : function(obj) {
+				obj = this._get_node(obj);
+				return obj.length ? obj.is(".jstree-checked") : false;
+			},
+			get_checked : function (obj, get_all) {
+				obj = !obj || obj === -1 ? this.get_container() : this._get_node(obj);
+				return get_all || this._get_settings().checkbox.two_state ? obj.find(".jstree-checked") : obj.find("> ul > .jstree-checked, .jstree-undetermined > ul > .jstree-checked");
+			},
+			get_unchecked : function (obj, get_all) { 
+				obj = !obj || obj === -1 ? this.get_container() : this._get_node(obj);
+				return get_all || this._get_settings().checkbox.two_state ? obj.find(".jstree-unchecked") : obj.find("> ul > .jstree-unchecked, .jstree-undetermined > ul > .jstree-unchecked");
+			},
+
+			show_checkboxes : function () { this.get_container().children("ul").removeClass("jstree-no-checkboxes"); },
+			hide_checkboxes : function () { this.get_container().children("ul").addClass("jstree-no-checkboxes"); },
+
+			_repair_state : function (obj) {
+				obj = this._get_node(obj);
+				if(!obj.length) { return; }
+				if(this._get_settings().checkbox.two_state) {
+					obj.find('li').andSelf().not('.jstree-checked').removeClass('jstree-undetermined').addClass('jstree-unchecked').children(':checkbox').prop('checked', true);
+					return;
+				}
+				var rc = this._get_settings().checkbox.real_checkboxes,
+					a = obj.find("> ul > .jstree-checked").length,
+					b = obj.find("> ul > .jstree-undetermined").length,
+					c = obj.find("> ul > li").length;
+				if(c === 0) { if(obj.hasClass("jstree-undetermined")) { this.change_state(obj, false); } }
+				else if(a === 0 && b === 0) { this.change_state(obj, true); }
+				else if(a === c) { this.change_state(obj, false); }
+				else { 
+					obj.parentsUntil(".jstree","li").andSelf().removeClass("jstree-checked jstree-unchecked").addClass("jstree-undetermined");
+					if(rc) { obj.parentsUntil(".jstree", "li").andSelf().children(":checkbox").prop("checked", false); }
+				}
+			},
+			reselect : function () {
+				if(this.data.ui && this.data.checkbox.noui) { 
+					var _this = this,
+						s = this.data.ui.to_select;
+					s = $.map($.makeArray(s), function (n) { return "#" + n.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:"); });
+					this.deselect_all();
+					$.each(s, function (i, val) { _this.check_node(val); });
+					this.__callback();
+				}
+				else { 
+					this.__call_old(); 
+				}
+			},
+			save_loaded : function () {
+				var _this = this;
+				this.data.core.to_load = [];
+				this.get_container_ul().find("li.jstree-closed.jstree-undetermined").each(function () {
+					if(this.id) { _this.data.core.to_load.push("#" + this.id); }
+				});
+			}
+		}
+	});
+	$(function() {
+		var css_string = '.jstree .jstree-real-checkbox { display:none; } ';
+		$.vakata.css.add_sheet({ str : css_string, title : "jstree" });
+	});
+})(jQuery);
+//*/
+
+/* 
+ * jsTree XML plugin
+ * The XML data store. Datastores are build by overriding the `load_node` and `_is_loaded` functions.
+ */
+(function ($) {
+	$.vakata.xslt = function (xml, xsl, callback) {
+		var rs = "", xm, xs, processor, support;
+		// TODO: IE9 no XSLTProcessor, no document.recalc
+		if(document.recalc) {
+			xm = document.createElement('xml');
+			xs = document.createElement('xml');
+			xm.innerHTML = xml;
+			xs.innerHTML = xsl;
+			$("body").append(xm).append(xs);
+			setTimeout( (function (xm, xs, callback) {
+				return function () {
+					callback.call(null, xm.transformNode(xs.XMLDocument));
+					setTimeout( (function (xm, xs) { return function () { $(xm).remove(); $(xs).remove(); }; })(xm, xs), 200);
+				};
+			})(xm, xs, callback), 100);
+			return true;
+		}
+		if(typeof window.DOMParser !== "undefined" && typeof window.XMLHttpRequest !== "undefined" && typeof window.XSLTProcessor === "undefined") {
+			xml = new DOMParser().parseFromString(xml, "text/xml");
+			xsl = new DOMParser().parseFromString(xsl, "text/xml");
+			// alert(xml.transformNode());
+			// callback.call(null, new XMLSerializer().serializeToString(rs));
+			
+		}
+		if(typeof window.DOMParser !== "undefined" && typeof window.XMLHttpRequest !== "undefined" && typeof window.XSLTProcessor !== "undefined") {
+			processor = new XSLTProcessor();
+			support = $.isFunction(processor.transformDocument) ? (typeof window.XMLSerializer !== "undefined") : true;
+			if(!support) { return false; }
+			xml = new DOMParser().parseFromString(xml, "text/xml");
+			xsl = new DOMParser().parseFromString(xsl, "text/xml");
+			if($.isFunction(processor.transformDocument)) {
+				rs = document.implementation.createDocument("", "", null);
+				processor.transformDocument(xml, xsl, rs, null);
+				callback.call(null, new XMLSerializer().serializeToString(rs));
+				return true;
+			}
+			else {
+				processor.importStylesheet(xsl);
+				rs = processor.transformToFragment(xml, document);
+				callback.call(null, $("<div />").append(rs).html());
+				return true;
+			}
+		}
+		return false;
+	};
+	var xsl = {
+		'nest' : '<' + '?xml version="1.0" encoding="utf-8" ?>' + 
+			'<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >' + 
+			'<xsl:output method="html" encoding="utf-8" omit-xml-declaration="yes" standalone="no" indent="no" media-type="text/html" />' + 
+			'<xsl:template match="/">' + 
+			'	<xsl:call-template name="nodes">' + 
+			'		<xsl:with-param name="node" select="/root" />' + 
+			'	</xsl:call-template>' + 
+			'</xsl:template>' + 
+			'<xsl:template name="nodes">' + 
+			'	<xsl:param name="node" />' + 
+			'	<ul>' + 
+			'	<xsl:for-each select="$node/item">' + 
+			'		<xsl:variable name="children" select="count(./item) &gt; 0" />' + 
+			'		<li>' + 
+			'			<xsl:attribute name="class">' + 
+			'				<xsl:if test="position() = last()">jstree-last </xsl:if>' + 
+			'				<xsl:choose>' + 
+			'					<xsl:when test="@state = \'open\'">jstree-open </xsl:when>' + 
+			'					<xsl:when test="$children or @hasChildren or @state = \'closed\'">jstree-closed </xsl:when>' + 
+			'					<xsl:otherwise>jstree-leaf </xsl:otherwise>' + 
+			'				</xsl:choose>' + 
+			'				<xsl:value-of select="@class" />' + 
+			'			</xsl:attribute>' + 
+			'			<xsl:for-each select="@*">' + 
+			'				<xsl:if test="name() != \'class\' and name() != \'state\' and name() != \'hasChildren\'">' + 
+			'					<xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + 
+			'				</xsl:if>' + 
+			'			</xsl:for-each>' + 
+			'	<ins class="jstree-icon"><xsl:text>&#xa0;</xsl:text></ins>' + 
+			'			<xsl:for-each select="content/name">' + 
+			'				<a>' + 
+			'				<xsl:attribute name="href">' + 
+			'					<xsl:choose>' + 
+			'					<xsl:when test="@href"><xsl:value-of select="@href" /></xsl:when>' + 
+			'					<xsl:otherwise>#</xsl:otherwise>' + 
+			'					</xsl:choose>' + 
+			'				</xsl:attribute>' + 
+			'				<xsl:attribute name="class"><xsl:value-of select="@lang" /> <xsl:value-of select="@class" /></xsl:attribute>' + 
+			'				<xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute>' + 
+			'				<xsl:for-each select="@*">' + 
+			'					<xsl:if test="name() != \'style\' and name() != \'class\' and name() != \'href\'">' + 
+			'						<xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + 
+			'					</xsl:if>' + 
+			'				</xsl:for-each>' + 
+			'					<ins>' + 
+			'						<xsl:attribute name="class">jstree-icon ' + 
+			'							<xsl:if test="string-length(attribute::icon) > 0 and not(contains(@icon,\'/\'))"><xsl:value-of select="@icon" /></xsl:if>' + 
+			'						</xsl:attribute>' + 
+			'						<xsl:if test="string-length(attribute::icon) > 0 and contains(@icon,\'/\')"><xsl:attribute name="style">background:url(<xsl:value-of select="@icon" />) center center no-repeat;</xsl:attribute></xsl:if>' + 
+			'						<xsl:text>&#xa0;</xsl:text>' + 
+			'					</ins>' + 
+			'					<xsl:copy-of select="./child::node()" />' + 
+			'				</a>' + 
+			'			</xsl:for-each>' + 
+			'			<xsl:if test="$children or @hasChildren"><xsl:call-template name="nodes"><xsl:with-param name="node" select="current()" /></xsl:call-template></xsl:if>' + 
+			'		</li>' + 
+			'	</xsl:for-each>' + 
+			'	</ul>' + 
+			'</xsl:template>' + 
+			'</xsl:stylesheet>',
+
+		'flat' : '<' + '?xml version="1.0" encoding="utf-8" ?>' + 
+			'<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >' + 
+			'<xsl:output method="html" encoding="utf-8" omit-xml-declaration="yes" standalone="no" indent="no" media-type="text/xml" />' + 
+			'<xsl:template match="/">' + 
+			'	<ul>' + 
+			'	<xsl:for-each select="//item[not(@parent_id) or @parent_id=0 or not(@parent_id = //item/@id)]">' + /* the last `or` may be removed */
+			'		<xsl:call-template name="nodes">' + 
+			'			<xsl:with-param name="node" select="." />' + 
+			'			<xsl:with-param name="is_last" select="number(position() = last())" />' + 
+			'		</xsl:call-template>' + 
+			'	</xsl:for-each>' + 
+			'	</ul>' + 
+			'</xsl:template>' + 
+			'<xsl:template name="nodes">' + 
+			'	<xsl:param name="node" />' + 
+			'	<xsl:param name="is_last" />' + 
+			'	<xsl:variable name="children" select="count(//item[@parent_id=$node/attribute::id]) &gt; 0" />' + 
+			'	<li>' + 
+			'	<xsl:attribute name="class">' + 
+			'		<xsl:if test="$is_last = true()">jstree-last </xsl:if>' + 
+			'		<xsl:choose>' + 
+			'			<xsl:when test="@state = \'open\'">jstree-open </xsl:when>' + 
+			'			<xsl:when test="$children or @hasChildren or @state = \'closed\'">jstree-closed </xsl:when>' + 
+			'			<xsl:otherwise>jstree-leaf </xsl:otherwise>' + 
+			'		</xsl:choose>' + 
+			'		<xsl:value-of select="@class" />' + 
+			'	</xsl:attribute>' + 
+			'	<xsl:for-each select="@*">' + 
+			'		<xsl:if test="name() != \'parent_id\' and name() != \'hasChildren\' and name() != \'class\' and name() != \'state\'">' + 
+			'		<xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + 
+			'		</xsl:if>' + 
+			'	</xsl:for-each>' + 
+			'	<ins class="jstree-icon"><xsl:text>&#xa0;</xsl:text></ins>' + 
+			'	<xsl:for-each select="content/name">' + 
+			'		<a>' + 
+			'		<xsl:attribute name="href">' + 
+			'			<xsl:choose>' + 
+			'			<xsl:when test="@href"><xsl:value-of select="@href" /></xsl:when>' + 
+			'			<xsl:otherwise>#</xsl:otherwise>' + 
+			'			</xsl:choose>' + 
+			'		</xsl:attribute>' + 
+			'		<xsl:attribute name="class"><xsl:value-of select="@lang" /> <xsl:value-of select="@class" /></xsl:attribute>' + 
+			'		<xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute>' + 
+			'		<xsl:for-each select="@*">' + 
+			'			<xsl:if test="name() != \'style\' and name() != \'class\' and name() != \'href\'">' + 
+			'				<xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + 
+			'			</xsl:if>' + 
+			'		</xsl:for-each>' + 
+			'			<ins>' + 
+			'				<xsl:attribute name="class">jstree-icon ' + 
+			'					<xsl:if test="string-length(attribute::icon) > 0 and not(contains(@icon,\'/\'))"><xsl:value-of select="@icon" /></xsl:if>' + 
+			'				</xsl:attribute>' + 
+			'				<xsl:if test="string-length(attribute::icon) > 0 and contains(@icon,\'/\')"><xsl:attribute name="style">background:url(<xsl:value-of select="@icon" />) center center no-repeat;</xsl:attribute></xsl:if>' + 
+			'				<xsl:text>&#xa0;</xsl:text>' + 
+			'			</ins>' + 
+			'			<xsl:copy-of select="./child::node()" />' + 
+			'		</a>' + 
+			'	</xsl:for-each>' + 
+			'	<xsl:if test="$children">' + 
+			'		<ul>' + 
+			'		<xsl:for-each select="//item[@parent_id=$node/attribute::id]">' + 
+			'			<xsl:call-template name="nodes">' + 
+			'				<xsl:with-param name="node" select="." />' + 
+			'				<xsl:with-param name="is_last" select="number(position() = last())" />' + 
+			'			</xsl:call-template>' + 
+			'		</xsl:for-each>' + 
+			'		</ul>' + 
+			'	</xsl:if>' + 
+			'	</li>' + 
+			'</xsl:template>' + 
+			'</xsl:stylesheet>'
+	},
+	escape_xml = function(string) {
+		return string
+			.toString()
+			.replace(/&/g, '&amp;')
+			.replace(/</g, '&lt;')
+			.replace(/>/g, '&gt;')
+			.replace(/"/g, '&quot;')
+			.replace(/'/g, '&apos;');
+	};
+	$.jstree.plugin("xml_data", {
+		defaults : { 
+			data : false,
+			ajax : false,
+			xsl : "flat",
+			clean_node : false,
+			correct_state : true,
+			get_skip_empty : false,
+			get_include_preamble : true
+		},
+		_fn : {
+			load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_xml(obj, function () { _this.__callback({ "obj" : _this._get_node(obj) }); s_call.call(this); }, e_call); },
+			_is_loaded : function (obj) { 
+				var s = this._get_settings().xml_data;
+				obj = this._get_node(obj);
+				return obj == -1 || !obj || (!s.ajax && !$.isFunction(s.data)) || obj.is(".jstree-open, .jstree-leaf") || obj.children("ul").children("li").size() > 0;
+			},
+			load_node_xml : function (obj, s_call, e_call) {
+				var s = this.get_settings().xml_data,
+					error_func = function () {},
+					success_func = function () {};
+
+				obj = this._get_node(obj);
+				if(obj && obj !== -1) {
+					if(obj.data("jstree_is_loading")) { return; }
+					else { obj.data("jstree_is_loading",true); }
+				}
+				switch(!0) {
+					case (!s.data && !s.ajax): throw "Neither data nor ajax settings supplied.";
+					case ($.isFunction(s.data)):
+						s.data.call(this, obj, $.proxy(function (d) {
+							this.parse_xml(d, $.proxy(function (d) {
+								if(d) {
+									d = d.replace(/ ?xmlns="[^"]*"/ig, "");
+									if(d.length > 10) {
+										d = $(d);
+										if(obj === -1 || !obj) { this.get_container().children("ul").empty().append(d.children()); }
+										else { obj.children("a.jstree-loading").removeClass("jstree-loading"); obj.append(d); obj.removeData("jstree_is_loading"); }
+										if(s.clean_node) { this.clean_node(obj); }
+										if(s_call) { s_call.call(this); }
+									}
+									else {
+										if(obj && obj !== -1) { 
+											obj.children("a.jstree-loading").removeClass("jstree-loading");
+											obj.removeData("jstree_is_loading");
+											if(s.correct_state) { 
+												this.correct_state(obj);
+												if(s_call) { s_call.call(this); } 
+											}
+										}
+										else {
+											if(s.correct_state) { 
+												this.get_container().children("ul").empty();
+												if(s_call) { s_call.call(this); } 
+											}
+										}
+									}
+								}
+							}, this));
+						}, this));
+						break;
+					case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):
+						if(!obj || obj == -1) {
+							this.parse_xml(s.data, $.proxy(function (d) {
+								if(d) {
+									d = d.replace(/ ?xmlns="[^"]*"/ig, "");
+									if(d.length > 10) {
+										d = $(d);
+										this.get_container().children("ul").empty().append(d.children());
+										if(s.clean_node) { this.clean_node(obj); }
+										if(s_call) { s_call.call(this); }
+									}
+								}
+								else { 
+									if(s.correct_state) { 
+										this.get_container().children("ul").empty(); 
+										if(s_call) { s_call.call(this); }
+									}
+								}
+							}, this));
+						}
+						break;
+					case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):
+						error_func = function (x, t, e) {
+							var ef = this.get_settings().xml_data.ajax.error; 
+							if(ef) { ef.call(this, x, t, e); }
+							if(obj !== -1 && obj.length) {
+								obj.children("a.jstree-loading").removeClass("jstree-loading");
+								obj.removeData("jstree_is_loading");
+								if(t === "success" && s.correct_state) { this.correct_state(obj); }
+							}
+							else {
+								if(t === "success" && s.correct_state) { this.get_container().children("ul").empty(); }
+							}
+							if(e_call) { e_call.call(this); }
+						};
+						success_func = function (d, t, x) {
+							d = x.responseText;
+							var sf = this.get_settings().xml_data.ajax.success; 
+							if(sf) { d = sf.call(this,d,t,x) || d; }
+							if(d === "" || (d && d.toString && d.toString().replace(/^[\s\n]+$/,"") === "")) {
+								return error_func.call(this, x, t, "");
+							}
+							this.parse_xml(d, $.proxy(function (d) {
+								if(d) {
+									d = d.replace(/ ?xmlns="[^"]*"/ig, "");
+									if(d.length > 10) {
+										d = $(d);
+										if(obj === -1 || !obj) { this.get_container().children("ul").empty().append(d.children()); }
+										else { obj.children("a.jstree-loading").removeClass("jstree-loading"); obj.append(d); obj.removeData("jstree_is_loading"); }
+										if(s.clean_node) { this.clean_node(obj); }
+										if(s_call) { s_call.call(this); }
+									}
+									else {
+										if(obj && obj !== -1) { 
+											obj.children("a.jstree-loading").removeClass("jstree-loading");
+											obj.removeData("jstree_is_loading");
+											if(s.correct_state) { 
+												this.correct_state(obj);
+												if(s_call) { s_call.call(this); } 
+											}
+										}
+										else {
+											if(s.correct_state) { 
+												this.get_container().children("ul").empty();
+												if(s_call) { s_call.call(this); } 
+											}
+										}
+									}
+								}
+							}, this));
+						};
+						s.ajax.context = this;
+						s.ajax.error = error_func;
+						s.ajax.success = success_func;
+						if(!s.ajax.dataType) { s.ajax.dataType = "xml"; }
+						if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }
+						if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }
+						$.ajax(s.ajax);
+						break;
+				}
+			},
+			parse_xml : function (xml, callback) {
+				var s = this._get_settings().xml_data;
+				$.vakata.xslt(xml, xsl[s.xsl], callback);
+			},
+			get_xml : function (tp, obj, li_attr, a_attr, is_callback) {
+				var result = "", 
+					s = this._get_settings(), 
+					_this = this,
+					tmp1, tmp2, li, a, lang;
+				if(!tp) { tp = "flat"; }
+				if(!is_callback) { is_callback = 0; }
+				obj = this._get_node(obj);
+				if(!obj || obj === -1) { obj = this.get_container().find("> ul > li"); }
+				li_attr = $.isArray(li_attr) ? li_attr : [ "id", "class" ];
+				if(!is_callback && this.data.types && $.inArray(s.types.type_attr, li_attr) === -1) { li_attr.push(s.types.type_attr); }
+
+				a_attr = $.isArray(a_attr) ? a_attr : [ ];
+
+				if(!is_callback) { 
+					if(s.xml_data.get_include_preamble) { 
+						result += '<' + '?xml version="1.0" encoding="UTF-8"?' + '>'; 
+					}
+					result += "<root>"; 
+				}
+				obj.each(function () {
+					result += "<item";
+					li = $(this);
+					$.each(li_attr, function (i, v) { 
+						var t = li.attr(v);
+						if(!s.xml_data.get_skip_empty || typeof t !== "undefined") {
+							result += " " + v + "=\"" + escape_xml((" " + (t || "")).replace(/ jstree[^ ]*/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,"")) + "\""; 
+						}
+					});
+					if(li.hasClass("jstree-open")) { result += " state=\"open\""; }
+					if(li.hasClass("jstree-closed")) { result += " state=\"closed\""; }
+					if(tp === "flat") { result += " parent_id=\"" + escape_xml(is_callback) + "\""; }
+					result += ">";
+					result += "<content>";
+					a = li.children("a");
+					a.each(function () {
+						tmp1 = $(this);
+						lang = false;
+						result += "<name";
+						if($.inArray("languages", s.plugins) !== -1) {
+							$.each(s.languages, function (k, z) {
+								if(tmp1.hasClass(z)) { result += " lang=\"" + escape_xml(z) + "\""; lang = z; return false; }
+							});
+						}
+						if(a_attr.length) { 
+							$.each(a_attr, function (k, z) {
+								var t = tmp1.attr(z);
+								if(!s.xml_data.get_skip_empty || typeof t !== "undefined") {
+									result += " " + z + "=\"" + escape_xml((" " + t || "").replace(/ jstree[^ ]*/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,"")) + "\"";
+								}
+							});
+						}
+						if(tmp1.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\s+$/ig,"").length) {
+							result += ' icon="' + escape_xml(tmp1.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,"")) + '"';
+						}
+						if(tmp1.children("ins").get(0).style.backgroundImage.length) {
+							result += ' icon="' + escape_xml(tmp1.children("ins").get(0).style.backgroundImage.replace("url(","").replace(")","").replace(/'/ig,"").replace(/"/ig,"")) + '"';
+						}
+						result += ">";
+						result += "<![CDATA[" + _this.get_text(tmp1, lang) + "]]>";
+						result += "</name>";
+					});
+					result += "</content>";
+					tmp2 = li[0].id || true;
+					li = li.find("> ul > li");
+					if(li.length) { tmp2 = _this.get_xml(tp, li, li_attr, a_attr, tmp2); }
+					else { tmp2 = ""; }
+					if(tp == "nest") { result += tmp2; }
+					result += "</item>";
+					if(tp == "flat") { result += tmp2; }
+				});
+				if(!is_callback) { result += "</root>"; }
+				return result;
+			}
+		}
+	});
+})(jQuery);
+//*/
+
+/*
+ * jsTree search plugin
+ * Enables both sync and async search on the tree
+ * DOES NOT WORK WITH JSON PROGRESSIVE RENDER
+ */
+(function ($) {
+	$.expr[':'].jstree_contains = function(a,i,m){
+		return (a.textContent || a.innerText || "").toLowerCase().indexOf(m[3].toLowerCase())>=0;
+	};
+	$.expr[':'].jstree_title_contains = function(a,i,m) {
+		return (a.getAttribute("title") || "").toLowerCase().indexOf(m[3].toLowerCase())>=0;
+	};
+	$.jstree.plugin("search", {
+		__init : function () {
+			this.data.search.str = "";
+			this.data.search.result = $();
+			if(this._get_settings().search.show_only_matches) {
+				this.get_container()
+					.bind("search.jstree", function (e, data) {
+						$(this).children("ul").find("li").hide().removeClass("jstree-last");
+						data.rslt.nodes.parentsUntil(".jstree").andSelf().show()
+							.filter("ul").each(function () { $(this).children("li:visible").eq(-1).addClass("jstree-last"); });
+					})
+					.bind("clear_search.jstree", function () {
+						$(this).children("ul").find("li").css("display","").end().end().jstree("clean_node", -1);
+					});
+			}
+		},
+		defaults : {
+			ajax : false,
+			search_method : "jstree_contains", // for case insensitive - jstree_contains
+			show_only_matches : false
+		},
+		_fn : {
+			search : function (str, skip_async) {
+				if($.trim(str) === "") { this.clear_search(); return; }
+				var s = this.get_settings().search, 
+					t = this,
+					error_func = function () { },
+					success_func = function () { };
+				this.data.search.str = str;
+
+				if(!skip_async && s.ajax !== false && this.get_container_ul().find("li.jstree-closed:not(:has(ul)):eq(0)").length > 0) {
+					this.search.supress_callback = true;
+					error_func = function () { };
+					success_func = function (d, t, x) {
+						var sf = this.get_settings().search.ajax.success; 
+						if(sf) { d = sf.call(this,d,t,x) || d; }
+						this.data.search.to_open = d;
+						this._search_open();
+					};
+					s.ajax.context = this;
+					s.ajax.error = error_func;
+					s.ajax.success = success_func;
+					if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, str); }
+					if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, str); }
+					if(!s.ajax.data) { s.ajax.data = { "search_string" : str }; }
+					if(!s.ajax.dataType || /^json/.exec(s.ajax.dataType)) { s.ajax.dataType = "json"; }
+					$.ajax(s.ajax);
+					return;
+				}
+				if(this.data.search.result.length) { this.clear_search(); }
+				this.data.search.result = this.get_container().find("a" + (this.data.languages ? "." + this.get_lang() : "" ) + ":" + (s.search_method) + "(" + this.data.search.str + ")");
+				this.data.search.result.addClass("jstree-search").parent().parents(".jstree-closed").each(function () {
+					t.open_node(this, false, true);
+				});
+				this.__callback({ nodes : this.data.search.result, str : str });
+			},
+			clear_search : function (str) {
+				this.data.search.result.removeClass("jstree-search");
+				this.__callback(this.data.search.result);
+				this.data.search.result = $();
+			},
+			_search_open : function (is_callback) {
+				var _this = this,
+					done = true,
+					current = [],
+					remaining = [];
+				if(this.data.search.to_open.length) {
+					$.each(this.data.search.to_open, function (i, val) {
+						if(val == "#") { return true; }
+						if($(val).length && $(val).is(".jstree-closed")) { current.push(val); }
+						else { remaining.push(val); }
+					});
+					if(current.length) {
+						this.data.search.to_open = remaining;
+						$.each(current, function (i, val) { 
+							_this.open_node(val, function () { _this._search_open(true); }); 
+						});
+						done = false;
+					}
+				}
+				if(done) { this.search(this.data.search.str, true); }
+			}
+		}
+	});
+})(jQuery);
+//*/
+
+/* 
+ * jsTree contextmenu plugin
+ */
+(function ($) {
+	$.vakata.context = {
+		hide_on_mouseleave : false,
+
+		cnt		: $("<div id='vakata-contextmenu' />"),
+		vis		: false,
+		tgt		: false,
+		par		: false,
+		func	: false,
+		data	: false,
+		rtl		: false,
+		show	: function (s, t, x, y, d, p, rtl) {
+			$.vakata.context.rtl = !!rtl;
+			var html = $.vakata.context.parse(s), h, w;
+			if(!html) { return; }
+			$.vakata.context.vis = true;
+			$.vakata.context.tgt = t;
+			$.vakata.context.par = p || t || null;
+			$.vakata.context.data = d || null;
+			$.vakata.context.cnt
+				.html(html)
+				.css({ "visibility" : "hidden", "display" : "block", "left" : 0, "top" : 0 });
+
+			if($.vakata.context.hide_on_mouseleave) {
+				$.vakata.context.cnt
+					.one("mouseleave", function(e) { $.vakata.context.hide(); });
+			}
+
+			h = $.vakata.context.cnt.height();
+			w = $.vakata.context.cnt.width();
+			if(x + w > $(document).width()) { 
+				x = $(document).width() - (w + 5); 
+				$.vakata.context.cnt.find("li > ul").addClass("right"); 
+			}
+			if(y + h > $(document).height()) { 
+				y = y - (h + t[0].offsetHeight); 
+				$.vakata.context.cnt.find("li > ul").addClass("bottom"); 
+			}
+
+			$.vakata.context.cnt
+				.css({ "left" : x, "top" : y })
+				.find("li:has(ul)")
+					.bind("mouseenter", function (e) { 
+						var w = $(document).width(),
+							h = $(document).height(),
+							ul = $(this).children("ul").show(); 
+						if(w !== $(document).width()) { ul.toggleClass("right"); }
+						if(h !== $(document).height()) { ul.toggleClass("bottom"); }
+					})
+					.bind("mouseleave", function (e) { 
+						$(this).children("ul").hide(); 
+					})
+					.end()
+				.css({ "visibility" : "visible" })
+				.show();
+			$(document).triggerHandler("context_show.vakata");
+		},
+		hide	: function () {
+			$.vakata.context.vis = false;
+			$.vakata.context.cnt.attr("class","").css({ "visibility" : "hidden" });
+			$(document).triggerHandler("context_hide.vakata");
+		},
+		parse	: function (s, is_callback) {
+			if(!s) { return false; }
+			var str = "",
+				tmp = false,
+				was_sep = true;
+			if(!is_callback) { $.vakata.context.func = {}; }
+			str += "<ul>";
+			$.each(s, function (i, val) {
+				if(!val) { return true; }
+				$.vakata.context.func[i] = val.action;
+				if(!was_sep && val.separator_before) {
+					str += "<li class='vakata-separator vakata-separator-before'></li>";
+				}
+				was_sep = false;
+				str += "<li class='" + (val._class || "") + (val._disabled ? " jstree-contextmenu-disabled " : "") + "'><ins ";
+				if(val.icon && val.icon.indexOf("/") === -1) { str += " class='" + val.icon + "' "; }
+				if(val.icon && val.icon.indexOf("/") !== -1) { str += " style='background:url(" + val.icon + ") center center no-repeat;' "; }
+				str += ">&#160;</ins><a href='#' rel='" + i + "'>";
+				if(val.submenu) {
+					str += "<span style='float:" + ($.vakata.context.rtl ? "left" : "right") + ";'>&raquo;</span>";
+				}
+				str += val.label + "</a>";
+				if(val.submenu) {
+					tmp = $.vakata.context.parse(val.submenu, true);
+					if(tmp) { str += tmp; }
+				}
+				str += "</li>";
+				if(val.separator_after) {
+					str += "<li class='vakata-separator vakata-separator-after'></li>";
+					was_sep = true;
+				}
+			});
+			str = str.replace(/<li class\='vakata-separator vakata-separator-after'\><\/li\>$/,"");
+			str += "</ul>";
+			$(document).triggerHandler("context_parse.vakata");
+			return str.length > 10 ? str : false;
+		},
+		exec	: function (i) {
+			if($.isFunction($.vakata.context.func[i])) {
+				// if is string - eval and call it!
+				$.vakata.context.func[i].call($.vakata.context.data, $.vakata.context.par);
+				return true;
+			}
+			else { return false; }
+		}
+	};
+	$(function () {
+		var css_string = '' + 
+			'#vakata-contextmenu { display:block; visibility:hidden; left:0; top:-200px; position:absolute; margin:0; padding:0; min-width:180px; background:#ebebeb; border:1px solid silver; z-index:10000; *width:180px; } ' + 
+			'#vakata-contextmenu ul { min-width:180px; *width:180px; } ' + 
+			'#vakata-contextmenu ul, #vakata-contextmenu li { margin:0; padding:0; list-style-type:none; display:block; } ' + 
+			'#vakata-contextmenu li { line-height:20px; min-height:20px; position:relative; padding:0px; } ' + 
+			'#vakata-contextmenu li a { padding:1px 6px; line-height:17px; display:block; text-decoration:none; margin:1px 1px 0 1px; } ' + 
+			'#vakata-contextmenu li ins { float:left; width:16px; height:16px; text-decoration:none; margin-right:2px; } ' + 
+			'#vakata-contextmenu li a:hover, #vakata-contextmenu li.vakata-hover > a { background:gray; color:white; } ' + 
+			'#vakata-contextmenu li ul { display:none; position:absolute; top:-2px; left:100%; background:#ebebeb; border:1px solid gray; } ' + 
+			'#vakata-contextmenu .right { right:100%; left:auto; } ' + 
+			'#vakata-contextmenu .bottom { bottom:-1px; top:auto; } ' + 
+			'#vakata-contextmenu li.vakata-separator { min-height:0; height:1px; line-height:1px; font-size:1px; overflow:hidden; margin:0 2px; background:silver; /* border-top:1px solid #fefefe; */ padding:0; } ';
+		$.vakata.css.add_sheet({ str : css_string, title : "vakata" });
+		$.vakata.context.cnt
+			.delegate("a","click", function (e) { e.preventDefault(); })
+			.delegate("a","mouseup", function (e) {
+				if(!$(this).parent().hasClass("jstree-contextmenu-disabled") && $.vakata.context.exec($(this).attr("rel"))) {
+					$.vakata.context.hide();
+				}
+				else { $(this).blur(); }
+			})
+			.delegate("a","mouseover", function () {
+				$.vakata.context.cnt.find(".vakata-hover").removeClass("vakata-hover");
+			})
+			.appendTo("body");
+		$(document).bind("mousedown", function (e) { if($.vakata.context.vis && !$.contains($.vakata.context.cnt[0], e.target)) { $.vakata.context.hide(); } });
+		if(typeof $.hotkeys !== "undefined") {
+			$(document)
+				.bind("keydown", "up", function (e) { 
+					if($.vakata.context.vis) { 
+						var o = $.vakata.context.cnt.find("ul:visible").last().children(".vakata-hover").removeClass("vakata-hover").prevAll("li:not(.vakata-separator)").first();
+						if(!o.length) { o = $.vakata.context.cnt.find("ul:visible").last().children("li:not(.vakata-separator)").last(); }
+						o.addClass("vakata-hover");
+						e.stopImmediatePropagation(); 
+						e.preventDefault();
+					} 
+				})
+				.bind("keydown", "down", function (e) { 
+					if($.vakata.context.vis) { 
+						var o = $.vakata.context.cnt.find("ul:visible").last().children(".vakata-hover").removeClass("vakata-hover").nextAll("li:not(.vakata-separator)").first();
+						if(!o.length) { o = $.vakata.context.cnt.find("ul:visible").last().children("li:not(.vakata-separator)").first(); }
+						o.addClass("vakata-hover");
+						e.stopImmediatePropagation(); 
+						e.preventDefault();
+					} 
+				})
+				.bind("keydown", "right", function (e) { 
+					if($.vakata.context.vis) { 
+						$.vakata.context.cnt.find(".vakata-hover").children("ul").show().children("li:not(.vakata-separator)").removeClass("vakata-hover").first().addClass("vakata-hover");
+						e.stopImmediatePropagation(); 
+						e.preventDefault();
+					} 
+				})
+				.bind("keydown", "left", function (e) { 
+					if($.vakata.context.vis) { 
+						$.vakata.context.cnt.find(".vakata-hover").children("ul").hide().children(".vakata-separator").removeClass("vakata-hover");
+						e.stopImmediatePropagation(); 
+						e.preventDefault();
+					} 
+				})
+				.bind("keydown", "esc", function (e) { 
+					$.vakata.context.hide(); 
+					e.preventDefault();
+				})
+				.bind("keydown", "space", function (e) { 
+					$.vakata.context.cnt.find(".vakata-hover").last().children("a").click();
+					e.preventDefault();
+				});
+		}
+	});
+
+	$.jstree.plugin("contextmenu", {
+		__init : function () {
+			this.get_container()
+				.delegate("a", "contextmenu.jstree", $.proxy(function (e) {
+						e.preventDefault();
+						if(!$(e.currentTarget).hasClass("jstree-loading")) {
+							this.show_contextmenu(e.currentTarget, e.pageX, e.pageY);
+						}
+					}, this))
+				.delegate("a", "click.jstree", $.proxy(function (e) {
+						if(this.data.contextmenu) {
+							$.vakata.context.hide();
+						}
+					}, this))
+				.bind("destroy.jstree", $.proxy(function () {
+						// TODO: move this to descruct method
+						if(this.data.contextmenu) {
+							$.vakata.context.hide();
+						}
+					}, this));
+			$(document).bind("context_hide.vakata", $.proxy(function () { this.data.contextmenu = false; }, this));
+		},
+		defaults : { 
+			select_node : false, // requires UI plugin
+			show_at_node : true,
+			items : { // Could be a function that should return an object like this one
+				"create" : {
+					"separator_before"	: false,
+					"separator_after"	: true,
+					"label"				: "Create",
+					"action"			: function (obj) { this.create(obj); }
+				},
+				"rename" : {
+					"separator_before"	: false,
+					"separator_after"	: false,
+					"label"				: "Rename",
+					"action"			: function (obj) { this.rename(obj); }
+				},
+				"remove" : {
+					"separator_before"	: false,
+					"icon"				: false,
+					"separator_after"	: false,
+					"label"				: "Delete",
+					"action"			: function (obj) { if(this.is_selected(obj)) { this.remove(); } else { this.remove(obj); } }
+				},
+				"ccp" : {
+					"separator_before"	: true,
+					"icon"				: false,
+					"separator_after"	: false,
+					"label"				: "Edit",
+					"action"			: false,
+					"submenu" : { 
+						"cut" : {
+							"separator_before"	: false,
+							"separator_after"	: false,
+							"label"				: "Cut",
+							"action"			: function (obj) { this.cut(obj); }
+						},
+						"copy" : {
+							"separator_before"	: false,
+							"icon"				: false,
+							"separator_after"	: false,
+							"label"				: "Copy",
+							"action"			: function (obj) { this.copy(obj); }
+						},
+						"paste" : {
+							"separator_before"	: false,
+							"icon"				: false,
+							"separator_after"	: false,
+							"label"				: "Paste",
+							"action"			: function (obj) { this.paste(obj); }
+						}
+					}
+				}
+			}
+		},
+		_fn : {
+			show_contextmenu : function (obj, x, y) {
+				obj = this._get_node(obj);
+				var s = this.get_settings().contextmenu,
+					a = obj.children("a:visible:eq(0)"),
+					o = false,
+					i = false;
+				if(s.select_node && this.data.ui && !this.is_selected(obj)) {
+					this.deselect_all();
+					this.select_node(obj, true);
+				}
+				if(s.show_at_node || typeof x === "undefined" || typeof y === "undefined") {
+					o = a.offset();
+					x = o.left;
+					y = o.top + this.data.core.li_height;
+				}
+				i = obj.data("jstree") && obj.data("jstree").contextmenu ? obj.data("jstree").contextmenu : s.items;
+				if($.isFunction(i)) { i = i.call(this, obj); }
+				this.data.contextmenu = true;
+				$.vakata.context.show(i, a, x, y, this, obj, this._get_settings().core.rtl);
+				if(this.data.themes) { $.vakata.context.cnt.attr("class", "jstree-" + this.data.themes.theme + "-context"); }
+			}
+		}
+	});
+})(jQuery);
+//*/
+
+/* 
+ * jsTree types plugin
+ * Adds support types of nodes
+ * You can set an attribute on each li node, that represents its type.
+ * According to the type setting the node may get custom icon/validation rules
+ */
+(function ($) {
+	$.jstree.plugin("types", {
+		__init : function () {
+			var s = this._get_settings().types;
+			this.data.types.attach_to = [];
+			this.get_container()
+				.bind("init.jstree", $.proxy(function () { 
+						var types = s.types, 
+							attr  = s.type_attr, 
+							icons_css = "", 
+							_this = this;
+
+						$.each(types, function (i, tp) {
+							$.each(tp, function (k, v) { 
+								if(!/^(max_depth|max_children|icon|valid_children)$/.test(k)) { _this.data.types.attach_to.push(k); }
+							});
+							if(!tp.icon) { return true; }
+							if( tp.icon.image || tp.icon.position) {
+								if(i == "default")	{ icons_css += '.jstree-' + _this.get_index() + ' a > .jstree-icon { '; }
+								else				{ icons_css += '.jstree-' + _this.get_index() + ' li[' + attr + '="' + i + '"] > a > .jstree-icon { '; }
+								if(tp.icon.image)	{ icons_css += ' background-image:url(' + tp.icon.image + '); '; }
+								if(tp.icon.position){ icons_css += ' background-position:' + tp.icon.position + '; '; }
+								else				{ icons_css += ' background-position:0 0; '; }
+								icons_css += '} ';
+							}
+						});
+						if(icons_css !== "") { $.vakata.css.add_sheet({ 'str' : icons_css, title : "jstree-types" }); }
+					}, this))
+				.bind("before.jstree", $.proxy(function (e, data) { 
+						var s, t, 
+							o = this._get_settings().types.use_data ? this._get_node(data.args[0]) : false, 
+							d = o && o !== -1 && o.length ? o.data("jstree") : false;
+						if(d && d.types && d.types[data.func] === false) { e.stopImmediatePropagation(); return false; }
+						if($.inArray(data.func, this.data.types.attach_to) !== -1) {
+							if(!data.args[0] || (!data.args[0].tagName && !data.args[0].jquery)) { return; }
+							s = this._get_settings().types.types;
+							t = this._get_type(data.args[0]);
+							if(
+								( 
+									(s[t] && typeof s[t][data.func] !== "undefined") || 
+									(s["default"] && typeof s["default"][data.func] !== "undefined") 
+								) && this._check(data.func, data.args[0]) === false
+							) {
+								e.stopImmediatePropagation();
+								return false;
+							}
+						}
+					}, this));
+			if(is_ie6) {
+				this.get_container()
+					.bind("load_node.jstree set_type.jstree", $.proxy(function (e, data) {
+							var r = data && data.rslt && data.rslt.obj && data.rslt.obj !== -1 ? this._get_node(data.rslt.obj).parent() : this.get_container_ul(),
+								c = false,
+								s = this._get_settings().types;
+							$.each(s.types, function (i, tp) {
+								if(tp.icon && (tp.icon.image || tp.icon.position)) {
+									c = i === "default" ? r.find("li > a > .jstree-icon") : r.find("li[" + s.type_attr + "='" + i + "'] > a > .jstree-icon");
+									if(tp.icon.image) { c.css("backgroundImage","url(" + tp.icon.image + ")"); }
+									c.css("backgroundPosition", tp.icon.position || "0 0");
+								}
+							});
+						}, this));
+			}
+		},
+		defaults : {
+			// defines maximum number of root nodes (-1 means unlimited, -2 means disable max_children checking)
+			max_children		: -1,
+			// defines the maximum depth of the tree (-1 means unlimited, -2 means disable max_depth checking)
+			max_depth			: -1,
+			// defines valid node types for the root nodes
+			valid_children		: "all",
+
+			// whether to use $.data
+			use_data : false, 
+			// where is the type stores (the rel attribute of the LI element)
+			type_attr : "rel",
+			// a list of types
+			types : {
+				// the default type
+				"default" : {
+					"max_children"	: -1,
+					"max_depth"		: -1,
+					"valid_children": "all"
+
+					// Bound functions - you can bind any other function here (using boolean or function)
+					//"select_node"	: true
+				}
+			}
+		},
+		_fn : {
+			_types_notify : function (n, data) {
+				if(data.type && this._get_settings().types.use_data) {
+					this.set_type(data.type, n);
+				}
+			},
+			_get_type : function (obj) {
+				obj = this._get_node(obj);
+				return (!obj || !obj.length) ? false : obj.attr(this._get_settings().types.type_attr) || "default";
+			},
+			set_type : function (str, obj) {
+				obj = this._get_node(obj);
+				var ret = (!obj.length || !str) ? false : obj.attr(this._get_settings().types.type_attr, str);
+				if(ret) { this.__callback({ obj : obj, type : str}); }
+				return ret;
+			},
+			_check : function (rule, obj, opts) {
+				obj = this._get_node(obj);
+				var v = false, t = this._get_type(obj), d = 0, _this = this, s = this._get_settings().types, data = false;
+				if(obj === -1) { 
+					if(!!s[rule]) { v = s[rule]; }
+					else { return; }
+				}
+				else {
+					if(t === false) { return; }
+					data = s.use_data ? obj.data("jstree") : false;
+					if(data && data.types && typeof data.types[rule] !== "undefined") { v = data.types[rule]; }
+					else if(!!s.types[t] && typeof s.types[t][rule] !== "undefined") { v = s.types[t][rule]; }
+					else if(!!s.types["default"] && typeof s.types["default"][rule] !== "undefined") { v = s.types["default"][rule]; }
+				}
+				if($.isFunction(v)) { v = v.call(this, obj); }
+				if(rule === "max_depth" && obj !== -1 && opts !== false && s.max_depth !== -2 && v !== 0) {
+					// also include the node itself - otherwise if root node it is not checked
+					obj.children("a:eq(0)").parentsUntil(".jstree","li").each(function (i) {
+						// check if current depth already exceeds global tree depth
+						if(s.max_depth !== -1 && s.max_depth - (i + 1) <= 0) { v = 0; return false; }
+						d = (i === 0) ? v : _this._check(rule, this, false);
+						// check if current node max depth is already matched or exceeded
+						if(d !== -1 && d - (i + 1) <= 0) { v = 0; return false; }
+						// otherwise - set the max depth to the current value minus current depth
+						if(d >= 0 && (d - (i + 1) < v || v < 0) ) { v = d - (i + 1); }
+						// if the global tree depth exists and it minus the nodes calculated so far is less than `v` or `v` is unlimited
+						if(s.max_depth >= 0 && (s.max_depth - (i + 1) < v || v < 0) ) { v = s.max_depth - (i + 1); }
+					});
+				}
+				return v;
+			},
+			check_move : function () {
+				if(!this.__call_old()) { return false; }
+				var m  = this._get_move(),
+					s  = m.rt._get_settings().types,
+					mc = m.rt._check("max_children", m.cr),
+					md = m.rt._check("max_depth", m.cr),
+					vc = m.rt._check("valid_children", m.cr),
+					ch = 0, d = 1, t;
+
+				if(vc === "none") { return false; } 
+				if($.isArray(vc) && m.ot && m.ot._get_type) {
+					m.o.each(function () {
+						if($.inArray(m.ot._get_type(this), vc) === -1) { d = false; return false; }
+					});
+					if(d === false) { return false; }
+				}
+				if(s.max_children !== -2 && mc !== -1) {
+					ch = m.cr === -1 ? this.get_container().find("> ul > li").not(m.o).length : m.cr.find("> ul > li").not(m.o).length;
+					if(ch + m.o.length > mc) { return false; }
+				}
+				if(s.max_depth !== -2 && md !== -1) {
+					d = 0;
+					if(md === 0) { return false; }
+					if(typeof m.o.d === "undefined") {
+						// TODO: deal with progressive rendering and async when checking max_depth (how to know the depth of the moved node)
+						t = m.o;
+						while(t.length > 0) {
+							t = t.find("> ul > li");
+							d ++;
+						}
+						m.o.d = d;
+					}
+					if(md - m.o.d < 0) { return false; }
+				}
+				return true;
+			},
+			create_node : function (obj, position, js, callback, is_loaded, skip_check) {
+				if(!skip_check && (is_loaded || this._is_loaded(obj))) {
+					var p  = (typeof position == "string" && position.match(/^before|after$/i) && obj !== -1) ? this._get_parent(obj) : this._get_node(obj),
+						s  = this._get_settings().types,
+						mc = this._check("max_children", p),
+						md = this._check("max_depth", p),
+						vc = this._check("valid_children", p),
+						ch;
+					if(typeof js === "string") { js = { data : js }; }
+					if(!js) { js = {}; }
+					if(vc === "none") { return false; } 
+					if($.isArray(vc)) {
+						if(!js.attr || !js.attr[s.type_attr]) { 
+							if(!js.attr) { js.attr = {}; }
+							js.attr[s.type_attr] = vc[0]; 
+						}
+						else {
+							if($.inArray(js.attr[s.type_attr], vc) === -1) { return false; }
+						}
+					}
+					if(s.max_children !== -2 && mc !== -1) {
+						ch = p === -1 ? this.get_container().find("> ul > li").length : p.find("> ul > li").length;
+						if(ch + 1 > mc) { return false; }
+					}
+					if(s.max_depth !== -2 && md !== -1 && (md - 1) < 0) { return false; }
+				}
+				return this.__call_old(true, obj, position, js, callback, is_loaded, skip_check);
+			}
+		}
+	});
+})(jQuery);
+//*/
+
+/* 
+ * jsTree HTML plugin
+ * The HTML data store. Datastores are build by replacing the `load_node` and `_is_loaded` functions.
+ */
+(function ($) {
+	$.jstree.plugin("html_data", {
+		__init : function () { 
+			// this used to use html() and clean the whitespace, but this way any attached data was lost
+			this.data.html_data.original_container_html = this.get_container().find(" > ul > li").clone(true);
+			// remove white space from LI node - otherwise nodes appear a bit to the right
+			this.data.html_data.original_container_html.find("li").andSelf().contents().filter(function() { return this.nodeType == 3; }).remove();
+		},
+		defaults : { 
+			data : false,
+			ajax : false,
+			correct_state : true
+		},
+		_fn : {
+			load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_html(obj, function () { _this.__callback({ "obj" : _this._get_node(obj) }); s_call.call(this); }, e_call); },
+			_is_loaded : function (obj) { 
+				obj = this._get_node(obj); 
+				return obj == -1 || !obj || (!this._get_settings().html_data.ajax && !$.isFunction(this._get_settings().html_data.data)) || obj.is(".jstree-open, .jstree-leaf") || obj.children("ul").children("li").size() > 0;
+			},
+			load_node_html : function (obj, s_call, e_call) {
+				var d,
+					s = this.get_settings().html_data,
+					error_func = function () {},
+					success_func = function () {};
+				obj = this._get_node(obj);
+				if(obj && obj !== -1) {
+					if(obj.data("jstree_is_loading")) { return; }
+					else { obj.data("jstree_is_loading",true); }
+				}
+				switch(!0) {
+					case ($.isFunction(s.data)):
+						s.data.call(this, obj, $.proxy(function (d) {
+							if(d && d !== "" && d.toString && d.toString().replace(/^[\s\n]+$/,"") !== "") {
+								d = $(d);
+								if(!d.is("ul")) { d = $("<ul />").append(d); }
+								if(obj == -1 || !obj) { this.get_container().children("ul").empty().append(d.children()).find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end().filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); }
+								else { obj.children("a.jstree-loading").removeClass("jstree-loading"); obj.append(d).children("ul").find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end().filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); obj.removeData("jstree_is_loading"); }
+								this.clean_node(obj);
+								if(s_call) { s_call.call(this); }
+							}
+							else {
+								if(obj && obj !== -1) {
+									obj.children("a.jstree-loading").removeClass("jstree-loading");
+									obj.removeData("jstree_is_loading");
+									if(s.correct_state) { 
+										this.correct_state(obj);
+										if(s_call) { s_call.call(this); } 
+									}
+								}
+								else {
+									if(s.correct_state) { 
+										this.get_container().children("ul").empty();
+										if(s_call) { s_call.call(this); } 
+									}
+								}
+							}
+						}, this));
+						break;
+					case (!s.data && !s.ajax):
+						if(!obj || obj == -1) {
+							this.get_container()
+								.children("ul").empty()
+								.append(this.data.html_data.original_container_html)
+								.find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end()
+								.filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon");
+							this.clean_node();
+						}
+						if(s_call) { s_call.call(this); }
+						break;
+					case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)):
+						if(!obj || obj == -1) {
+							d = $(s.data);
+							if(!d.is("ul")) { d = $("<ul />").append(d); }
+							this.get_container()
+								.children("ul").empty().append(d.children())
+								.find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end()
+								.filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon");
+							this.clean_node();
+						}
+						if(s_call) { s_call.call(this); }
+						break;
+					case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1):
+						obj = this._get_node(obj);
+						error_func = function (x, t, e) {
+							var ef = this.get_settings().html_data.ajax.error; 
+							if(ef) { ef.call(this, x, t, e); }
+							if(obj != -1 && obj.length) {
+								obj.children("a.jstree-loading").removeClass("jstree-loading");
+								obj.removeData("jstree_is_loading");
+								if(t === "success" && s.correct_state) { this.correct_state(obj); }
+							}
+							else {
+								if(t === "success" && s.correct_state) { this.get_container().children("ul").empty(); }
+							}
+							if(e_call) { e_call.call(this); }
+						};
+						success_func = function (d, t, x) {
+							var sf = this.get_settings().html_data.ajax.success; 
+							if(sf) { d = sf.call(this,d,t,x) || d; }
+							if(d === "" || (d && d.toString && d.toString().replace(/^[\s\n]+$/,"") === "")) {
+								return error_func.call(this, x, t, "");
+							}
+							if(d) {
+								d = $(d);
+								if(!d.is("ul")) { d = $("<ul />").append(d); }
+								if(obj == -1 || !obj) { this.get_container().children("ul").empty().append(d.children()).find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end().filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); }
+								else { obj.children("a.jstree-loading").removeClass("jstree-loading"); obj.append(d).children("ul").find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end().filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); obj.removeData("jstree_is_loading"); }
+								this.clean_node(obj);
+								if(s_call) { s_call.call(this); }
+							}
+							else {
+								if(obj && obj !== -1) {
+									obj.children("a.jstree-loading").removeClass("jstree-loading");
+									obj.removeData("jstree_is_loading");
+									if(s.correct_state) { 
+										this.correct_state(obj);
+										if(s_call) { s_call.call(this); } 
+									}
+								}
+								else {
+									if(s.correct_state) { 
+										this.get_container().children("ul").empty();
+										if(s_call) { s_call.call(this); } 
+									}
+								}
+							}
+						};
+						s.ajax.context = this;
+						s.ajax.error = error_func;
+						s.ajax.success = success_func;
+						if(!s.ajax.dataType) { s.ajax.dataType = "html"; }
+						if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); }
+						if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); }
+						$.ajax(s.ajax);
+						break;
+				}
+			}
+		}
+	});
+	// include the HTML data plugin by default
+	$.jstree.defaults.plugins.push("html_data");
+})(jQuery);
+//*/
+
+/* 
+ * jsTree themeroller plugin
+ * Adds support for jQuery UI themes. Include this at the end of your plugins list, also make sure "themes" is not included.
+ */
+(function ($) {
+	$.jstree.plugin("themeroller", {
+		__init : function () {
+			var s = this._get_settings().themeroller;
+			this.get_container()
+				.addClass("ui-widget-content")
+				.addClass("jstree-themeroller")
+				.delegate("a","mouseenter.jstree", function (e) {
+					if(!$(e.currentTarget).hasClass("jstree-loading")) {
+						$(this).addClass(s.item_h);
+					}
+				})
+				.delegate("a","mouseleave.jstree", function () {
+					$(this).removeClass(s.item_h);
+				})
+				.bind("init.jstree", $.proxy(function (e, data) { 
+						data.inst.get_container().find("> ul > li > .jstree-loading > ins").addClass("ui-icon-refresh");
+						this._themeroller(data.inst.get_container().find("> ul > li"));
+					}, this))
+				.bind("open_node.jstree create_node.jstree", $.proxy(function (e, data) { 
+						this._themeroller(data.rslt.obj);
+					}, this))
+				.bind("loaded.jstree refresh.jstree", $.proxy(function (e) {
+						this._themeroller();
+					}, this))
+				.bind("close_node.jstree", $.proxy(function (e, data) {
+						this._themeroller(data.rslt.obj);
+					}, this))
+				.bind("delete_node.jstree", $.proxy(function (e, data) {
+						this._themeroller(data.rslt.parent);
+					}, this))
+				.bind("correct_state.jstree", $.proxy(function (e, data) {
+						data.rslt.obj
+							.children("ins.jstree-icon").removeClass(s.opened + " " + s.closed + " ui-icon").end()
+							.find("> a > ins.ui-icon")
+								.filter(function() { 
+									return this.className.toString()
+										.replace(s.item_clsd,"").replace(s.item_open,"").replace(s.item_leaf,"")
+										.indexOf("ui-icon-") === -1; 
+								}).removeClass(s.item_open + " " + s.item_clsd).addClass(s.item_leaf || "jstree-no-icon");
+					}, this))
+				.bind("select_node.jstree", $.proxy(function (e, data) {
+						data.rslt.obj.children("a").addClass(s.item_a);
+					}, this))
+				.bind("deselect_node.jstree deselect_all.jstree", $.proxy(function (e, data) {
+						this.get_container()
+							.find("a." + s.item_a).removeClass(s.item_a).end()
+							.find("a.jstree-clicked").addClass(s.item_a);
+					}, this))
+				.bind("dehover_node.jstree", $.proxy(function (e, data) {
+						data.rslt.obj.children("a").removeClass(s.item_h);
+					}, this))
+				.bind("hover_node.jstree", $.proxy(function (e, data) {
+						this.get_container()
+							.find("a." + s.item_h).not(data.rslt.obj).removeClass(s.item_h);
+						data.rslt.obj.children("a").addClass(s.item_h);
+					}, this))
+				.bind("move_node.jstree", $.proxy(function (e, data) {
+						this._themeroller(data.rslt.o);
+						this._themeroller(data.rslt.op);
+					}, this));
+		},
+		__destroy : function () {
+			var s = this._get_settings().themeroller,
+				c = [ "ui-icon" ];
+			$.each(s, function (i, v) {
+				v = v.split(" ");
+				if(v.length) { c = c.concat(v); }
+			});
+			this.get_container()
+				.removeClass("ui-widget-content")
+				.find("." + c.join(", .")).removeClass(c.join(" "));
+		},
+		_fn : {
+			_themeroller : function (obj) {
+				var s = this._get_settings().themeroller;
+				obj = !obj || obj == -1 ? this.get_container_ul() : this._get_node(obj).parent();
+				obj
+					.find("li.jstree-closed")
+						.children("ins.jstree-icon").removeClass(s.opened).addClass("ui-icon " + s.closed).end()
+						.children("a").addClass(s.item)
+							.children("ins.jstree-icon").addClass("ui-icon")
+								.filter(function() { 
+									return this.className.toString()
+										.replace(s.item_clsd,"").replace(s.item_open,"").replace(s.item_leaf,"")
+										.indexOf("ui-icon-") === -1; 
+								}).removeClass(s.item_leaf + " " + s.item_open).addClass(s.item_clsd || "jstree-no-icon")
+								.end()
+							.end()
+						.end()
+					.end()
+					.find("li.jstree-open")
+						.children("ins.jstree-icon").removeClass(s.closed).addClass("ui-icon " + s.opened).end()
+						.children("a").addClass(s.item)
+							.children("ins.jstree-icon").addClass("ui-icon")
+								.filter(function() { 
+									return this.className.toString()
+										.replace(s.item_clsd,"").replace(s.item_open,"").replace(s.item_leaf,"")
+										.indexOf("ui-icon-") === -1; 
+								}).removeClass(s.item_leaf + " " + s.item_clsd).addClass(s.item_open || "jstree-no-icon")
+								.end()
+							.end()
+						.end()
+					.end()
+					.find("li.jstree-leaf")
+						.children("ins.jstree-icon").removeClass(s.closed + " ui-icon " + s.opened).end()
+						.children("a").addClass(s.item)
+							.children("ins.jstree-icon").addClass("ui-icon")
+								.filter(function() { 
+									return this.className.toString()
+										.replace(s.item_clsd,"").replace(s.item_open,"").replace(s.item_leaf,"")
+										.indexOf("ui-icon-") === -1; 
+								}).removeClass(s.item_clsd + " " + s.item_open).addClass(s.item_leaf || "jstree-no-icon");
+			}
+		},
+		defaults : {
+			"opened"	: "ui-icon-triangle-1-se",
+			"closed"	: "ui-icon-triangle-1-e",
+			"item"		: "ui-state-default",
+			"item_h"	: "ui-state-hover",
+			"item_a"	: "ui-state-active",
+			"item_open"	: "ui-icon-folder-open",
+			"item_clsd"	: "ui-icon-folder-collapsed",
+			"item_leaf"	: "ui-icon-document"
+		}
+	});
+	$(function() {
+		var css_string = '' + 
+			'.jstree-themeroller .ui-icon { overflow:visible; } ' + 
+			'.jstree-themeroller a { padding:0 2px; } ' + 
+			'.jstree-themeroller .jstree-no-icon { display:none; }';
+		$.vakata.css.add_sheet({ str : css_string, title : "jstree" });
+	});
+})(jQuery);
+//*/
+
+/* 
+ * jsTree unique plugin
+ * Forces different names amongst siblings (still a bit experimental)
+ * NOTE: does not check language versions (it will not be possible to have nodes with the same title, even in different languages)
+ */
+(function ($) {
+	$.jstree.plugin("unique", {
+		__init : function () {
+			this.get_container()
+				.bind("before.jstree", $.proxy(function (e, data) { 
+						var nms = [], res = true, p, t;
+						if(data.func == "move_node") {
+							// obj, ref, position, is_copy, is_prepared, skip_check
+							if(data.args[4] === true) {
+								if(data.args[0].o && data.args[0].o.length) {
+									data.args[0].o.children("a").each(function () { nms.push($(this).text().replace(/^\s+/g,"")); });
+									res = this._check_unique(nms, data.args[0].np.find("> ul > li").not(data.args[0].o), "move_node");
+								}
+							}
+						}
+						if(data.func == "create_node") {
+							// obj, position, js, callback, is_loaded
+							if(data.args[4] || this._is_loaded(data.args[0])) {
+								p = this._get_node(data.args[0]);
+								if(data.args[1] && (data.args[1] === "before" || data.args[1] === "after")) {
+									p = this._get_parent(data.args[0]);
+									if(!p || p === -1) { p = this.get_container(); }
+								}
+								if(typeof data.args[2] === "string") { nms.push(data.args[2]); }
+								else if(!data.args[2] || !data.args[2].data) { nms.push(this._get_string("new_node")); }
+								else { nms.push(data.args[2].data); }
+								res = this._check_unique(nms, p.find("> ul > li"), "create_node");
+							}
+						}
+						if(data.func == "rename_node") {
+							// obj, val
+							nms.push(data.args[1]);
+							t = this._get_node(data.args[0]);
+							p = this._get_parent(t);
+							if(!p || p === -1) { p = this.get_container(); }
+							res = this._check_unique(nms, p.find("> ul > li").not(t), "rename_node");
+						}
+						if(!res) {
+							e.stopPropagation();
+							return false;
+						}
+					}, this));
+		},
+		defaults : { 
+			error_callback : $.noop
+		},
+		_fn : { 
+			_check_unique : function (nms, p, func) {
+				var cnms = [];
+				p.children("a").each(function () { cnms.push($(this).text().replace(/^\s+/g,"")); });
+				if(!cnms.length || !nms.length) { return true; }
+				cnms = cnms.sort().join(",,").replace(/(,|^)([^,]+)(,,\2)+(,|$)/g,"$1$2$4").replace(/,,+/g,",").replace(/,$/,"").split(",");
+				if((cnms.length + nms.length) != cnms.concat(nms).sort().join(",,").replace(/(,|^)([^,]+)(,,\2)+(,|$)/g,"$1$2$4").replace(/,,+/g,",").replace(/,$/,"").split(",").length) {
+					this._get_settings().unique.error_callback.call(null, nms, p, func);
+					return false;
+				}
+				return true;
+			},
+			check_move : function () {
+				if(!this.__call_old()) { return false; }
+				var p = this._get_move(), nms = [];
+				if(p.o && p.o.length) {
+					p.o.children("a").each(function () { nms.push($(this).text().replace(/^\s+/g,"")); });
+					return this._check_unique(nms, p.np.find("> ul > li").not(p.o), "check_move");
+				}
+				return true;
+			}
+		}
+	});
+})(jQuery);
+//*/
+
+/*
+ * jsTree wholerow plugin
+ * Makes select and hover work on the entire width of the node
+ * MAY BE HEAVY IN LARGE DOM
+ */
+(function ($) {
+	$.jstree.plugin("wholerow", {
+		__init : function () {
+			if(!this.data.ui) { throw "jsTree wholerow: jsTree UI plugin not included."; }
+			this.data.wholerow.html = false;
+			this.data.wholerow.to = false;
+			this.get_container()
+				.bind("init.jstree", $.proxy(function (e, data) { 
+						this._get_settings().core.animation = 0;
+					}, this))
+				.bind("open_node.jstree create_node.jstree clean_node.jstree loaded.jstree", $.proxy(function (e, data) { 
+						this._prepare_wholerow_span( data && data.rslt && data.rslt.obj ? data.rslt.obj : -1 );
+					}, this))
+				.bind("search.jstree clear_search.jstree reopen.jstree after_open.jstree after_close.jstree create_node.jstree delete_node.jstree clean_node.jstree", $.proxy(function (e, data) { 
+						if(this.data.to) { clearTimeout(this.data.to); }
+						this.data.to = setTimeout( (function (t, o) { return function() { t._prepare_wholerow_ul(o); }; })(this,  data && data.rslt && data.rslt.obj ? data.rslt.obj : -1), 0);
+					}, this))
+				.bind("deselect_all.jstree", $.proxy(function (e, data) { 
+						this.get_container().find(" > .jstree-wholerow .jstree-clicked").removeClass("jstree-clicked " + (this.data.themeroller ? this._get_settings().themeroller.item_a : "" ));
+					}, this))
+				.bind("select_node.jstree deselect_node.jstree ", $.proxy(function (e, data) { 
+						data.rslt.obj.each(function () { 
+							var ref = data.inst.get_container().find(" > .jstree-wholerow li:visible:eq(" + ( parseInt((($(this).offset().top - data.inst.get_container().offset().top + data.inst.get_container()[0].scrollTop) / data.inst.data.core.li_height),10)) + ")");
+							// ref.children("a")[e.type === "select_node" ? "addClass" : "removeClass"]("jstree-clicked");
+							ref.children("a").attr("class",data.rslt.obj.children("a").attr("class"));
+						});
+					}, this))
+				.bind("hover_node.jstree dehover_node.jstree", $.proxy(function (e, data) { 
+						this.get_container().find(" > .jstree-wholerow .jstree-hovered").removeClass("jstree-hovered " + (this.data.themeroller ? this._get_settings().themeroller.item_h : "" ));
+						if(e.type === "hover_node") {
+							var ref = this.get_container().find(" > .jstree-wholerow li:visible:eq(" + ( parseInt(((data.rslt.obj.offset().top - this.get_container().offset().top + this.get_container()[0].scrollTop) / this.data.core.li_height),10)) + ")");
+							// ref.children("a").addClass("jstree-hovered");
+							ref.children("a").attr("class",data.rslt.obj.children(".jstree-hovered").attr("class"));
+						}
+					}, this))
+				.delegate(".jstree-wholerow-span, ins.jstree-icon, li", "click.jstree", function (e) {
+						var n = $(e.currentTarget);
+						if(e.target.tagName === "A" || (e.target.tagName === "INS" && n.closest("li").is(".jstree-open, .jstree-closed"))) { return; }
+						n.closest("li").children("a:visible:eq(0)").click();
+						e.stopImmediatePropagation();
+					})
+				.delegate("li", "mouseover.jstree", $.proxy(function (e) {
+						e.stopImmediatePropagation();
+						if($(e.currentTarget).children(".jstree-hovered, .jstree-clicked").length) { return false; }
+						this.hover_node(e.currentTarget);
+						return false;
+					}, this))
+				.delegate("li", "mouseleave.jstree", $.proxy(function (e) {
+						if($(e.currentTarget).children("a").hasClass("jstree-hovered").length) { return; }
+						this.dehover_node(e.currentTarget);
+					}, this));
+			if(is_ie7 || is_ie6) {
+				$.vakata.css.add_sheet({ str : ".jstree-" + this.get_index() + " { position:relative; } ", title : "jstree" });
+			}
+		},
+		defaults : {
+		},
+		__destroy : function () {
+			this.get_container().children(".jstree-wholerow").remove();
+			this.get_container().find(".jstree-wholerow-span").remove();
+		},
+		_fn : {
+			_prepare_wholerow_span : function (obj) {
+				obj = !obj || obj == -1 ? this.get_container().find("> ul > li") : this._get_node(obj);
+				if(obj === false) { return; } // added for removing root nodes
+				obj.each(function () {
+					$(this).find("li").andSelf().each(function () {
+						var $t = $(this);
+						if($t.children(".jstree-wholerow-span").length) { return true; }
+						$t.prepend("<span class='jstree-wholerow-span' style='width:" + ($t.parentsUntil(".jstree","li").length * 18) + "px;'>&#160;</span>");
+					});
+				});
+			},
+			_prepare_wholerow_ul : function () {
+				var o = this.get_container().children("ul").eq(0), h = o.html();
+				o.addClass("jstree-wholerow-real");
+				if(this.data.wholerow.last_html !== h) {
+					this.data.wholerow.last_html = h;
+					this.get_container().children(".jstree-wholerow").remove();
+					this.get_container().append(
+						o.clone().removeClass("jstree-wholerow-real")
+							.wrapAll("<div class='jstree-wholerow' />").parent()
+							.width(o.parent()[0].scrollWidth)
+							.css("top", (o.height() + ( is_ie7 ? 5 : 0)) * -1 )
+							.find("li[id]").each(function () { this.removeAttribute("id"); }).end()
+					);
+				}
+			}
+		}
+	});
+	$(function() {
+		var css_string = '' + 
+			'.jstree .jstree-wholerow-real { position:relative; z-index:1; } ' + 
+			'.jstree .jstree-wholerow-real li { cursor:pointer; } ' + 
+			'.jstree .jstree-wholerow-real a { border-left-color:transparent !important; border-right-color:transparent !important; } ' + 
+			'.jstree .jstree-wholerow { position:relative; z-index:0; height:0; } ' + 
+			'.jstree .jstree-wholerow ul, .jstree .jstree-wholerow li { width:100%; } ' + 
+			'.jstree .jstree-wholerow, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow li, .jstree .jstree-wholerow a { margin:0 !important; padding:0 !important; } ' + 
+			'.jstree .jstree-wholerow, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow li { background:transparent !important; }' + 
+			'.jstree .jstree-wholerow ins, .jstree .jstree-wholerow span, .jstree .jstree-wholerow input { display:none !important; }' + 
+			'.jstree .jstree-wholerow a, .jstree .jstree-wholerow a:hover { text-indent:-9999px; !important; width:100%; padding:0 !important; border-right-width:0px !important; border-left-width:0px !important; } ' + 
+			'.jstree .jstree-wholerow-span { position:absolute; left:0; margin:0px; padding:0; height:18px; border-width:0; padding:0; z-index:0; }';
+		if(is_ff2) {
+			css_string += '' + 
+				'.jstree .jstree-wholerow a { display:block; height:18px; margin:0; padding:0; border:0; } ' + 
+				'.jstree .jstree-wholerow-real a { border-color:transparent !important; } ';
+		}
+		if(is_ie7 || is_ie6) {
+			css_string += '' + 
+				'.jstree .jstree-wholerow, .jstree .jstree-wholerow li, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow a { margin:0; padding:0; line-height:18px; } ' + 
+				'.jstree .jstree-wholerow a { display:block; height:18px; line-height:18px; overflow:hidden; } ';
+		}
+		$.vakata.css.add_sheet({ str : css_string, title : "jstree" });
+	});
+})(jQuery);
+//*/
+
+/*
+* jsTree model plugin
+* This plugin gets jstree to use a class model to retrieve data, creating great dynamism
+*/
+(function ($) {
+	var nodeInterface = ["getChildren","getChildrenCount","getAttr","getName","getProps"],
+		validateInterface = function(obj, inter) {
+			var valid = true;
+			obj = obj || {};
+			inter = [].concat(inter);
+			$.each(inter, function (i, v) {
+				if(!$.isFunction(obj[v])) { valid = false; return false; }
+			});
+			return valid;
+		};
+	$.jstree.plugin("model", {
+		__init : function () {
+			if(!this.data.json_data) { throw "jsTree model: jsTree json_data plugin not included."; }
+			this._get_settings().json_data.data = function (n, b) {
+				var obj = (n == -1) ? this._get_settings().model.object : n.data("jstree_model");
+				if(!validateInterface(obj, nodeInterface)) { return b.call(null, false); }
+				if(this._get_settings().model.async) {
+					obj.getChildren($.proxy(function (data) {
+						this.model_done(data, b);
+					}, this));
+				}
+				else {
+					this.model_done(obj.getChildren(), b);
+				}
+			};
+		},
+		defaults : {
+			object : false,
+			id_prefix : false,
+			async : false
+		},
+		_fn : {
+			model_done : function (data, callback) {
+				var ret = [], 
+					s = this._get_settings(),
+					_this = this;
+
+				if(!$.isArray(data)) { data = [data]; }
+				$.each(data, function (i, nd) {
+					var r = nd.getProps() || {};
+					r.attr = nd.getAttr() || {};
+					if(nd.getChildrenCount()) { r.state = "closed"; }
+					r.data = nd.getName();
+					if(!$.isArray(r.data)) { r.data = [r.data]; }
+					if(_this.data.types && $.isFunction(nd.getType)) {
+						r.attr[s.types.type_attr] = nd.getType();
+					}
+					if(r.attr.id && s.model.id_prefix) { r.attr.id = s.model.id_prefix + r.attr.id; }
+					if(!r.metadata) { r.metadata = { }; }
+					r.metadata.jstree_model = nd;
+					ret.push(r);
+				});
+				callback.call(null, ret);
+			}
+		}
+	});
+})(jQuery);
+//*/
+
+})();
\ No newline at end of file
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/debian/js/jquery/themes/default/d.gif and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/debian/js/jquery/themes/default/d.gif differ
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/debian/js/jquery/themes/default/d.png and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/debian/js/jquery/themes/default/d.png differ
diff -Nru cacti-0.8.8a/debian/js/jquery/themes/default/style.css cacti-0.8.8a+dfsg/debian/js/jquery/themes/default/style.css
--- cacti-0.8.8a/debian/js/jquery/themes/default/style.css	1970-01-01 01:00:00.000000000 +0100
+++ cacti-0.8.8a+dfsg/debian/js/jquery/themes/default/style.css	2012-04-23 21:58:08.000000000 +0200
@@ -0,0 +1,74 @@
+/*
+ * jsTree default theme 1.0
+ * Supported features: dots/no-dots, icons/no-icons, focused, loading
+ * Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search
+ */
+
+.jstree-default li, 
+.jstree-default ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; }
+.jstree-default li { background-position:-90px 0; background-repeat:repeat-y; }
+.jstree-default li.jstree-last { background:transparent; }
+.jstree-default .jstree-open > ins { background-position:-72px 0; }
+.jstree-default .jstree-closed > ins { background-position:-54px 0; }
+.jstree-default .jstree-leaf > ins { background-position:-36px 0; }
+
+.jstree-default .jstree-hovered { background:#e7f4f9; border:1px solid #d8f0fa; padding:0 2px 0 1px; }
+.jstree-default .jstree-clicked { background:#beebff; border:1px solid #99defd; padding:0 2px 0 1px; }
+.jstree-default a .jstree-icon { background-position:-56px -19px; }
+.jstree-default a.jstree-loading .jstree-icon { background:url("throbber.gif") center center no-repeat !important; }
+
+.jstree-default.jstree-focused { background:#ffffee; }
+
+.jstree-default .jstree-no-dots li, 
+.jstree-default .jstree-no-dots .jstree-leaf > ins { background:transparent; }
+.jstree-default .jstree-no-dots .jstree-open > ins { background-position:-18px 0; }
+.jstree-default .jstree-no-dots .jstree-closed > ins { background-position:0 0; }
+
+.jstree-default .jstree-no-icons a .jstree-icon { display:none; }
+
+.jstree-default .jstree-search { font-style:italic; }
+
+.jstree-default .jstree-no-icons .jstree-checkbox { display:inline-block; }
+.jstree-default .jstree-no-checkboxes .jstree-checkbox { display:none !important; }
+.jstree-default .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; }
+.jstree-default .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; }
+.jstree-default .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; }
+.jstree-default .jstree-checked > a > .jstree-checkbox:hover { background-position:-38px -37px; }
+.jstree-default .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; }
+.jstree-default .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; }
+
+#vakata-dragged.jstree-default ins { background:transparent !important; }
+#vakata-dragged.jstree-default .jstree-ok { background:url("d.png") -2px -53px no-repeat !important; }
+#vakata-dragged.jstree-default .jstree-invalid { background:url("d.png") -18px -53px no-repeat !important; }
+#jstree-marker.jstree-default { background:url("d.png") -41px -57px no-repeat !important; text-indent:-100px; }
+
+.jstree-default a.jstree-search { color:aqua; }
+.jstree-default .jstree-locked a { color:silver; cursor:default; }
+
+#vakata-contextmenu.jstree-default-context, 
+#vakata-contextmenu.jstree-default-context li ul { background:#f0f0f0; border:1px solid #979797; -moz-box-shadow: 1px 1px 2px #999; -webkit-box-shadow: 1px 1px 2px #999; box-shadow: 1px 1px 2px #999; }
+#vakata-contextmenu.jstree-default-context li { }
+#vakata-contextmenu.jstree-default-context a { color:black; }
+#vakata-contextmenu.jstree-default-context a:hover, 
+#vakata-contextmenu.jstree-default-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; }
+#vakata-contextmenu.jstree-default-context li.jstree-contextmenu-disabled a, 
+#vakata-contextmenu.jstree-default-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; }
+#vakata-contextmenu.jstree-default-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; }
+#vakata-contextmenu.jstree-default-context li ul { margin-left:-4px; }
+
+/* IE6 BEGIN */
+.jstree-default li, 
+.jstree-default ins,
+#vakata-dragged.jstree-default .jstree-invalid, 
+#vakata-dragged.jstree-default .jstree-ok, 
+#jstree-marker.jstree-default { _background-image:url("d.gif"); }
+.jstree-default .jstree-open ins { _background-position:-72px 0; }
+.jstree-default .jstree-closed ins { _background-position:-54px 0; }
+.jstree-default .jstree-leaf ins { _background-position:-36px 0; }
+.jstree-default a ins.jstree-icon { _background-position:-56px -19px; }
+#vakata-contextmenu.jstree-default-context ins { _display:none; }
+#vakata-contextmenu.jstree-default-context li { _zoom:1; }
+.jstree-default .jstree-undetermined a .jstree-checkbox { _background-position:-20px -19px; }
+.jstree-default .jstree-checked a .jstree-checkbox { _background-position:-38px -19px; }
+.jstree-default .jstree-unchecked a .jstree-checkbox { _background-position:-2px -19px; }
+/* IE6 END */
\ No newline at end of file
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/debian/js/jquery/themes/default/throbber.gif and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/debian/js/jquery/themes/default/throbber.gif differ
diff -Nru cacti-0.8.8a/debian/NEWS.Debian cacti-0.8.8a+dfsg/debian/NEWS.Debian
--- cacti-0.8.8a/debian/NEWS.Debian	1970-01-01 01:00:00.000000000 +0100
+++ cacti-0.8.8a+dfsg/debian/NEWS.Debian	2012-09-15 07:35:11.000000000 +0200
@@ -0,0 +1,14 @@
+cacti (0.8.8a-4) unstable; urgency=low
+
+  In 0.8.8 cacti introduced the Plugin Architecture in the main package. In
+  the Debian package I decided to let the user put all his plug-ins into
+  /usr/local/share/cacti/plugins. Unfortunately bug #681558 prevents this from
+  working out of the box. Therefore I moved the packaged location back to
+  /usr/share/cacti/site/plugins, but system administrators are encouraged to
+  setup the system properly, i.e. by soft-linking /usr/share/cacti/site/plugins
+  to /usr/local/share/cacti/plugins and adding two links back from
+  /usr/local/share/cacti/lib to /usr/share/cacti/site/lib and
+  /usr/local/share/cacti/include to /usr/share/cacti/site/include. This is also
+  documented in README.Plugins
+
+ -- Paul Gevers <[email-masked]>  Wed, 01 Aug 2012 22:13:57 +0200
diff -Nru cacti-0.8.8a/debian/patches/replace_treeview_by_jquery.jstree.patch cacti-0.8.8a+dfsg/debian/patches/replace_treeview_by_jquery.jstree.patch
--- cacti-0.8.8a/debian/patches/replace_treeview_by_jquery.jstree.patch	1970-01-01 01:00:00.000000000 +0100
+++ cacti-0.8.8a+dfsg/debian/patches/replace_treeview_by_jquery.jstree.patch	2012-11-25 12:19:18.000000000 +0100
@@ -0,0 +1,508 @@
+Description: treeview has a license issue, cacti upstream is going to replace it
+ with functionality from jquery.jstree.
+ .
+ This patch implements the changes needed for an upstream layout where the
+ necessary code is in cacti/include/js/jquery/ but the code in that path is
+ not included in this patch.
+ .
+ The necessary jquery scripts and theme info can come from cacti upstream and from
+ debian packages (libjs-jquery and libjs-jquery-cookie) The version used when
+ creating this patch can be found here:
+ http://svn.cacti.net/viewvc/cacti/branches/0.8.9/include/js/jquery/jquery.js?pathrev=7324
+ http://svn.cacti.net/viewvc/cacti/branches/0.8.9/include/js/jquery/jquery.jstree.js?pathrev=7324
+ http://svn.cacti.net/viewvc/cacti/branches/main/include/js/jquery/themes/default/?pathrev=7324
+ http://anonscm.debian.org/gitweb/?p=pkg-javascript/jquery-goodies.git;a=blob;f=cookie/jquery.cookie.js;hb=c50e1a2d599cb48893e8d77470e71e83e44dfdb5
+ .
+ This patch does NOT implement the changes needed for the Debian package of
+ cacti.
+Bug: http://bugs.cacti.net/view.php?id=2228
+Bug-Debian: http://bugs.debian.org/679980
+Author: Paul Gevers <[email-masked]>
+Date: Wed, 21 Nov 2012 23:19:40 +0100
+
+diff --git a/include/top_graph_header.php b/include/top_graph_header.php
+index 86bba4b..97766f4 100644
+--- a/include/top_graph_header.php
++++ b/include/top_graph_header.php
+@@ -84,8 +84,9 @@ $page_title = api_plugin_hook_function('page_title', draw_navigation_text("title
+ 	<link href="<?php echo $config['url_path']; ?>include/main.css" type="text/css" rel="stylesheet">
+ 	<link href="<?php echo $config['url_path']; ?>images/favicon.ico" rel="shortcut icon"/>
+ 	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/layout.js"></script>
+-	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/treeview/ua.js"></script>
+-	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/treeview/ftiens4.js"></script>
++	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/js/jquery/jquery.js" language="javascript"></script>
++	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/js/jquery/jquery.cookie.js" language="javascript"></script>
++	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/js/jquery/jquery.jstree.js"></script>
+ 	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/jscalendar/calendar.js"></script>
+ 	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/jscalendar/lang/calendar-en.js"></script>
+ 	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/jscalendar/calendar-setup.js"></script>
+@@ -178,7 +179,6 @@ $page_title = api_plugin_hook_function('page_title', draw_navigation_text("title
+ 		<td valign="top" style="padding: 5px; border-right: #aaaaaa 1px solid;background-repeat:repeat-y;background-color:#efefef;" bgcolor='#efefef' width='<?php print htmlspecialchars(read_graph_config_option("default_dual_pane_width"));?>' class='noprint'>
+ 			<table border=0 cellpadding=0 cellspacing=0><tr><td><a style="font-size:7pt;text-decoration:none;color:silver" href="http://www.treemenu.net/" target=_blank></a></td></tr></table>
+ 			<?php grow_dhtml_trees(); ?>
+-			<script type="text/javascript">initializeDocument();</script>
+ 
+ 			<?php if (isset($_GET["select_first"])) { ?>
+ 			<script type="text/javascript">
+diff --git a/lib/graph_export.php b/lib/graph_export.php
+index fd57041..0f1558f 100644
+--- a/lib/graph_export.php
++++ b/lib/graph_export.php
+@@ -1365,15 +1365,6 @@ function draw_html_left_tree($fp, $tree_id)  {
+ 	/* create the treeview representation for the html data */
+ 	grow_dhtml_trees_export($fp,$tree_id);
+ 
+-	fwrite($fp,"<script type='text/javascript'>initializeDocument();</script>\n");
+-	fwrite($fp,"<script type='text/javascript'>\n");
+-	fwrite($fp,"var obj;\n");
+-	fwrite($fp,"obj = findObj(1);\n");
+-	fwrite($fp,"if (!obj.isOpen) {\n");
+-	fwrite($fp,"clickOnNode(1);\n");
+-	fwrite($fp,"}\n");
+-	fwrite($fp,"clickOnLink(2,'','main');\n");
+-	fwrite($fp,"</script>\n");
+ 	fwrite($fp,"</td>\n");
+ 	fwrite($fp,"<td valign='top'>\n");
+ }
+@@ -1383,16 +1374,7 @@ function grow_dhtml_trees_export($fp, $tree_id) {
+ 	include_once($config["library_path"] . "/tree.php");
+ 	include_once($config["library_path"] . "/data_query.php");
+ 
+-	fwrite($fp, "<script type='text/javascript'>\n");
+-	fwrite($fp, "<!--
+-			USETEXTLINKS = 1
+-			STARTALLOPEN = 0
+-			USEFRAMES = 0
+-			USEICONS = 0
+-			WRAPTEXT = 1
+-			ICONPATH = 'treeview/'
+-			PERSERVESTATE = 1
+-			HIGHLIGHT = 1\n");
++	fwrite($fp, "<div id=\"jtree\">\n\t<ul>\n");
+ 
+ 	if (read_config_option("export_tree_isolation") == "off") {
+ 		$dhtml_tree_base = 0;
+@@ -1413,9 +1395,34 @@ function grow_dhtml_trees_export($fp, $tree_id) {
+ 		}
+ 	}
+ 
+-	fwrite($fp,"foldersTree.treeID = \"t2\"
+-			//-->\n
+-			</script>\n");
++	fwrite($fp, "\t</ul>\n</div>\n");
++	fwrite($fp, "<script type=\"text/javascript\">\n");
++	fwrite($fp, "$(function () {
++	$(\"#jtree\")
++		.jstree({
++                        \"plugins\" : [\"ui\",\"themes\",\"html_data\",\"cookies\"],
++        	        \"themes\" : {\"icons\" : false,
++				\"url\" : \"./js/style.css\"},
++			\"cookies\" : {
++				\"save_opened\" : \"Cacti_jstree_open\",
++				\"save_selected\" : \"Cacti_jstree_select\"
++				}
++
++                })
++
++                // Make sure that the nodes are actually used as links
++                // We need reselect to prevent endless loops
++                // https://groups.google.com/d/topic/jstree/j6XNq9hQdeA/discussion
++                .bind(\"reselect.jstree\", function (e, data) { 
++                      data.inst.get_container().bind(\"select_node.jstree\", function (e, data) {
++                           // data.rstl.obj is the object that was selected.
++                           document.location.href = data.rslt.obj.children(\"a\").attr(\"href\");
++                       });
++                });
++
++});\n");
++	fwrite($fp, "</script>\n");
++
+ }
+ 
+ /* get_graph_tree_array_export - returns a list of graph trees taking permissions into account if
+@@ -1478,8 +1485,7 @@ function create_dhtml_tree_export($tree_id) {
+ 	$dhtml_tree = array();
+ 	$dhtml_tree[0] = $start;
+ 	$dhtml_tree[1] = read_graph_config_option("expand_hosts");
+-	$dhtml_tree[2] = "foldersTree = gFld(\"\", \"\")\n";
+-	$i = 2;
++	$i = 1;
+ 
+ 	$tree_list = get_graph_tree_array_export();
+ 
+@@ -1499,7 +1505,6 @@ function create_dhtml_tree_export($tree_id) {
+ 		if (((read_config_option("export_tree_isolation") == "on") && ($tree_id == $tree["id"])) ||
+ 			(read_config_option("export_tree_isolation") == "off")) {
+ 
+-			$i++;
+ 
+ 			$hier_sql = "SELECT DISTINCT
+ 					graph_tree_items.id,
+@@ -1524,17 +1529,24 @@ function create_dhtml_tree_export($tree_id) {
+ 			if (sizeof($hierarchy) > 0) {
+ 				foreach ($hierarchy as $leaf) {
+ 					if ($dhtml_tree_id <> $tree["id"]) {
+-						$dhtml_tree[$i] = "ou0 = insFld(foldersTree, gFld(\"" . get_tree_name($tree["id"]) . "\", \"" . clean_up_export_name(get_tree_name($tree["id"])) . "_leaf.html\"))\n";
++						$i++;
++						$clean_id = clean_up_export_name(get_tree_name($tree["id"]));
++						$dhtml_tree[$i] = "\t\t<li id=\"" . $clean_id . "\"><a href=\"" . $clean_id . "_leaf.html\">" . get_tree_name($tree["id"]) . "</a>\n";
+ 					}
+ 					$dhtml_tree_id = $tree["id"];
+ 
+-					$i++;
+ 					$tier = tree_tier($leaf["order_key"]);
+ 
+ 					if ($leaf["host_id"] > 0) {  //It's a host
+-						$dhtml_tree[$i] = "ou" . ($tier) . " = insFld(ou" . ($tier-1) . ", gFld(\"Host: " . $leaf["hostname"] . "\", \"" . clean_up_export_name($leaf["hostname"] . "_" . $leaf["id"]) . ".html\"))\n";
++						$i++;
++						$dhtml_tree[$i] = "\t\t\t<ul>\n";
++						$i++;
++						$clean_id = clean_up_export_name($leaf["hostname"] . "_" . $leaf["id"]);
++						$dhtml_tree[$i] = "\t\t\t\t<li id=\"" . $clean_id . "\"><a href=\"" . $clean_id . ".html\">Host: " . htmlspecialchars($leaf["hostname"]) . "</a>\n";
+ 
+ 						if (read_config_option("export_tree_expand_hosts") == "on") {
++							$i++;
++							$dhtml_tree[$i] = "\t\t\t\t\t<ul>\n";
+ 							if ($leaf["host_grouping_type"] == HOST_GROUPING_GRAPH_TEMPLATE) {
+ 								$graph_templates = db_fetch_assoc("SELECT
+ 									graph_templates.id,
+@@ -1552,7 +1564,8 @@ function create_dhtml_tree_export($tree_id) {
+ 							 	if (sizeof($graph_templates) > 0) {
+ 									foreach ($graph_templates as $graph_template) {
+ 										$i++;
+-										$dhtml_tree[$i] = "ou" . ($tier+1) . " = insFld(ou" . ($tier) . ", gFld(\" " . $graph_template["name"] . "\", \"" . clean_up_export_name($leaf["hostname"] . "_gt_" . $leaf["id"]) . "_" . $graph_template["id"] . ".html\"))\n";
++										$clean_id = clean_up_export_name($leaf["hostname"] . "_gt_" . $leaf["id"] . "_" . $graph_template["id"]);
++										$dhtml_tree[$i] = "\t\t\t\t\t\t<li id=\"" . $clean_id . "\"><a href=\"" . $clean_id . ".html\">" . htmlspecialchars($graph_template["name"]) . "</a></li>\n";
+ 									}
+ 								}
+ 							}else if ($leaf["host_grouping_type"] == HOST_GROUPING_DATA_QUERY_INDEX) {
+@@ -1571,34 +1584,52 @@ function create_dhtml_tree_export($tree_id) {
+ 									));
+ 
+ 								if (sizeof($data_queries) > 0) {
+-								foreach ($data_queries as $data_query) {
+-									$i++;
+-
+-									$dhtml_tree[$i] = "ou" . ($tier+1) . " = insFld(ou" . ($tier) . ", gFld(\" " . $data_query["name"] . "\", \"" . clean_up_export_name($leaf["hostname"] . "_dq_" . $leaf["title"] . "_" . $leaf["id"]) . "_" . $data_query["id"] . ".html\"))\n";
++									foreach ($data_queries as $data_query) {
++										$i++;
++										$clean_id = clean_up_export_name($leaf["hostname"] . "_dq_" . $leaf["title"] . "_" . $leaf["id"] . "_" . $data_query["id"]);
++										$dhtml_tree[$i] = "\t\t\t\t\t\t<li id=\"" . $clean_id . "\"><a href=\"" . $clean_id . ".html\">" . htmlspecialchars($data_query["name"]) . "</a>\n";
+ 
+-									/* fetch a list of field names that are sorted by the preferred sort field */
+-									$sort_field_data = get_formatted_data_query_indexes($leaf["host_id"], $data_query["id"]);
++										/* fetch a list of field names that are sorted by the preferred sort field */
++										$sort_field_data = get_formatted_data_query_indexes($leaf["host_id"], $data_query["id"]);
+ 
+-									if ($data_query["id"] > 0) {
+-										while (list($snmp_index, $sort_field_value) = each($sort_field_data)) {
++										if ($data_query["id"] > 0) {
+ 											$i++;
+-											$dhtml_tree[$i] = "ou" . ($tier+2) . " = insFld(ou" . ($tier+1) . ", gFld(\" " . $sort_field_value . "\", \"" . clean_up_export_name($leaf["hostname"] . "_dqi_" . $leaf["title"] . "_" . $leaf["id"]) . "_" . $data_query["id"] . "_" . $snmp_index . ".html\"))\n";
++											$dhtml_tree[$i] = "\t\t\t\t\t\t\t<ul>\n";
++											while (list($snmp_index, $sort_field_value) = each($sort_field_data)) {
++												$i++;
++												$clean_id = clean_up_export_name($leaf["hostname"] . "_dqi_" . $leaf["id"] . "_" . $data_query["id"] . "_" . $snmp_index);
++												$dhtml_tree[$i] = "\t\t\t\t\t\t\t\t<li id=\"" . $clean_id . "\"><a href=\"" . $clean_id . ".html\">" . htmlspecialchars($sort_field_value) . "</a></li>\n";
++											}
++											$i++;
++											$dhtml_tree[$i] = "\t\t\t\t\t\t\t</ul>\n";
+ 										}
++										$i++;
++										$dhtml_tree[$i] = "\t\t\t\t\t\t</li>\n";
+ 									}
+ 								}
+-								}
+ 							}
++							$i++;
++							$dhtml_tree[$i] = "\t\t\t\t\t</ul>\n";
+ 						}
++						$i++;
++						$dhtml_tree[$i] = "\t\t\t\t</li>\n";
+ 					}else {
+-						$dhtml_tree[$i] = "ou" . ($tier) . " = insFld(ou" . ($tier-1) . ", gFld(\"" . $leaf["title"] . "\", \"" . clean_up_export_name(get_tree_name($tree["id"]) . "_" . $leaf["title"] . "_" . $leaf["id"]) . "_leaf.html\"))\n";
++						$i++;
++						$clean_id = clean_up_export_name(get_tree_name($tree["id"]) . "_" . $leaf["title"] . "_" . $leaf["id"]);
++						$dhtml_tree[$i] = "\t\t\t\t<li id=\"" . $clean_id . "\"><a href=\"" . $clean_id . "_leaf.html\">" . htmlspecialchars($leaf["title"]) . "</a></li>\n";
+ 					}
+ 				}
++				$i++;
++				$dhtml_tree[$i] = "\t\t\t</ul>\n";
+ 			}else{
+ 				if ($dhtml_tree_id <> $tree["id"]) {
+-					$dhtml_tree[$i] = "ou0 = insFld(foldersTree, gFld(\"" . get_tree_name($tree["id"]) . "\", \"" . clean_up_export_name(get_tree_name($tree["id"])) . "_leaf.html\"))\n";
+ 					$i++;
++					$clean_id = clean_up_export_name(get_tree_name($tree["id"]));
++					$dhtml_tree[$i] = "\t\t<li id=\"" . $clean_id . "_leaf\"><a href=\"" . $clean_id . "_leaf.html\">" . get_tree_name($tree["id"]) . "</a></li>\n";
+ 				}
+ 			}
++			$i++;
++			$dhtml_tree[$i] = "\t\t</li>\n";
+ 		}
+ 	}
+ 	}
+@@ -1612,10 +1643,10 @@ function create_dhtml_tree_export($tree_id) {
+         $dir - the export directory where graphs will either be staged or located.
+ */
+ function create_export_directory_structure($cacti_root_path, $dir) {
+-	/* create the treeview sub-directory */
+-	if (!is_dir("$dir/treeview")) {
+-		if (!mkdir("$dir/treeview", 0755)) {
+-			export_fatal("Create directory '" . $dir . "/treeview' failed.  Can not continue");
++	/* create the jquery sub-directory */
++	if (!is_dir("$dir/js")) {
++		if (!mkdir("$dir/js", 0755)) {
++			export_fatal("Create directory '" . $dir . "/js' failed.  Can not continue");
+ 		}
+ 	}
+ 
+@@ -1626,8 +1657,6 @@ function create_export_directory_structure($cacti_root_path, $dir) {
+ 		}
+ 	}
+ 
+-	$treeview_dir = $dir . "/treeview";
+-
+ 	/* css */
+ 	copy("$cacti_root_path/include/main.css", "$dir/main.css");
+ 
+@@ -1639,18 +1668,15 @@ function create_export_directory_structure($cacti_root_path, $dir) {
+ 	copy("$cacti_root_path/images/shadow_gray.gif", "$dir/shadow_gray.gif");
+ 
+ 	/* java scripts for the tree */
+-	copy("$cacti_root_path/include/treeview/ftiens4_export.js", "$treeview_dir/ftiens4.js");
+-	copy("$cacti_root_path/include/treeview/ua.js", "$treeview_dir/ua.js");
+-
+-	/* images for the tree */
+-	copy("$cacti_root_path/include/treeview/ftv2blank.gif", "$treeview_dir/ftv2blank.gif");
+-	copy("$cacti_root_path/include/treeview/ftv2lastnode.gif", "$treeview_dir/ftv2lastnode.gif");
+-	copy("$cacti_root_path/include/treeview/ftv2mlastnode.gif", "$treeview_dir/ftv2mlastnode.gif");
+-	copy("$cacti_root_path/include/treeview/ftv2mnode.gif", "$treeview_dir/ftv2mnode.gif");
+-	copy("$cacti_root_path/include/treeview/ftv2node.gif", "$treeview_dir/ftv2node.gif");
+-	copy("$cacti_root_path/include/treeview/ftv2plastnode.gif", "$treeview_dir/ftv2plastnode.gif");
+-	copy("$cacti_root_path/include/treeview/ftv2pnode.gif", "$treeview_dir/ftv2pnode.gif");
+-	copy("$cacti_root_path/include/treeview/ftv2vertline.gif", "$treeview_dir/ftv2vertline.gif");
++	copy("$cacti_root_path/include/js/jquery/jquery.js", "$dir/js/jquery.js");
++	copy("$cacti_root_path/include/js/jquery/jquery.jstree.js", "$dir/js/jquery.jstree.js");
++	copy("$cacti_root_path/include/js/jquery/jquery.cookie.js", "$dir/js/jquery.cookie.js");
++
++	/* theme info for java scripts */
++	copy("$cacti_root_path/include/js/jquery/themes/default/style.css", "$dir/js/style.css");
++	copy("$cacti_root_path/include/js/jquery/themes/default/d.png", "$dir/js/d.png");
++	copy("$cacti_root_path/include/js/jquery/themes/default/d.gif", "$dir/js/d.gif");
++	copy("$cacti_root_path/include/js/jquery/themes/default/throbber.gif", "$dir/js/throbber.gif");
+ }
+ 
+ function get_host_description($host_id) {
+@@ -1738,8 +1764,9 @@ define("HTML_HEADER_TREE",
+ 	<meta http-equiv=refresh content='300'; url='index.html'>
+ 	<meta http-equiv=Pragma content=no-cache>
+ 	<meta http-equiv=cache-control content=no-cache>
+-	<script type=\"text/javascript\" src=\"./treeview/ua.js\"></script>
+-	<script type=\"text/javascript\" src=\"./treeview/ftiens4.js\"></script>
++	<script type=\"text/javascript\" src=\"./js/jquery.js\" language=\"javascript\"></script>
++	<script type=\"text/javascript\" src=\"./js/jquery.cookie.js\" language=\"javascript\"></script>
++	<script type=\"text/javascript\" src=\"./js/jquery.jstree.js\" language=\"javascript\"></script>
+ </head>
+ <body>
+ <table style='width:100%;height:100%;' cellspacing='0' cellpadding='0'>
+diff --git a/lib/html_tree.php b/lib/html_tree.php
+index 861c6cc..a5bd796 100644
+--- a/lib/html_tree.php
++++ b/lib/html_tree.php
+@@ -495,17 +495,9 @@ function grow_dhtml_trees() {
+ 	include_once($config["library_path"] . "/data_query.php");
+ 
+ 	?>
+-	<script type="text/javascript">
+-	<!--
+-	USETEXTLINKS = 1
+-	STARTALLOPEN = 0
+-	USEFRAMES = 0
+-	USEICONS = 0
+-	WRAPTEXT = 1
+-	PERSERVESTATE = 1
+-	HIGHLIGHT = 1
+ 	<?php
+ 	/* get current time */
++/* Probably not needed anymore as jstree uses jquery.cookies
+ 	list($micro,$seconds) = explode(" ", microtime());
+ 	$current_time = $seconds + $micro;
+ 	$expand_hosts = read_graph_config_option("expand_hosts");
+@@ -522,6 +514,8 @@ function grow_dhtml_trees() {
+ 			$dhtml_tree = $_SESSION['dhtml_tree'];
+ 		}
+ 	}
++*/
++	$dhtml_tree = create_dhtml_tree();
+ 
+ 	$total_tree_items = sizeof($dhtml_tree) - 1;
+ 
+@@ -529,8 +523,31 @@ function grow_dhtml_trees() {
+ 		print $dhtml_tree[$i];
+ 	}
+ 	?>
+-	//-->
+-	</script>
++<script type="text/javascript">
++$(function () {
++	$("#jtree")
++		.jstree({
++			"plugins" : ["ui","themes","html_data","cookies"],
++			"themes" : {"icons" : false,
++				"url" : "<?php echo  $config['url_path']; ?>include/js/jquery/themes/default/style.css"},
++			"cookies" : {
++				"save_opened" : "Cacti_jstree_open",
++				"save_selected" : "Cacti_jstree_select"
++				}
++			})
++
++		// Make sure that the nodes are actually used as links
++		// We need reselect to prevent endless loops
++		// https://groups.google.com/d/topic/jstree/j6XNq9hQdeA/discussion
++		.bind("reselect.jstree", function (e, data) { 
++			data.inst.get_container().bind("select_node.jstree", function (e, data) {
++				// data.rstl.obj is the object that was selected.
++				document.location.href = data.rslt.obj.children("a").attr("href");
++			});
++		});
++
++});
++</script>
+ 	<?php
+ }
+ 
+@@ -543,8 +560,9 @@ function create_dhtml_tree() {
+ 
+ 	$dhtml_tree[0] = $start;
+ 	$dhtml_tree[1] = read_graph_config_option("expand_hosts");
+-	$dhtml_tree[2] = "foldersTree = gFld(\"\", \"\")\n";
+-	$dhtml_tree[3] = "foldersTree.xID = \"root\"\n";
++	$dhtml_tree[2] = "\n<div id=\"jtree\">\n";
++	$dhtml_tree[3] = "\t<ul>\n";
++
+ 	$i = 3;
+ 
+ 	$tree_list = get_graph_tree_array();
+@@ -567,7 +585,6 @@ function create_dhtml_tree() {
+ 
+ 	if (sizeof($tree_list) > 0) {
+ 		foreach ($tree_list as $tree) {
+-			$i++;
+ 			$hierarchy = db_fetch_assoc("select
+ 				graph_tree_items.id,
+ 				graph_tree_items.title,
+@@ -583,21 +600,22 @@ function create_dhtml_tree() {
+ 				and graph_tree_items.local_graph_id = 0
+ 				order by graph_tree_items.order_key");
+ 
+-			$dhtml_tree[$i] = "ou0 = insFld(foldersTree, gFld(\"" . htmlspecialchars($tree["name"]) . "\", \"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"]) . "\"))\n";
+ 			$i++;
+-			$dhtml_tree[$i] = "ou0.xID = \"tree_" . $tree["id"] . "\"\n";
++			$dhtml_tree[$i] = "\t\t<li id=\"" . htmlspecialchars("tree_" . $tree["id"]) . "\"><a href=\"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"]) . "\">" . htmlspecialchars($tree["name"]) . "</a>\n";
+ 
+ 			if (sizeof($hierarchy) > 0) {
++				$i++;
++				$dhtml_tree[$i] = "\t\t\t<ul>\n";
+ 				foreach ($hierarchy as $leaf) {
+-					$i++;
+ 					$tier = tree_tier($leaf["order_key"]);
+ 
+ 					if ($leaf["host_id"] > 0) {
+-						$dhtml_tree[$i] = "ou" . ($tier) . " = insFld(ou" . abs(($tier-1)) . ", gFld(\"" . "Host: " . htmlspecialchars($leaf["hostname"]) . "\", \"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"] . "&leaf_id=" . $leaf["id"]) . "\"))\n";
+ 						$i++;
+-						$dhtml_tree[$i] = "ou" . ($tier) . ".xID = \"tree_" . $tree["id"] . "_leaf_" . $leaf["id"] . "\"\n";
++						$dhtml_tree[$i] = "\t\t\t\t<li id=\"" . htmlspecialchars("tree_" . $tree["id"] . "_leaf_" . $leaf["id"]) . "\"><a href=\"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"] . "&leaf_id=" . $leaf["id"]) . "\">Host: " . htmlspecialchars($leaf["hostname"]) . "</a>\n";
+ 
+ 						if (read_graph_config_option("expand_hosts") == "on") {
++							$i++;
++							$dhtml_tree[$i] = "\t\t\t\t\t<ul>\n";
+ 							if ($leaf["host_grouping_type"] == HOST_GROUPING_GRAPH_TEMPLATE) {
+ 								$graph_templates = db_fetch_assoc("select
+ 									graph_templates.id,
+@@ -612,9 +630,7 @@ function create_dhtml_tree() {
+ 								if (sizeof($graph_templates) > 0) {
+ 									foreach ($graph_templates as $graph_template) {
+ 										$i++;
+-										$dhtml_tree[$i] = "ou" . ($tier+1) . " = insFld(ou" . ($tier) . ", gFld(\" " . htmlspecialchars($graph_template["name"]) . "\", \"graph_view.php?action=tree&tree_id=" . $tree["id"] . "&leaf_id=" . $leaf["id"] . "&host_group_data=graph_template:" . $graph_template["id"] . "\"))\n";
+-										$i++;
+-										$dhtml_tree[$i] = "ou" . ($tier+1) . ".xID = \"tree_" . $tree["id"] . "_leaf_" . $leaf["id"] . "_hgd_gt_" . $graph_template["id"] . "\"\n";
++										$dhtml_tree[$i] = "\t\t\t\t\t\t<li id=\"" . htmlspecialchars("tree_" . $tree["id"] . "_leaf_" . $leaf["id"] . "_hgd_gt_" . $graph_template["id"]) . "\"><a href=\"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"] . "&leaf_id=" . $leaf["id"] . "&host_group_data=graph_template:" . $graph_template["id"]) . "\">" . htmlspecialchars($graph_template["name"]) . "</a></li>\n";
+ 									}
+ 								}
+ 							}else if ($leaf["host_grouping_type"] == HOST_GROUPING_DATA_QUERY_INDEX) {
+@@ -645,33 +661,48 @@ function create_dhtml_tree() {
+ 										if ((($data_query["id"] == 0) && ($non_template_graphs > 0)) ||
+ 											(($data_query["id"] > 0) && (sizeof($sort_field_data) > 0))) {
+ 											$i++;
+-											$dhtml_tree[$i] = "ou" . ($tier+1) . " = insFld(ou" . ($tier) . ", gFld(\" " . htmlspecialchars($data_query["name"]) . "\", \"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"] . "&leaf_id=" . $leaf["id"] . "&host_group_data=data_query:" . $data_query["id"]) . "\"))\n";
+-											$i++;
+-											$dhtml_tree[$i] = "ou" . ($tier+1) . ".xID = \"tree_" . $tree["id"] . "_leaf_" . $leaf["id"] . "_hgd_dq_" . $data_query["id"] . "\"\n";
+-
++											$dhtml_tree[$i] = "\t\t\t\t\t\t<li id=\"" . htmlspecialchars("tree_" . $tree["id"] . "_leaf_" . $leaf["id"] . "_hgd_dq_" . $data_query["id"]) . "\"><a href=\"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"] . "&leaf_id=" . $leaf["id"] . "&host_group_data=data_query:" . $data_query["id"]) . "\">" . htmlspecialchars($data_query["name"]) . "</a>\n";
+ 											if ($data_query["id"] > 0) {
++												$i++;
++												$dhtml_tree[$i] = "\t\t\t\t\t\t\t<ul>\n";
+ 												while (list($snmp_index, $sort_field_value) = each($sort_field_data)) {
+ 													$i++;
+-													$dhtml_tree[$i] = "ou" . ($tier+2) . " = insFld(ou" . ($tier+1) . ", gFld(\" " . htmlspecialchars($sort_field_value) . "\", \"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"] . "&leaf_id=" . $leaf["id"] . "&host_group_data=data_query_index:" . $data_query["id"] . ":" . urlencode($snmp_index)) . "\"))\n";
+-													$i++;
+-													$dhtml_tree[$i] = "ou" . ($tier+2) . ".xID = \"tree_" . $tree["id"] . "_leaf_" . $leaf["id"] . "_hgd_dqi" . $data_query["id"] . "_" . urlencode($snmp_index) . "\"\n";
++													$dhtml_tree[$i] = "\t\t\t\t\t\t\t\t<li id=\"" . htmlspecialchars("tree_" . $tree["id"] . "_leaf_" . $leaf["id"] . "_hgd_dqi" . $data_query["id"]) . "_" . urlencode($snmp_index) . "\"><a href=\"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"] . "&leaf_id=" . $leaf["id"] . "&host_group_data=data_query_index:" . $data_query["id"] . ":" . urlencode($snmp_index)) . "\">" . htmlspecialchars($sort_field_value) . "</a></li>\n";
+ 												}
++											$i++;
++											$dhtml_tree[$i] = "\t\t\t\t\t\t\t</ul>\n";
++											$i++;
++											$dhtml_tree[$i] = "\t\t\t\t\t\t</li>\n";
+ 											}
+ 										}
+ 									}
+ 								}
++							$i++;
++							$dhtml_tree[$i] = "\t\t\t\t\t\t</li>\n";
+ 							}
++						$i++;
++						$dhtml_tree[$i] = "\t\t\t\t\t</ul>\n";
+ 						}
++					$i++;
++					$dhtml_tree[$i] = "\t\t\t\t</li>\n";
+ 					}else{
+-						$dhtml_tree[$i] = "ou" . ($tier) . " = insFld(ou" . abs(($tier-1)) . ", gFld(\"" . htmlspecialchars($leaf["title"]) . "\", \"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"] . "&leaf_id=" . $leaf["id"]) . "\"))\n";
+ 						$i++;
+-						$dhtml_tree[$i] = "ou" . ($tier) . ".xID = \"tree_" . $tree["id"] . "_leaf_" . $leaf["id"] . "\"\n";
++						$dhtml_tree[$i] = "\t\t\t\t<li id=\"" . htmlspecialchars("tree_" . $tree["id"] . "_leaf_" . $leaf["id"]) . "\"><a href=\"" . htmlspecialchars("graph_view.php?action=tree&tree_id=" . $tree["id"] . "&leaf_id=" . $leaf["id"]) . "\">" . htmlspecialchars($leaf["title"]) . "</a></li>\n";
+ 					}
+ 				}
++				$i++;
++				$dhtml_tree[$i] = "\t\t\t</ul>\n";
+ 			}
++			$i++;
++			$dhtml_tree[$i] = "\t\t</li>\n";
+ 		}
+ 	}
+ 
++	$i++;
++	$dhtml_tree[$i] = "\t</ul>\n";
++	$i++;
++	$dhtml_tree[$i] = "</div>\n";
++
+ 	return $dhtml_tree;
+ }
+ 
+@@ -758,14 +789,6 @@ function grow_right_pane_tree($tree_id, $leaf_id, $host_group_data) {
+ 		}
+ 	}
+ 
+-	print "<script type=\"text/javascript\">\n";
+-	print "<!--\n";
+-	print "myNode = findObj(\"$nodeid\")\n";
+-	print "myNode.forceOpeningOfAncestorFolders();\n";
+-	print "highlightObjLink(myNode)\n";
+-	print "//-->\n";
+-	print "</script>";
+-
+ 	/* ================= input validation ================= */
+ 	input_validate_input_number(get_request_var_post("graphs"));
+ 	input_validate_input_number(get_request_var_post("page"));
+-- 
+1.7.10.4
+
diff -Nru cacti-0.8.8a/debian/patches/series cacti-0.8.8a+dfsg/debian/patches/series
--- cacti-0.8.8a/debian/patches/series	2012-05-19 07:58:51.000000000 +0200
+++ cacti-0.8.8a+dfsg/debian/patches/series	2012-12-10 20:38:19.000000000 +0100
@@ -6,3 +6,5 @@
 10_566609_suhosin.memory_limit.patch
 cacti.sql_ensure_cron_works.patch
 cacti.sql_drop_tables_to_begin.patch
+replace_treeview_by_jquery.jstree.patch
+use_jquery_for_debian.patch
diff -Nru cacti-0.8.8a/debian/patches/use_jquery_for_debian.patch cacti-0.8.8a+dfsg/debian/patches/use_jquery_for_debian.patch
--- cacti-0.8.8a/debian/patches/use_jquery_for_debian.patch	1970-01-01 01:00:00.000000000 +0100
+++ cacti-0.8.8a+dfsg/debian/patches/use_jquery_for_debian.patch	2012-12-10 20:50:56.000000000 +0100
@@ -0,0 +1,23 @@
+Description: Using jquery.jstree with cacti should use jquery and jquery-cookie from
+ existing packages.
+ .
+ This patch replaces embedded paths by system locations of jquery(|.cookie)
+Bug-Debian: http://bugs.debian.org/679980
+Forwarded: not needed
+Author: Paul Gevers <[email-masked]>
+Date: Mon, 10 Dec 2012 20:50:00 +0100
+
+
+--- a/include/top_graph_header.php
++++ b/include/top_graph_header.php
+@@ -84,8 +84,8 @@
+ 	<link href="<?php echo $config['url_path']; ?>include/main.css" type="text/css" rel="stylesheet">
+ 	<link href="<?php echo $config['url_path']; ?>images/favicon.ico" rel="shortcut icon"/>
+ 	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/layout.js"></script>
+-	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/js/jquery/jquery.js" language="javascript"></script>
+-	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/js/jquery/jquery.cookie.js" language="javascript"></script>
++	<script type="text/javascript" src="/javascript/jquery/jquery.js" language="javascript"></script>
++	<script type="text/javascript" src="/javascript/jquery-cookie/jquery.cookie.js" language="javascript"></script>
+ 	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/js/jquery/jquery.jstree.js"></script>
+ 	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/jscalendar/calendar.js"></script>
+ 	<script type="text/javascript" src="<?php echo $config['url_path']; ?>include/jscalendar/lang/calendar-en.js"></script>
diff -Nru cacti-0.8.8a/debian/README.Debian cacti-0.8.8a+dfsg/debian/README.Debian
--- cacti-0.8.8a/debian/README.Debian	2012-05-08 21:18:58.000000000 +0200
+++ cacti-0.8.8a+dfsg/debian/README.Debian	2012-09-15 07:35:11.000000000 +0200
@@ -8,13 +8,12 @@
 Fri, 06 Jan 2006 08:07:46 +0100
 
 edited by Paul Gevers <[email-masked]>
-Tue, 08 May 2012 21:18:38 +0200
+Wed, 01 Aug 2012 22:13:57 +0200
 ----------------
 
 * plugin architecture
   Since release 0.8.8 Cacti supports the plugin architecture out of the
-  box. To use it, follow the discriptions from the Cacti website, but
-  put the plugins you want to use in /usr/local/share/cacti/plugins/
+  box. To use it, first read README.Plugins
 
 * Debian is one of the distribution that tries to get php5-suhosin
   installed by default if you are running php5. However due to bug 668157
diff -Nru cacti-0.8.8a/debian/README.Plugins cacti-0.8.8a+dfsg/debian/README.Plugins
--- cacti-0.8.8a/debian/README.Plugins	1970-01-01 01:00:00.000000000 +0100
+++ cacti-0.8.8a+dfsg/debian/README.Plugins	2012-09-15 07:35:11.000000000 +0200
@@ -0,0 +1,18 @@
+If you read this and care about keeping your system maintainable, please change
+the layout of the plugins structure of cacti. Due to the way a lot of plug-ins
+are written (details in bug #681558) in combination with Debian policy, I can
+not fix this in the package.
+
+* Create a directory /usr/local/share/cacti/plugins:
+  mkdir /usr/local/share/cacti/plugins
+* Move all content of /usr/share/cacti/site/plugins to
+  /usr/local/share/cacti/plugins
+  mv /usr/share/cacti/site/plugins/* /usr/local/share/cacti/plugins/
+* Remove the empty /usr/share/cacti/site/plugins directory
+  rmdir /usr/share/cacti/site/plugins
+* Create the following symlinks:
+  ln -s /usr/local/share/cacti/plugins /usr/share/cacti/site/plugins
+  ln -s /usr/share/cacti/site/include /usr/local/share/cacti/include
+  ln -s /usr/share/cacti/site/lib /usr/local/share/cacti/lib
+
+ -- Paul Gevers <[email-masked]>  Wed, 01 Aug 2012 22:32:32 +0200
diff -Nru cacti-0.8.8a/debian/source/include-binaries cacti-0.8.8a+dfsg/debian/source/include-binaries
--- cacti-0.8.8a/debian/source/include-binaries	1970-01-01 01:00:00.000000000 +0100
+++ cacti-0.8.8a+dfsg/debian/source/include-binaries	2012-12-11 20:31:48.000000000 +0100
@@ -0,0 +1,3 @@
+debian/js/jquery/themes/default/throbber.gif
+debian/js/jquery/themes/default/d.gif
+debian/js/jquery/themes/default/d.png
diff -Nru cacti-0.8.8a/include/treeview/ftiens4_export.js cacti-0.8.8a+dfsg/include/treeview/ftiens4_export.js
--- cacti-0.8.8a/include/treeview/ftiens4_export.js	2012-04-04 03:49:40.000000000 +0200
+++ cacti-0.8.8a+dfsg/include/treeview/ftiens4_export.js	1970-01-01 01:00:00.000000000 +0100
@@ -1,1126 +0,0 @@
-//****************************************************************
-// Keep this copyright notice:
-// This copy of the script is the property of the owner of the
-// particular web site you were visiting.
-// Do not download the script's files from there.
-// For a free download and full instructions go to:
-// http://www.treeview.net
-//****************************************************************
-
-
-// Log of changes:
-//
-//      12 May 03 - Support for Safari Beta 3
-//      01 Mar 03 - VERSION 4.3 - Support for checkboxes
-//      21 Feb 03 - Added support for Opera 7
-//      22 Sep 02 - Added maySelect member for node-by-node control
-//                  of selection and highlight
-//      21 Sep 02 - Cookie values are now separated by cookieCutter
-//      12 Sep 02 - VERSION 4.2 - Can highlight Selected Nodes and
-//                  can preserve state through external (DB) IDs
-//      29 Aug 02 - Fine tune 'supportDeferral' for IE4 and IE Mac
-//      25 Aug 02 - Fixes: STARTALLOPEN, and multi-page frameless
-//      09 Aug 02 - Fix repeated folder on Mozilla 1.x
-//      31 Jul 02 - VERSION 4.1 - Dramatic speed increase for trees
-//      with hundreds or thousands of nodes; changes to the control
-//      flags of the gLnk function
-//      18 Jul 02 - Changes in pre-load images function
-//      13 Jun 02 - Add ICONPATH var to allow for gif subdir
-//      20 Apr 02 - Improve support for frame-less layout
-//      07 Apr 02 - Minor changes to support server-side dynamic feeding
-//                  (example: FavoritesManagerASP)
-
-
-// Definition of class Folder
-// *****************************************************************
-function Folder(folderDescription, hreference) //constructor
-{
-  //constant data
-  this.desc = folderDescription;
-  this.hreference = hreference;
-  this.id = -1;
-  this.navObj = 0;
-  this.iconImg = 0;
-  this.nodeImg = 0;
-  this.isLastNode = 0;
-  this.iconSrc = ICONPATH + "";
-  this.iconSrcClosed = ICONPATH + "";
-  this.children = new Array;
-  this.nChildren = 0;
-  this.level = 0;
-  this.leftSideCoded = "";
-  this.isLastNode=false;
-  this.parentObj = null;
-  this.maySelect=true;
-  this.prependHTML = ""
-
-  //dynamic data
-  this.isOpen = false
-  this.isLastOpenedFolder = false
-  this.isRendered = 0
-
-  //methods
-  this.initialize = initializeFolder
-  this.setState = setStateFolder
-  this.addChild = addChild
-  this.createIndex = createEntryIndex
-  this.escondeBlock = escondeBlock
-  this.esconde = escondeFolder
-  this.folderMstr = folderMstr
-  this.renderOb = drawFolder
-  this.totalHeight = totalHeight
-  this.subEntries = folderSubEntries
-  this.linkHTML = linkFolderHTML
-  this.blockStartHTML = blockStartHTML
-  this.blockEndHTML = blockEndHTML
-  this.nodeImageSrc = nodeImageSrc
-  this.iconImageSrc = iconImageSrc
-  this.getID = getID
-  this.forceOpeningOfAncestorFolders = forceOpeningOfAncestorFolders
-}
-
-function initializeFolder(level, lastNode, leftSide)
-{
-  var j=0
-  var i=0
-  nc = this.nChildren
-
-  this.createIndex()
-  this.level = level
-  this.leftSideCoded = leftSide
-
-  if (browserVersion == 0 || STARTALLOPEN==1)
-    this.isOpen=true;
-
-  if (level>0)
-    if (lastNode) //the last child in the children array
-		leftSide = leftSide + "0"
-	else
-		leftSide = leftSide + "1"
-
-  this.isLastNode = lastNode
-
-  if (nc > 0)
-  {
-    level = level + 1
-    for (i=0 ; i < this.nChildren; i++)
-    {
-      if (i == this.nChildren-1)
-        this.children[i].initialize(level, 1, leftSide)
-      else
-        this.children[i].initialize(level, 0, leftSide)
-    }
-  }
-}
-
-function drawFolder(insertAtObj)
-{
-  var nodeName = ""
-  var auxEv = ""
-  var docW = ""
-
-  var leftSide = leftSideHTML(this.leftSideCoded)
-
-  if (browserVersion > 0)
-    auxEv = "<a href='javascript:clickOnNode(\""+this.getID()+"\")'>"
-  else
-    auxEv = "<a>"
-
-  nodeName = this.nodeImageSrc()
-
-  if (this.level>0)
-    if (this.isLastNode) //the last child in the children array
-	    leftSide = leftSide + "<td valign=top>" + auxEv + "<img name='nodeIcon" + this.id + "' id='nodeIcon" + this.id + "' src='" + nodeName + "' width=16 height=22 border=0></a></td>"
-    else
-      leftSide = leftSide + "<td valign=top style='background-image:" + ICONPATH + "ftv2vertline.gif;'>" + auxEv + "<img name='nodeIcon" + this.id + "' id='nodeIcon" + this.id + "' src='" + nodeName + "' width=16 height=22 border=0></a></td>"
-
-  this.isRendered = 1
-
-  if (browserVersion == 2) {
-    if (!doc.yPos)
-      doc.yPos=20
-  }
-
-  docW = this.blockStartHTML("folder");
-
-  docW = docW + "<tr>" + leftSide + "<td valign=top>";
-  if (USEICONS)
-  {
-    docW = docW + this.linkHTML(false)
-    docW = docW + "<img id='folderIcon" + this.id + "' name='folderIcon" + this.id + "' src='" + this.iconImageSrc() + "' border=0></a>"
-  }
-  else
-  {
-	  if (this.prependHTML == "")
-        docW = docW + "<img src=" + ICONPATH + "ftv2blank.gif height=2 width=2>"
-  }
-  if (WRAPTEXT)
-	  docW = docW + "</td>"+this.prependHTML+"<td valign=middle width=100%>"
-  else
-	  docW = docW + "</td>"+this.prependHTML+"<td valign=middle nowrap width=100%>"
-  if (USETEXTLINKS)
-  {
-    docW = docW + this.linkHTML(true)
-    docW = docW + this.desc + "</a>"
-  }
-  else
-    docW = docW + this.desc
-  docW = docW + "</td>"
-
-  docW = docW + this.blockEndHTML()
-
-  if (insertAtObj == null)
-  {
-	  if (supportsDeferral) {
-		  doc.write("<div id=domRoot></div>") //transition between regular flow HTML, and node-insert DOM DHTML
-		  insertAtObj = getElById("domRoot")
-		  insertAtObj.insertAdjacentHTML("beforeEnd", docW)
-	  }
-	  else
-		  doc.write(docW)
-  }
-  else
-  {
-      insertAtObj.insertAdjacentHTML("afterEnd", docW)
-  }
-
-  if (browserVersion == 2)
-  {
-    this.navObj = doc.layers["folder"+this.id]
-    if (USEICONS)
-      this.iconImg = this.navObj.document.images["folderIcon"+this.id]
-    this.nodeImg = this.navObj.document.images["nodeIcon"+this.id]
-    doc.yPos=doc.yPos+this.navObj.clip.height
-  }
-  else if (browserVersion != 0)
-  {
-    this.navObj = getElById("folder"+this.id)
-    if (USEICONS)
-      this.iconImg = getElById("folderIcon"+this.id)
-    this.nodeImg = getElById("nodeIcon"+this.id)
-  }
-}
-
-function setStateFolder(isOpen)
-{
-  var subEntries
-  var totalHeight
-  var fIt = 0
-  var i=0
-  var currentOpen
-
-  if (isOpen == this.isOpen)
-    return
-
-  if (browserVersion == 2)
-  {
-    totalHeight = 0
-    for (i=0; i < this.nChildren; i++)
-      totalHeight = totalHeight + this.children[i].navObj.clip.height
-      subEntries = this.subEntries()
-    if (this.isOpen)
-      totalHeight = 0 - totalHeight
-    for (fIt = this.id + subEntries + 1; fIt < nEntries; fIt++)
-      indexOfEntries[fIt].navObj.moveBy(0, totalHeight)
-  }
-  this.isOpen = isOpen;
-
-  if (this.getID()!=foldersTree.getID() && PERSERVESTATE && !this.isOpen) //closing
-  {
-     currentOpen = GetCookie("clickedFolder")
-     if (currentOpen != null) {
-         currentOpen = currentOpen.replace(this.getID()+cookieCutter, "")
-         SetCookie("clickedFolder", currentOpen)
-     }
-  }
-
-  if (!this.isOpen && this.isLastOpenedfolder)
-  {
-		lastOpenedFolder = null;
-		this.isLastOpenedfolder = false;
-  }
-  propagateChangesInState(this)
-}
-
-function propagateChangesInState(folder)
-{
-  var i=0
-
-  //Change icon
-  if (folder.nChildren > 0 && folder.level>0)  //otherwise the one given at render stays
-    folder.nodeImg.src = folder.nodeImageSrc()
-
-  //Change node
-  if (USEICONS)
-    folder.iconImg.src = folder.iconImageSrc()
-
-  //Propagate changes
-  for (i=folder.nChildren-1; i>=0; i--)
-    if (folder.isOpen)
-      folder.children[i].folderMstr(folder.navObj)
-    else
-  	  folder.children[i].esconde()
-}
-
-function escondeFolder()
-{
-  this.escondeBlock()
-
-  this.setState(0)
-}
-
-function linkFolderHTML(isTextLink)
-{
-  var docW = "";
-
-  if (this.hreference)
-  {
-	if (USEFRAMES)
-	  docW = docW + "<a href='" + this.hreference + "' TARGET=\"basefrm\" "
-	else
-	  docW = docW + "<a href='" + this.hreference + "' TARGET=_self "
-
-    if (isTextLink) {
-        docW += "id=\"itemTextLink"+this.id+"\" ";
-    }
-
-    if (browserVersion > 0)
-      docW = docW + "onClick='javascript:clickOnFolder(\""+this.getID()+"\")'"
-
-    docW = docW + ">"
-  }
-  else
-    docW = docW + "<a>"
-
-  if (this.hreference == '')
-    docW = '';
-
-  return docW;
-}
-
-function addChild(childNode)
-{
-  this.children[this.nChildren] = childNode
-  childNode.parentObj = this
-  this.nChildren++
-  return childNode
-}
-
-function folderSubEntries()
-{
-  var i = 0
-  var se = this.nChildren
-
-  for (i=0; i < this.nChildren; i++){
-    if (this.children[i].children) //is a folder
-      se = se + this.children[i].subEntries()
-  }
-
-  return se
-}
-
-function nodeImageSrc() {
-  var srcStr = "";
-
-  if (this.isLastNode) //the last child in the children array
-  {
-    if (this.nChildren == 0)
-      srcStr = ICONPATH + "ftv2lastnode.gif"
-    else
-      if (this.isOpen)
-        srcStr = ICONPATH + "ftv2mlastnode.gif"
-      else
-        srcStr = ICONPATH + "ftv2plastnode.gif"
-  }
-  else
-  {
-    if (this.nChildren == 0)
-      srcStr = ICONPATH + "ftv2node.gif"
-    else
-      if (this.isOpen)
-        srcStr = ICONPATH + "ftv2mnode.gif"
-      else
-        srcStr = ICONPATH + "ftv2pnode.gif"
-  }
-  return srcStr;
-}
-
-function iconImageSrc() {
-  if (this.isOpen)
-    return(this.iconSrc)
-  else
-    return(this.iconSrcClosed)
-}
-
-// Definition of class Item (a document or link inside a Folder)
-// *************************************************************
-
-function Item(itemDescription, itemLink, target) // Constructor
-{
-  // constant data
-  this.desc = itemDescription
-  this.link = itemLink
-  this.id = -1 //initialized in initalize()
-  this.navObj = 0 //initialized in render()
-  this.iconImg = 0 //initialized in render()
-  this.iconSrc = ICONPATH + "ftv2doc.gif"
-  this.isRendered = 0
-  this.isLastNode = false
-  this.level = 0
-  this.leftSideCoded = ""
-  this.nChildren = 0
-  this.target = target
-  this.parentObj = null
-  this.maySelect=true
-  this.prependHTML = ""
-
-  // methods
-  this.initialize = initializeItem
-  this.createIndex = createEntryIndex
-  this.escondeBlock = escondeBlock
-  this.esconde = escondeBlock
-  this.folderMstr = folderMstr
-  this.renderOb = drawItem
-  this.totalHeight = totalHeight
-  this.blockStartHTML = blockStartHTML
-  this.blockEndHTML = blockEndHTML
-  this.getID = getID
-  this.forceOpeningOfAncestorFolders = forceOpeningOfAncestorFolders
-}
-
-function initializeItem(level, lastNode, leftSide)
-{
-  this.createIndex()
-  this.level = level
-  this.leftSideCoded = leftSide
-  this.isLastNode = lastNode
-}
-
-function drawItem(insertAtObj)
-{
-  var leftSide = leftSideHTML(this.leftSideCoded)
-  var docW = ""
-
-  var fullLink = "href=\""+this.link+"\" target=\""+this.target+"\" onClick=\"clickOnLink('"+this.getID()+"\', '"+this.link+"','"+this.target+"');return false;\"";
-  this.isRendered = 1
-
-  if (this.level>0)
-    if (this.isLastNode) //the last 'brother' in the children array
-    {
-      leftSide = leftSide + "<td valign=top><img src='" + ICONPATH + "ftv2lastnode.gif' width=16 height=22></td>"
-    }
-    else
-    {
-      leftSide = leftSide + "<td valign=top style='background-image:" + ICONPATH + "ftv2vertline.gif;'><img src='" + ICONPATH + "ftv2node.gif' width=16 height=22></td>"
-    }
-
-  docW = docW + this.blockStartHTML("item")
-
-  docW = docW + "<tr>" + leftSide + "<td valign=top>"
-  if (USEICONS)
-      docW = docW + "<a " + fullLink  + " id=\"itemIconLink"+this.id+"\">" + "<img id='itemIcon"+this.id+"' " + "src='"+this.iconSrc+"' border=0>" + "</a>"
-  else
-	  if (this.prependHTML == "")
-        docW = docW + "<img src=" + ICONPATH + "ftv2blank.gif height=2 width=3>"
-
-  if (WRAPTEXT)
-    docW = docW + "</td>"+this.prependHTML+"<td valign=middle width=100%>"
-  else
-    docW = docW + "</td>"+this.prependHTML+"<td valign=middle nowrap width=100%>"
-
-  if (USETEXTLINKS)
-    docW = docW + "<a " + fullLink + " id=\"itemTextLink"+this.id+"\">" + this.desc + "</a>"
-  else
-    docW = docW + this.desc
-
-  docW = docW + "</td>"
-
-  docW = docW + this.blockEndHTML()
-
-  if (insertAtObj == null)
-  {
-	  doc.write(docW)
-  }
-  else
-  {
-      insertAtObj.insertAdjacentHTML("afterEnd", docW)
-  }
-
-  if (browserVersion == 2) {
-    this.navObj = doc.layers["item"+this.id]
-    if (USEICONS)
-      this.iconImg = this.navObj.document.images["itemIcon"+this.id]
-    doc.yPos=doc.yPos+this.navObj.clip.height
-  } else if (browserVersion != 0) {
-    this.navObj = getElById("item"+this.id)
-    if (USEICONS)
-      this.iconImg = getElById("itemIcon"+this.id)
-  }
-}
-
-
-// Methods common to both objects (pseudo-inheritance)
-// ********************************************************
-
-function forceOpeningOfAncestorFolders() {
-  if (this.parentObj == null || this.parentObj.isOpen)
-    return
-  else {
-    this.parentObj.forceOpeningOfAncestorFolders()
-    clickOnNodeObj(this.parentObj)
-  }
-}
-
-function escondeBlock()
-{
-  if (browserVersion == 1 || browserVersion == 3) {
-    if (this.navObj.style.display == "none")
-      return
-    this.navObj.style.display = "none"
-  } else {
-    if (this.navObj.visibility == "hidden")
-      return
-    this.navObj.visibility = "hidden"
-  }
-}
-
-function folderMstr(domObj)
-{
-  if (browserVersion == 1 || browserVersion == 3) {
-    if (t==-1)
-      return
-    var str = new String(doc.links[t])
-    if (str.slice(14,16) != "em")
-      return
-  }
-
-  if (!this.isRendered)
-     this.renderOb(domObj)
-  else
-    if (browserVersion == 1 || browserVersion == 3)
-      this.navObj.style.display = "block"
-    else
-      this.navObj.visibility = "show"
-}
-
-function blockStartHTML(idprefix) {
-  var idParam = "id='" + idprefix + this.id + "'"
-  var docW = ""
-
-  if (browserVersion == 2)
-    docW = "<layer "+ idParam + " top=" + doc.yPos + " visibility=show>"
-  else if (browserVersion != 0)
-    docW = "<div " + idParam + " style='display:block; position:block;'>"
-
-  docW = docW + "<table border=0 cellspacing=0 cellpadding=0 width=100% >"
-
-  return docW
-}
-
-function blockEndHTML() {
-  var docW = ""
-
-  docW = "</table>"
-
-  if (browserVersion == 2)
-    docW = docW + "</layer>"
-  else if (browserVersion != 0)
-    docW = docW + "</div>"
-
-  return docW
-}
-
-function createEntryIndex()
-{
-  this.id = nEntries
-  indexOfEntries[nEntries] = this
-  nEntries++
-}
-
-// total height of subEntries open
-function totalHeight() //used with browserVersion == 2
-{
-  var h = this.navObj.clip.height
-  var i = 0
-
-  if (this.isOpen) //is a folder and _is_ open
-    for (i=0 ; i < this.nChildren; i++)
-      h = h + this.children[i].totalHeight()
-
-  return h
-}
-
-
-function leftSideHTML(leftSideCoded) {
-	var i;
-	var retStr = "";
-
-	for (i=0; i<leftSideCoded.length; i++)
-	{
-		if (leftSideCoded.charAt(i) == "1")
-		{
-			retStr = retStr + "<td valign=top style='background-image:" + ICONPATH + "ftv2vertline.gif;'><img src='" + ICONPATH + "ftv2vertline.gif' width=16 height=22></td>"
-		}
-		if (leftSideCoded.charAt(i) == "0")
-		{
-			retStr = retStr + "<td valign=top><img src='" + ICONPATH + "ftv2blank.gif' width=16 height=22></td>"
-		}
-	}
-	return retStr
-}
-
-function getID()
-{
-  //define a .xID in all nodes (folders and items) if you want to PERVESTATE that
-  //work when the tree changes. The value eXternal value must be unique for each
-  //node and must node change when other nodes are added or removed
-  //The value may be numeric or string, but cannot have the same char used in cookieCutter
-  if (typeof this.xID != "undefined")
-    return this.xID
-  else
-    return this.id
-}
-
-
-// Events
-// *********************************************************
-
-function clickOnFolder(folderId)
-{
-    var clicked = findObj(folderId)
-
-    if (!clicked.isOpen) {
-      clickOnNodeObj(clicked)
-    }
-
-    if (lastOpenedFolder != null && lastOpenedFolder != folderId)
-      clickOnNode(lastOpenedFolder); //sets lastOpenedFolder to null
-
-    if (clicked.nChildren==0) {
-      lastOpenedFolder = folderId;
-      clicked.isLastOpenedfolder = true
-    }
-
-    if (isLinked(clicked.hreference)) {
-        //highlightObjLink(clicked);
-    }
-}
-
-function clickOnNode(folderId)
-{
-  clickOnNodeObj(findObj(folderId))
-}
-
-function clickOnNodeObj(folderObj)
-{
-  var state = 0
-  var currentOpen
-
-  state = folderObj.isOpen
-  folderObj.setState(!state) //open<->close
-
-  if (folderObj.id!=foldersTree.id && PERSERVESTATE)
-  {
-    currentOpen = GetCookie("clickedFolder")
-    if (currentOpen == null)
-      currentOpen = ""
-
-    if (!folderObj.isOpen) //closing
-    {
-      currentOpen = currentOpen.replace(folderObj.getID()+cookieCutter, "")
-      SetCookie("clickedFolder", currentOpen)
-    }
-    else
-      SetCookie("clickedFolder", currentOpen+folderObj.getID()+cookieCutter)
-  }
-}
-
-function clickOnLink(clickedId, target, windowName) {
-    //highlightObjLink(findObj(clickedId));
-    if (isLinked(target)) {
-        window.open(target,windowName);
-    }
-}
-
-function ld  ()
-{
-	return document.links.length-1
-}
-
-
-// Auxiliary Functions
-// *******************
-
-function findObj(id)
-{
-  var i=0;
-  var nodeObj;
-  if (typeof foldersTree.xID != "undefined") {
-    nodeObj = indexOfEntries[i];
-    for(i=0;i<nEntries&&indexOfEntries[i].xID!=id;i++) //may need optimization
-      ;
-    id = i
-  }
-  if (id >= nEntries)
-    return null; //example: node removed in DB
-  else
-    return indexOfEntries[id];
-}
-
-function isLinked(hrefText) {
-    var result = true;
-    result = (result && hrefText !=null);
-    result = (result && hrefText != '');
-    result = (result && hrefText.indexOf('undefined') < 0);
-    result = (result && hrefText.indexOf('parent.op') < 0);
-    return result;
-}
-
-// Do highlighting by changing background and foreg. colors of folder or doc text
-function highlightObjLink(nodeObj) {
-  if (!HIGHLIGHT || nodeObj==null || nodeObj.maySelect==false) {//node deleted in DB
-    return;
-  }
-
-  if (browserVersion == 1 || browserVersion == 3) {
-    var clickedDOMObj = getElById('itemTextLink'+nodeObj.id);
-    if (clickedDOMObj != null) {
-        if (lastClicked != null) {
-            var prevClickedDOMObj = getElById('itemTextLink'+lastClicked.id);
-            prevClickedDOMObj.style.color=lastClickedColor;
-            prevClickedDOMObj.style.backgroundColor=lastClickedBgColor;
-        }
-
-        lastClickedColor    = clickedDOMObj.style.color;
-        lastClickedBgColor  = clickedDOMObj.style.backgroundColor;
-        clickedDOMObj.style.color=HIGHLIGHT_COLOR;
-        clickedDOMObj.style.backgroundColor=HIGHLIGHT_BG;
-    }
-  }
-  lastClicked = nodeObj;
-  if (PERSERVESTATE)
-    SetCookie('highlightedTreeviewLink', nodeObj.getID());
-}
-
-function gFld(description, hreference)
-{
-  folder = new Folder(description, hreference);
-  return folder;
-}
-
-function gLnk(optionFlags, description, linkData)
-{
-  var fullLink = "";
-  var targetFlag = "";
-  var target = "";
-  var protocolFlag = "";
-  var protocol = "";
-
-  if (optionFlags>=0) //is numeric (old style) or empty (error)
-  {
-    return oldGLnk(optionFlags, description, linkData)
-  }
-
-  targetFlag = optionFlags.charAt(0)
-  if (targetFlag=="B")
-    target = "_blank"
-  if (targetFlag=="P")
-    target = "_parent"
-  if (targetFlag=="R")
-    target = "basefrm"
-  if (targetFlag=="S")
-    target = "_self"
-  if (targetFlag=="T")
-    target = "_self"
-
-  if (optionFlags.length > 1) {
-    protocolFlag = optionFlags.charAt(1)
-    if (protocolFlag=="h")
-      protocol = "http://"
-    if (protocolFlag=="s")
-      protocol = "https://"
-    if (protocolFlag=="f")
-      protocol = "ftp://"
-    if (protocolFlag=="m")
-      protocol = "mailto:"
-  }
-
-  fullLink = "'" + protocol + linkData + "' target=" + target
-
-  linkItem = new Item(description, protocol+linkData, target)
-  return linkItem
-}
-
-//Function created Aug 1, 2002 for backwards compatibility purposes
-function oldGLnk(target, description, linkData)
-{
-  var fullLink = "";
-  //Backwards compatibility code
-  if (USEFRAMES)
-  {
-	  if (target==0)
-	  {
-		fullLink = "'"+linkData+"' target=\"basefrm\""
-	  }
-	  else
-	  {
-		if (target==1)
-		   fullLink = "'http://"+linkData+"' target=_blank"
-		else
-		   if (target==2)
-			  fullLink = "'http://"+linkData+"' target=\"basefrm\""
-		   else
-			  fullLink = linkData+" target=\"_top\""
-	  }
-  }
-  else
-  {
-	  if (target==0)
-	  {
-		fullLink = "'"+linkData+"' target=_top"
-	  }
-	  else
-	  {
-		if (target==1)
-		   fullLink = "'http://"+linkData+"' target=_blank"
-		else
-		   fullLink = "'http://"+linkData+"' target=_top"
-	  }
-  }
-
-  linkItem = new Item(description, fullLink)
-  return linkItem
-}
-
-function insFld(parentFolder, childFolder)
-{
-  return parentFolder.addChild(childFolder)
-}
-
-function insDoc(parentFolder, document)
-{
-  return parentFolder.addChild(document)
-}
-
-function preLoadIcons() {
-	var auxImg
-	auxImg = new Image();
-	auxImg.src = ICONPATH + "ftv2vertline.gif";
-	auxImg.src = ICONPATH + "ftv2mlastnode.gif";
-	auxImg.src = ICONPATH + "ftv2mnode.gif";
-	auxImg.src = ICONPATH + "ftv2plastnode.gif";
-	auxImg.src = ICONPATH + "ftv2pnode.gif";
-	auxImg.src = ICONPATH + "ftv2blank.gif";
-	auxImg.src = ICONPATH + "ftv2lastnode.gif";
-	auxImg.src = ICONPATH + "ftv2node.gif";
-}
-
-//Open some folders for initial layout, if necessary
-function setInitialLayout() {
-  if (browserVersion > 0 && !STARTALLOPEN)
-    clickOnNodeObj(foldersTree);
-
-  if (!STARTALLOPEN && (browserVersion > 0) && PERSERVESTATE)
-		PersistentFolderOpening();
-}
-
-//Used with NS4 and STARTALLOPEN
-function renderAllTree(nodeObj, parent) {
-  var i=0;
-  nodeObj.renderOb(parent)
-  if (supportsDeferral)
-    for (i=nodeObj.nChildren-1; i>=0; i--)
-      renderAllTree(nodeObj.children[i], nodeObj.navObj)
-  else
-    for (i=0 ; i < nodeObj.nChildren; i++)
-      renderAllTree(nodeObj.children[i], null)
-}
-
-function hideWholeTree(nodeObj, hideThisOne, nodeObjMove) {
-  var i=0;
-  var heightContained=0;
-  var childrenMove=nodeObjMove;
-
-  if (hideThisOne)
-    nodeObj.escondeBlock()
-
-  if (browserVersion == 2)
-    nodeObj.navObj.moveBy(0, 0-nodeObjMove)
-
-  for (i=0 ; i < nodeObj.nChildren; i++) {
-    heightContainedInChild = hideWholeTree(nodeObj.children[i], true, childrenMove)
-    if (browserVersion == 2) {
-      heightContained = heightContained + heightContainedInChild + nodeObj.children[i].navObj.clip.height
-      childrenMove = childrenMove + heightContainedInChild
-	}
-  }
-
-  return heightContained;
-}
-
-
-// Simulating inserAdjacentHTML on NS6
-// Code by [email-masked]
-// ******************************************
-
-if(typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentElement){
-	HTMLElement.prototype.insertAdjacentElement = function (where,parsedNode)
-	{
-		switch (where){
-		case 'beforeBegin':
-			this.parentNode.insertBefore(parsedNode,this)
-			break;
-		case 'afterBegin':
-			this.insertBefore(parsedNode,this.firstChild);
-			break;
-		case 'beforeEnd':
-			this.appendChild(parsedNode);
-			break;
-		case 'afterEnd':
-			if (this.nextSibling)
-				this.parentNode.insertBefore(parsedNode,this.nextSibling);
-			else this.parentNode.appendChild(parsedNode);
-			break;
-		}
-	}
-
-	HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr)
-	{
-		var r = this.ownerDocument.createRange();
-		r.setStartBefore(this);
-		var parsedHTML = r.createContextualFragment(htmlStr);
-		this.insertAdjacentElement(where,parsedHTML)
-	}
-}
-
-function getElById(idVal) {
-  if (document.getElementById != null)
-    return document.getElementById(idVal)
-  if (document.all != null)
-    return document.all[idVal]
-
-  alert("Problem getting element by id")
-  return null
-}
-
-
-// Functions for cookies
-// Note: THESE FUNCTIONS ARE OPTIONAL. No cookies are used unless
-// the PERSERVESTATE variable is set to 1 (default 0)
-// The separator currently in use is ^ (chr 94)
-// ***********************************************************
-
-function PersistentFolderOpening()
-{
-  var stateInCookie;
-  var fldStr=""
-  var fldArr
-  var fldPos=0
-  var id
-  var nodeObj
-  stateInCookie = GetCookie("clickedFolder");
-  SetCookie('clickedFolder', "") //at the end of function it will be back, minus null cases
-
-  if(stateInCookie!=null)
-  {
-    fldArr = stateInCookie.split(cookieCutter)
-    for (fldPos=0; fldPos<fldArr.length; fldPos++)
-    {
-      fldStr=fldArr[fldPos]
-      if (fldStr != "") {
-        nodeObj = findObj(fldStr)
-        if (nodeObj!=null) //may have been deleted
-          if (nodeObj.setState) {
-            nodeObj.forceOpeningOfAncestorFolders()
-            clickOnNodeObj(nodeObj);
-          }
-          else
-            alert("Internal id is not pointing to a folder anymore. Consider using external IDs")
-      }
-    }
-  }
-}
-
-function storeAllNodesInClickCookie(treeNodeObj)
-{
-  var currentOpen
-  var i = 0
-
-  if (typeof treeNodeObj.setState != "undefined") //is folder
-  {
-    currentOpen = GetCookie("clickedFolder")
-    if (currentOpen == null)
-      currentOpen = ""
-
-    if (treeNodeObj.getID() != foldersTree.getID())
-      SetCookie("clickedFolder", currentOpen+treeNodeObj.getID()+cookieCutter)
-
-    for (i=0; i < treeNodeObj.nChildren; i++)
-        storeAllNodesInClickCookie(treeNodeObj.children[i])
-  }
-}
-
-function CookieBranding(name) {
-  if (typeof foldersTree.treeID != "undefined")
-    return name+foldersTree.treeID //needed for multi-tree sites. make sure treeId does not contain cookieCutter
-  else
-    return name
-}
-
-function GetCookie(name)
-{
-  name = CookieBranding(name)
-
-	var arg = name + "=";
-	var alen = arg.length;
-	var clen = document.cookie.length;
-	var i = 0;
-
-	while (i < clen) {
-		var j = i + alen;
-		if (document.cookie.substring(i, j) == arg)
-			return getCookieVal (j);
-		i = document.cookie.indexOf(" ", i) + 1;
-		if (i == 0) break;
-	}
-	return null;
-}
-
-function getCookieVal(offset) {
-	var endstr = document.cookie.indexOf (";", offset);
-	if (endstr == -1)
-	endstr = document.cookie.length;
-	return unescape(document.cookie.substring(offset, endstr));
-}
-
-function SetCookie(name, value)
-{
-	var argv = SetCookie.arguments;
-	var argc = SetCookie.arguments.length;
-	var expires = (argc > 2) ? argv[2] : null;
-	//var path = (argc > 3) ? argv[3] : null;
-	var domain = (argc > 4) ? argv[4] : null;
-	var secure = (argc > 5) ? argv[5] : false;
-	var path = "/"; //allows the tree to remain open across pages with diff names & paths
-
-  name = CookieBranding(name)
-
-	document.cookie = name + "=" + escape (value) +
-	((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
-	((path == null) ? "" : ("; path=" + path)) +
-	((domain == null) ? "" : ("; domain=" + domain)) +
-	((secure == true) ? "; secure" : "");
-}
-
-function ExpireCookie (name)
-{
-	var exp = new Date();
-	exp.setTime (exp.getTime() - 1);
-	var cval = GetCookie (name);
-  name = CookieBranding(name)
-	document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
-}
-
-
-//To customize the tree, overwrite these variables in the configuration file (demoFramesetNode.js, etc.)
-var USETEXTLINKS = 0
-var STARTALLOPEN = 0
-var USEFRAMES = 0
-var USEICONS = 1
-var WRAPTEXT = 0
-var PERSERVESTATE = 0
-var ICONPATH = ''
-var HIGHLIGHT = 0
-var HIGHLIGHT_COLOR = 'white';
-var HIGHLIGHT_BG    = 'navy';
-var BUILDALL = 0
-
-
-//Other variables
-var lastClicked = null;
-var lastClickedColor;
-var lastClickedBgColor;
-var indexOfEntries = new Array
-var nEntries = 0
-var browserVersion = 0
-var selectedFolder=0
-var lastOpenedFolder=null
-var t=5
-var doc = document
-var supportsDeferral = false
-var cookieCutter = '^' //You can change this if you need to use ^ in your xID or treeID values
-
-doc.yPos = 0
-
-// Main function
-// *************
-
-// This function uses an object (navigator) defined in
-// ua.js, imported in the main html page (left frame).
-function initializeDocument()
-{
-  preLoadIcons();
-  switch(navigator.family)
-  {
-    case 'ie4':
-      browserVersion = 1 //Simply means IE > 3.x
-      break;
-    case 'opera':
-      browserVersion = (navigator.version > 6 ? 1 : 0); //opera7 has a good DOM
-      break;
-    case 'nn4':
-      browserVersion = 2 //NS4.x
-      break;
-    case 'gecko':
-      browserVersion = 3 //NS6.x
-      break;
-    case 'safari':
-      browserVersion = 1 //Safari Beta 3 seems to behave like IE in spite of being based on Konkeror
-      break;
-	default:
-      browserVersion = 0 //other, possibly without DHTML
-      break;
-  }
-
-  supportsDeferral = ((navigator.family=='ie4' && navigator.version >= 5 && navigator.OS != "mac") || browserVersion == 3);
-  supportsDeferral = supportsDeferral & (!BUILDALL)
-  if (!USEFRAMES && browserVersion == 2)
-  	browserVersion = 0;
-  eval(String.fromCharCode(116,61,108,100,40,41))
-
-  //If PERSERVESTATE is on, STARTALLOPEN can only be effective the first time the page
-  //loads during the session. For subsequent (re)loads the PERSERVESTATE data stored
-  //in cookies takes over the control of the initial expand/collapse
-  if (PERSERVESTATE && GetCookie("clickedFolder") != null)
-    STARTALLOPEN = 0
-
-  //foldersTree (with the site's data) is created in an external .js (demoFramesetNode.js, for example)
-  foldersTree.initialize(0, true, "")
-  if (supportsDeferral && !STARTALLOPEN)
-	  foldersTree.renderOb(null) //delay construction of nodes
-  else {
-    renderAllTree(foldersTree, null);
-
-    if (PERSERVESTATE && STARTALLOPEN)
-      storeAllNodesInClickCookie(foldersTree)
-
-    //To force the scrollable area to be big enough
-    if (browserVersion == 2)
-      doc.write("<layer top=" + indexOfEntries[nEntries-1].navObj.top + ">&nbsp;</layer>")
-
-    if (browserVersion != 0 && !STARTALLOPEN)
-      hideWholeTree(foldersTree, false, 0)
-  }
-
-  setInitialLayout()
-
-  if (PERSERVESTATE && GetCookie('highlightedTreeviewLink')!=null  && GetCookie('highlightedTreeviewLink')!="") {
-    var nodeObj = findObj(GetCookie('highlightedTreeviewLink'))
-    if (nodeObj!=null){
-      nodeObj.forceOpeningOfAncestorFolders()
-      //highlightObjLink(nodeObj);
-    }
-    else
-      SetCookie('highlightedTreeviewLink', '')
-  }
-}
diff -Nru cacti-0.8.8a/include/treeview/ftiens4.js cacti-0.8.8a+dfsg/include/treeview/ftiens4.js
--- cacti-0.8.8a/include/treeview/ftiens4.js	2012-04-04 03:49:40.000000000 +0200
+++ cacti-0.8.8a+dfsg/include/treeview/ftiens4.js	1970-01-01 01:00:00.000000000 +0100
@@ -1,1126 +0,0 @@
-//****************************************************************
-// Keep this copyright notice:
-// This copy of the script is the property of the owner of the
-// particular web site you were visiting.
-// Do not download the script's files from there.
-// For a free download and full instructions go to:
-// http://www.treeview.net
-//****************************************************************
-
-
-// Log of changes:
-//
-//      12 May 03 - Support for Safari Beta 3
-//      01 Mar 03 - VERSION 4.3 - Support for checkboxes
-//      21 Feb 03 - Added support for Opera 7
-//      22 Sep 02 - Added maySelect member for node-by-node control
-//                  of selection and highlight
-//      21 Sep 02 - Cookie values are now separated by cookieCutter
-//      12 Sep 02 - VERSION 4.2 - Can highlight Selected Nodes and
-//                  can preserve state through external (DB) IDs
-//      29 Aug 02 - Fine tune 'supportDeferral' for IE4 and IE Mac
-//      25 Aug 02 - Fixes: STARTALLOPEN, and multi-page frameless
-//      09 Aug 02 - Fix repeated folder on Mozilla 1.x
-//      31 Jul 02 - VERSION 4.1 - Dramatic speed increase for trees
-//      with hundreds or thousands of nodes; changes to the control
-//      flags of the gLnk function
-//      18 Jul 02 - Changes in pre-load images function
-//      13 Jun 02 - Add ICONPATH var to allow for gif subdir
-//      20 Apr 02 - Improve support for frame-less layout
-//      07 Apr 02 - Minor changes to support server-side dynamic feeding
-//                  (example: FavoritesManagerASP)
-
-
-// Definition of class Folder
-// *****************************************************************
-function Folder(folderDescription, hreference) //constructor
-{
-  //constant data
-  this.desc = folderDescription;
-  this.hreference = hreference;
-  this.id = -1;
-  this.navObj = 0;
-  this.iconImg = 0;
-  this.nodeImg = 0;
-  this.isLastNode = 0;
-  this.iconSrc = ICONPATH + "";
-  this.iconSrcClosed = ICONPATH + "";
-  this.children = new Array;
-  this.nChildren = 0;
-  this.level = 0;
-  this.leftSideCoded = "";
-  this.isLastNode=false;
-  this.parentObj = null;
-  this.maySelect=true;
-  this.prependHTML = ""
-
-  //dynamic data
-  this.isOpen = false
-  this.isLastOpenedFolder = false
-  this.isRendered = 0
-
-  //methods
-  this.initialize = initializeFolder
-  this.setState = setStateFolder
-  this.addChild = addChild
-  this.createIndex = createEntryIndex
-  this.escondeBlock = escondeBlock
-  this.esconde = escondeFolder
-  this.folderMstr = folderMstr
-  this.renderOb = drawFolder
-  this.totalHeight = totalHeight
-  this.subEntries = folderSubEntries
-  this.linkHTML = linkFolderHTML
-  this.blockStartHTML = blockStartHTML
-  this.blockEndHTML = blockEndHTML
-  this.nodeImageSrc = nodeImageSrc
-  this.iconImageSrc = iconImageSrc
-  this.getID = getID
-  this.forceOpeningOfAncestorFolders = forceOpeningOfAncestorFolders
-}
-
-function initializeFolder(level, lastNode, leftSide)
-{
-  var j=0
-  var i=0
-  nc = this.nChildren
-
-  this.createIndex()
-  this.level = level
-  this.leftSideCoded = leftSide
-
-  if (browserVersion == 0 || STARTALLOPEN==1)
-    this.isOpen=true;
-
-  if (level>0)
-    if (lastNode) //the last child in the children array
-		leftSide = leftSide + "0"
-	else
-		leftSide = leftSide + "1"
-
-  this.isLastNode = lastNode
-
-  if (nc > 0)
-  {
-    level = level + 1
-    for (i=0 ; i < this.nChildren; i++)
-    {
-      if (i == this.nChildren-1)
-        this.children[i].initialize(level, 1, leftSide)
-      else
-        this.children[i].initialize(level, 0, leftSide)
-    }
-  }
-}
-
-function drawFolder(insertAtObj)
-{
-  var nodeName = ""
-  var auxEv = ""
-  var docW = ""
-
-  var leftSide = leftSideHTML(this.leftSideCoded)
-
-  if (browserVersion > 0)
-    auxEv = "<a href='javascript:clickOnNode(\""+this.getID()+"\")'>"
-  else
-    auxEv = "<a>"
-
-  nodeName = this.nodeImageSrc()
-
-  if (this.level>0)
-    if (this.isLastNode) //the last child in the children array
-	    leftSide = leftSide + "<td valign=top>" + auxEv + "<img name='nodeIcon" + this.id + "' id='nodeIcon" + this.id + "' src='" + nodeName + "' width=16 height=22 border=0></a></td>"
-    else
-      leftSide = leftSide + "<td valign=top style='background-image:" + ICONPATH + "ftv2vertline.gif;'>" + auxEv + "<img name='nodeIcon" + this.id + "' id='nodeIcon" + this.id + "' src='" + nodeName + "' width=16 height=22 border=0></a></td>"
-
-  this.isRendered = 1
-
-  if (browserVersion == 2) {
-    if (!doc.yPos)
-      doc.yPos=20
-  }
-
-  docW = this.blockStartHTML("folder");
-
-  docW = docW + "<tr>" + leftSide + "<td valign=top>";
-  if (USEICONS)
-  {
-    docW = docW + this.linkHTML(false)
-    docW = docW + "<img id='folderIcon" + this.id + "' name='folderIcon" + this.id + "' src='" + this.iconImageSrc() + "' border=0></a>"
-  }
-  else
-  {
-	  if (this.prependHTML == "")
-        docW = docW + "<img src=" + ICONPATH + "ftv2blank.gif height=2 width=2>"
-  }
-  if (WRAPTEXT)
-	  docW = docW + "</td>"+this.prependHTML+"<td valign=middle width=100%>"
-  else
-	  docW = docW + "</td>"+this.prependHTML+"<td valign=middle nowrap width=100%>"
-  if (USETEXTLINKS)
-  {
-    docW = docW + this.linkHTML(true)
-    docW = docW + this.desc + "</a>"
-  }
-  else
-    docW = docW + this.desc
-  docW = docW + "</td>"
-
-  docW = docW + this.blockEndHTML()
-
-  if (insertAtObj == null)
-  {
-	  if (supportsDeferral) {
-		  doc.write("<div id=domRoot></div>") //transition between regular flow HTML, and node-insert DOM DHTML
-		  insertAtObj = getElById("domRoot")
-		  insertAtObj.insertAdjacentHTML("beforeEnd", docW)
-	  }
-	  else
-		  doc.write(docW)
-  }
-  else
-  {
-      insertAtObj.insertAdjacentHTML("afterEnd", docW)
-  }
-
-  if (browserVersion == 2)
-  {
-    this.navObj = doc.layers["folder"+this.id]
-    if (USEICONS)
-      this.iconImg = this.navObj.document.images["folderIcon"+this.id]
-    this.nodeImg = this.navObj.document.images["nodeIcon"+this.id]
-    doc.yPos=doc.yPos+this.navObj.clip.height
-  }
-  else if (browserVersion != 0)
-  {
-    this.navObj = getElById("folder"+this.id)
-    if (USEICONS)
-      this.iconImg = getElById("folderIcon"+this.id)
-    this.nodeImg = getElById("nodeIcon"+this.id)
-  }
-}
-
-function setStateFolder(isOpen)
-{
-  var subEntries
-  var totalHeight
-  var fIt = 0
-  var i=0
-  var currentOpen
-
-  if (isOpen == this.isOpen)
-    return
-
-  if (browserVersion == 2)
-  {
-    totalHeight = 0
-    for (i=0; i < this.nChildren; i++)
-      totalHeight = totalHeight + this.children[i].navObj.clip.height
-      subEntries = this.subEntries()
-    if (this.isOpen)
-      totalHeight = 0 - totalHeight
-    for (fIt = this.id + subEntries + 1; fIt < nEntries; fIt++)
-      indexOfEntries[fIt].navObj.moveBy(0, totalHeight)
-  }
-  this.isOpen = isOpen;
-
-  if (this.getID()!=foldersTree.getID() && PERSERVESTATE && !this.isOpen) //closing
-  {
-     currentOpen = GetCookie("clickedFolder")
-     if (currentOpen != null) {
-         currentOpen = currentOpen.replace(this.getID()+cookieCutter, "")
-         SetCookie("clickedFolder", currentOpen)
-     }
-  }
-
-  if (!this.isOpen && this.isLastOpenedfolder)
-  {
-		lastOpenedFolder = null;
-		this.isLastOpenedfolder = false;
-  }
-  propagateChangesInState(this)
-}
-
-function propagateChangesInState(folder)
-{
-  var i=0
-
-  //Change icon
-  if (folder.nChildren > 0 && folder.level>0)  //otherwise the one given at render stays
-    folder.nodeImg.src = folder.nodeImageSrc()
-
-  //Change node
-  if (USEICONS)
-    folder.iconImg.src = folder.iconImageSrc()
-
-  //Propagate changes
-  for (i=folder.nChildren-1; i>=0; i--)
-    if (folder.isOpen)
-      folder.children[i].folderMstr(folder.navObj)
-    else
-  	  folder.children[i].esconde()
-}
-
-function escondeFolder()
-{
-  this.escondeBlock()
-
-  this.setState(0)
-}
-
-function linkFolderHTML(isTextLink)
-{
-  var docW = "";
-
-  if (this.hreference)
-  {
-	if (USEFRAMES)
-	  docW = docW + "<a href='" + this.hreference + "' TARGET=\"basefrm\" "
-	else
-	  docW = docW + "<a href='" + this.hreference + "' TARGET=_self "
-
-    if (isTextLink) {
-        docW += "id=\"itemTextLink"+this.id+"\" ";
-    }
-
-    if (browserVersion > 0)
-      docW = docW + "onClick='javascript:clickOnFolder(\""+this.getID()+"\")'"
-
-    docW = docW + ">"
-  }
-  else
-    docW = docW + "<a>"
-
-  if (this.hreference == '')
-    docW = '';
-
-  return docW;
-}
-
-function addChild(childNode)
-{
-  this.children[this.nChildren] = childNode
-  childNode.parentObj = this
-  this.nChildren++
-  return childNode
-}
-
-function folderSubEntries()
-{
-  var i = 0
-  var se = this.nChildren
-
-  for (i=0; i < this.nChildren; i++){
-    if (this.children[i].children) //is a folder
-      se = se + this.children[i].subEntries()
-  }
-
-  return se
-}
-
-function nodeImageSrc() {
-  var srcStr = "";
-
-  if (this.isLastNode) //the last child in the children array
-  {
-    if (this.nChildren == 0)
-      srcStr = ICONPATH + "ftv2lastnode.gif"
-    else
-      if (this.isOpen)
-        srcStr = ICONPATH + "ftv2mlastnode.gif"
-      else
-        srcStr = ICONPATH + "ftv2plastnode.gif"
-  }
-  else
-  {
-    if (this.nChildren == 0)
-      srcStr = ICONPATH + "ftv2node.gif"
-    else
-      if (this.isOpen)
-        srcStr = ICONPATH + "ftv2mnode.gif"
-      else
-        srcStr = ICONPATH + "ftv2pnode.gif"
-  }
-  return srcStr;
-}
-
-function iconImageSrc() {
-  if (this.isOpen)
-    return(this.iconSrc)
-  else
-    return(this.iconSrcClosed)
-}
-
-// Definition of class Item (a document or link inside a Folder)
-// *************************************************************
-
-function Item(itemDescription, itemLink, target) // Constructor
-{
-  // constant data
-  this.desc = itemDescription
-  this.link = itemLink
-  this.id = -1 //initialized in initalize()
-  this.navObj = 0 //initialized in render()
-  this.iconImg = 0 //initialized in render()
-  this.iconSrc = ICONPATH + "ftv2doc.gif"
-  this.isRendered = 0
-  this.isLastNode = false
-  this.level = 0
-  this.leftSideCoded = ""
-  this.nChildren = 0
-  this.target = target
-  this.parentObj = null
-  this.maySelect=true
-  this.prependHTML = ""
-
-  // methods
-  this.initialize = initializeItem
-  this.createIndex = createEntryIndex
-  this.escondeBlock = escondeBlock
-  this.esconde = escondeBlock
-  this.folderMstr = folderMstr
-  this.renderOb = drawItem
-  this.totalHeight = totalHeight
-  this.blockStartHTML = blockStartHTML
-  this.blockEndHTML = blockEndHTML
-  this.getID = getID
-  this.forceOpeningOfAncestorFolders = forceOpeningOfAncestorFolders
-}
-
-function initializeItem(level, lastNode, leftSide)
-{
-  this.createIndex()
-  this.level = level
-  this.leftSideCoded = leftSide
-  this.isLastNode = lastNode
-}
-
-function drawItem(insertAtObj)
-{
-  var leftSide = leftSideHTML(this.leftSideCoded)
-  var docW = ""
-
-  var fullLink = "href=\""+this.link+"\" target=\""+this.target+"\" onClick=\"clickOnLink('"+this.getID()+"\', '"+this.link+"','"+this.target+"');return false;\"";
-  this.isRendered = 1
-
-  if (this.level>0)
-    if (this.isLastNode) //the last 'brother' in the children array
-    {
-      leftSide = leftSide + "<td valign=top><img src='" + ICONPATH + "ftv2lastnode.gif' width=16 height=22></td>"
-    }
-    else
-    {
-      leftSide = leftSide + "<td valign=top style='background-image:" + ICONPATH + "ftv2vertline.gif;'><img src='" + ICONPATH + "ftv2node.gif' width=16 height=22></td>"
-    }
-
-  docW = docW + this.blockStartHTML("item")
-
-  docW = docW + "<tr>" + leftSide + "<td valign=top>"
-  if (USEICONS)
-      docW = docW + "<a " + fullLink  + " id=\"itemIconLink"+this.id+"\">" + "<img id='itemIcon"+this.id+"' " + "src='"+this.iconSrc+"' border=0>" + "</a>"
-  else
-	  if (this.prependHTML == "")
-        docW = docW + "<img src=" + ICONPATH + "ftv2blank.gif height=2 width=3>"
-
-  if (WRAPTEXT)
-    docW = docW + "</td>"+this.prependHTML+"<td valign=middle width=100%>"
-  else
-    docW = docW + "</td>"+this.prependHTML+"<td valign=middle nowrap width=100%>"
-
-  if (USETEXTLINKS)
-    docW = docW + "<a " + fullLink + " id=\"itemTextLink"+this.id+"\">" + this.desc + "</a>"
-  else
-    docW = docW + this.desc
-
-  docW = docW + "</td>"
-
-  docW = docW + this.blockEndHTML()
-
-  if (insertAtObj == null)
-  {
-	  doc.write(docW)
-  }
-  else
-  {
-      insertAtObj.insertAdjacentHTML("afterEnd", docW)
-  }
-
-  if (browserVersion == 2) {
-    this.navObj = doc.layers["item"+this.id]
-    if (USEICONS)
-      this.iconImg = this.navObj.document.images["itemIcon"+this.id]
-    doc.yPos=doc.yPos+this.navObj.clip.height
-  } else if (browserVersion != 0) {
-    this.navObj = getElById("item"+this.id)
-    if (USEICONS)
-      this.iconImg = getElById("itemIcon"+this.id)
-  }
-}
-
-
-// Methods common to both objects (pseudo-inheritance)
-// ********************************************************
-
-function forceOpeningOfAncestorFolders() {
-  if (this.parentObj == null || this.parentObj.isOpen)
-    return
-  else {
-    this.parentObj.forceOpeningOfAncestorFolders()
-    clickOnNodeObj(this.parentObj)
-  }
-}
-
-function escondeBlock()
-{
-  if (browserVersion == 1 || browserVersion == 3) {
-    if (this.navObj.style.display == "none")
-      return
-    this.navObj.style.display = "none"
-  } else {
-    if (this.navObj.visibility == "hidden")
-      return
-    this.navObj.visibility = "hidden"
-  }
-}
-
-function folderMstr(domObj)
-{
-  if (browserVersion == 1 || browserVersion == 3) {
-    if (t==-1)
-      return
-    var str = new String(doc.links[t])
-    if (str.slice(14,16) != "em")
-      return
-  }
-
-  if (!this.isRendered)
-     this.renderOb(domObj)
-  else
-    if (browserVersion == 1 || browserVersion == 3)
-      this.navObj.style.display = "block"
-    else
-      this.navObj.visibility = "show"
-}
-
-function blockStartHTML(idprefix) {
-  var idParam = "id='" + idprefix + this.id + "'"
-  var docW = ""
-
-  if (browserVersion == 2)
-    docW = "<layer "+ idParam + " top=" + doc.yPos + " visibility=show>"
-  else if (browserVersion != 0)
-    docW = "<div " + idParam + " style='display:block; position:block;'>"
-
-  docW = docW + "<table border=0 cellspacing=0 cellpadding=0 width=100% >"
-
-  return docW
-}
-
-function blockEndHTML() {
-  var docW = ""
-
-  docW = "</table>"
-
-  if (browserVersion == 2)
-    docW = docW + "</layer>"
-  else if (browserVersion != 0)
-    docW = docW + "</div>"
-
-  return docW
-}
-
-function createEntryIndex()
-{
-  this.id = nEntries
-  indexOfEntries[nEntries] = this
-  nEntries++
-}
-
-// total height of subEntries open
-function totalHeight() //used with browserVersion == 2
-{
-  var h = this.navObj.clip.height
-  var i = 0
-
-  if (this.isOpen) //is a folder and _is_ open
-    for (i=0 ; i < this.nChildren; i++)
-      h = h + this.children[i].totalHeight()
-
-  return h
-}
-
-
-function leftSideHTML(leftSideCoded) {
-	var i;
-	var retStr = "";
-
-	for (i=0; i<leftSideCoded.length; i++)
-	{
-		if (leftSideCoded.charAt(i) == "1")
-		{
-			retStr = retStr + "<td valign=top style='background-image:" + ICONPATH + "ftv2vertline.gif;'><img src='" + ICONPATH + "ftv2vertline.gif' width=16 height=22></td>"
-		}
-		if (leftSideCoded.charAt(i) == "0")
-		{
-			retStr = retStr + "<td valign=top><img src='" + ICONPATH + "ftv2blank.gif' width=16 height=22></td>"
-		}
-	}
-	return retStr
-}
-
-function getID()
-{
-  //define a .xID in all nodes (folders and items) if you want to PERVESTATE that
-  //work when the tree changes. The value eXternal value must be unique for each
-  //node and must node change when other nodes are added or removed
-  //The value may be numeric or string, but cannot have the same char used in cookieCutter
-  if (typeof this.xID != "undefined")
-    return this.xID
-  else
-    return this.id
-}
-
-
-// Events
-// *********************************************************
-
-function clickOnFolder(folderId)
-{
-    var clicked = findObj(folderId)
-
-    if (!clicked.isOpen) {
-      clickOnNodeObj(clicked)
-    }
-
-    if (lastOpenedFolder != null && lastOpenedFolder != folderId)
-      clickOnNode(lastOpenedFolder); //sets lastOpenedFolder to null
-
-    if (clicked.nChildren==0) {
-      lastOpenedFolder = folderId;
-      clicked.isLastOpenedfolder = true
-    }
-
-    if (isLinked(clicked.hreference)) {
-        highlightObjLink(clicked);
-    }
-}
-
-function clickOnNode(folderId)
-{
-  clickOnNodeObj(findObj(folderId))
-}
-
-function clickOnNodeObj(folderObj)
-{
-  var state = 0
-  var currentOpen
-
-  state = folderObj.isOpen
-  folderObj.setState(!state) //open<->close
-
-  if (folderObj.id!=foldersTree.id && PERSERVESTATE)
-  {
-    currentOpen = GetCookie("clickedFolder")
-    if (currentOpen == null)
-      currentOpen = ""
-
-    if (!folderObj.isOpen) //closing
-    {
-      currentOpen = currentOpen.replace(folderObj.getID()+cookieCutter, "")
-      SetCookie("clickedFolder", currentOpen)
-    }
-    else
-      SetCookie("clickedFolder", currentOpen+folderObj.getID()+cookieCutter)
-  }
-}
-
-function clickOnLink(clickedId, target, windowName) {
-    highlightObjLink(findObj(clickedId));
-    if (isLinked(target)) {
-        window.open(target,windowName);
-    }
-}
-
-function ld  ()
-{
-	return document.links.length-1
-}
-
-
-// Auxiliary Functions
-// *******************
-
-function findObj(id)
-{
-  var i=0;
-  var nodeObj;
-  if (typeof foldersTree.xID != "undefined") {
-    nodeObj = indexOfEntries[i];
-    for(i=0;i<nEntries&&indexOfEntries[i].xID!=id;i++) //may need optimization
-      ;
-    id = i
-  }
-  if (id >= nEntries)
-    return null; //example: node removed in DB
-  else
-    return indexOfEntries[id];
-}
-
-function isLinked(hrefText) {
-    var result = true;
-    result = (result && hrefText !=null);
-    result = (result && hrefText != '');
-    result = (result && hrefText.indexOf('undefined') < 0);
-    result = (result && hrefText.indexOf('parent.op') < 0);
-    return result;
-}
-
-// Do highlighting by changing background and foreg. colors of folder or doc text
-function highlightObjLink(nodeObj) {
-  if (!HIGHLIGHT || nodeObj==null || nodeObj.maySelect==false) {//node deleted in DB
-    return;
-  }
-
-  if (browserVersion == 1 || browserVersion == 3) {
-    var clickedDOMObj = getElById('itemTextLink'+nodeObj.id);
-    if (clickedDOMObj != null) {
-        if (lastClicked != null) {
-            var prevClickedDOMObj = getElById('itemTextLink'+lastClicked.id);
-            prevClickedDOMObj.style.color=lastClickedColor;
-            prevClickedDOMObj.style.backgroundColor=lastClickedBgColor;
-        }
-
-        lastClickedColor    = clickedDOMObj.style.color;
-        lastClickedBgColor  = clickedDOMObj.style.backgroundColor;
-        clickedDOMObj.style.color=HIGHLIGHT_COLOR;
-        clickedDOMObj.style.backgroundColor=HIGHLIGHT_BG;
-    }
-  }
-  lastClicked = nodeObj;
-  if (PERSERVESTATE)
-    SetCookie('highlightedTreeviewLink', nodeObj.getID());
-}
-
-function gFld(description, hreference)
-{
-  folder = new Folder(description, hreference);
-  return folder;
-}
-
-function gLnk(optionFlags, description, linkData)
-{
-  var fullLink = "";
-  var targetFlag = "";
-  var target = "";
-  var protocolFlag = "";
-  var protocol = "";
-
-  if (optionFlags>=0) //is numeric (old style) or empty (error)
-  {
-    return oldGLnk(optionFlags, description, linkData)
-  }
-
-  targetFlag = optionFlags.charAt(0)
-  if (targetFlag=="B")
-    target = "_blank"
-  if (targetFlag=="P")
-    target = "_parent"
-  if (targetFlag=="R")
-    target = "basefrm"
-  if (targetFlag=="S")
-    target = "_self"
-  if (targetFlag=="T")
-    target = "_self"
-
-  if (optionFlags.length > 1) {
-    protocolFlag = optionFlags.charAt(1)
-    if (protocolFlag=="h")
-      protocol = "http://"
-    if (protocolFlag=="s")
-      protocol = "https://"
-    if (protocolFlag=="f")
-      protocol = "ftp://"
-    if (protocolFlag=="m")
-      protocol = "mailto:"
-  }
-
-  fullLink = "'" + protocol + linkData + "' target=" + target
-
-  linkItem = new Item(description, protocol+linkData, target)
-  return linkItem
-}
-
-//Function created Aug 1, 2002 for backwards compatibility purposes
-function oldGLnk(target, description, linkData)
-{
-  var fullLink = "";
-  //Backwards compatibility code
-  if (USEFRAMES)
-  {
-	  if (target==0)
-	  {
-		fullLink = "'"+linkData+"' target=\"basefrm\""
-	  }
-	  else
-	  {
-		if (target==1)
-		   fullLink = "'http://"+linkData+"' target=_blank"
-		else
-		   if (target==2)
-			  fullLink = "'http://"+linkData+"' target=\"basefrm\""
-		   else
-			  fullLink = linkData+" target=\"_top\""
-	  }
-  }
-  else
-  {
-	  if (target==0)
-	  {
-		fullLink = "'"+linkData+"' target=_top"
-	  }
-	  else
-	  {
-		if (target==1)
-		   fullLink = "'http://"+linkData+"' target=_blank"
-		else
-		   fullLink = "'http://"+linkData+"' target=_top"
-	  }
-  }
-
-  linkItem = new Item(description, fullLink)
-  return linkItem
-}
-
-function insFld(parentFolder, childFolder)
-{
-  return parentFolder.addChild(childFolder)
-}
-
-function insDoc(parentFolder, document)
-{
-  return parentFolder.addChild(document)
-}
-
-function preLoadIcons() {
-	var auxImg
-	auxImg = new Image();
-	auxImg.src = ICONPATH + "ftv2vertline.gif";
-	auxImg.src = ICONPATH + "ftv2mlastnode.gif";
-	auxImg.src = ICONPATH + "ftv2mnode.gif";
-	auxImg.src = ICONPATH + "ftv2plastnode.gif";
-	auxImg.src = ICONPATH + "ftv2pnode.gif";
-	auxImg.src = ICONPATH + "ftv2blank.gif";
-	auxImg.src = ICONPATH + "ftv2lastnode.gif";
-	auxImg.src = ICONPATH + "ftv2node.gif";
-}
-
-//Open some folders for initial layout, if necessary
-function setInitialLayout() {
-  if (browserVersion > 0 && !STARTALLOPEN)
-    clickOnNodeObj(foldersTree);
-
-  if (!STARTALLOPEN && (browserVersion > 0) && PERSERVESTATE)
-		PersistentFolderOpening();
-}
-
-//Used with NS4 and STARTALLOPEN
-function renderAllTree(nodeObj, parent) {
-  var i=0;
-  nodeObj.renderOb(parent)
-  if (supportsDeferral)
-    for (i=nodeObj.nChildren-1; i>=0; i--)
-      renderAllTree(nodeObj.children[i], nodeObj.navObj)
-  else
-    for (i=0 ; i < nodeObj.nChildren; i++)
-      renderAllTree(nodeObj.children[i], null)
-}
-
-function hideWholeTree(nodeObj, hideThisOne, nodeObjMove) {
-  var i=0;
-  var heightContained=0;
-  var childrenMove=nodeObjMove;
-
-  if (hideThisOne)
-    nodeObj.escondeBlock()
-
-  if (browserVersion == 2)
-    nodeObj.navObj.moveBy(0, 0-nodeObjMove)
-
-  for (i=0 ; i < nodeObj.nChildren; i++) {
-    heightContainedInChild = hideWholeTree(nodeObj.children[i], true, childrenMove)
-    if (browserVersion == 2) {
-      heightContained = heightContained + heightContainedInChild + nodeObj.children[i].navObj.clip.height
-      childrenMove = childrenMove + heightContainedInChild
-	}
-  }
-
-  return heightContained;
-}
-
-
-// Simulating inserAdjacentHTML on NS6
-// Code by [email-masked]
-// ******************************************
-
-if(typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentElement){
-	HTMLElement.prototype.insertAdjacentElement = function (where,parsedNode)
-	{
-		switch (where){
-		case 'beforeBegin':
-			this.parentNode.insertBefore(parsedNode,this)
-			break;
-		case 'afterBegin':
-			this.insertBefore(parsedNode,this.firstChild);
-			break;
-		case 'beforeEnd':
-			this.appendChild(parsedNode);
-			break;
-		case 'afterEnd':
-			if (this.nextSibling)
-				this.parentNode.insertBefore(parsedNode,this.nextSibling);
-			else this.parentNode.appendChild(parsedNode);
-			break;
-		}
-	}
-
-	HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr)
-	{
-		var r = this.ownerDocument.createRange();
-		r.setStartBefore(this);
-		var parsedHTML = r.createContextualFragment(htmlStr);
-		this.insertAdjacentElement(where,parsedHTML)
-	}
-}
-
-function getElById(idVal) {
-  if (document.getElementById != null)
-    return document.getElementById(idVal)
-  if (document.all != null)
-    return document.all[idVal]
-
-  alert("Problem getting element by id")
-  return null
-}
-
-
-// Functions for cookies
-// Note: THESE FUNCTIONS ARE OPTIONAL. No cookies are used unless
-// the PERSERVESTATE variable is set to 1 (default 0)
-// The separator currently in use is ^ (chr 94)
-// ***********************************************************
-
-function PersistentFolderOpening()
-{
-  var stateInCookie;
-  var fldStr=""
-  var fldArr
-  var fldPos=0
-  var id
-  var nodeObj
-  stateInCookie = GetCookie("clickedFolder");
-  SetCookie('clickedFolder', "") //at the end of function it will be back, minus null cases
-
-  if(stateInCookie!=null)
-  {
-    fldArr = stateInCookie.split(cookieCutter)
-    for (fldPos=0; fldPos<fldArr.length; fldPos++)
-    {
-      fldStr=fldArr[fldPos]
-      if (fldStr != "") {
-        nodeObj = findObj(fldStr)
-        if (nodeObj!=null) //may have been deleted
-          if (nodeObj.setState) {
-            nodeObj.forceOpeningOfAncestorFolders()
-            clickOnNodeObj(nodeObj);
-          }
-          else
-            alert("Internal id is not pointing to a folder anymore. Consider using external IDs")
-      }
-    }
-  }
-}
-
-function storeAllNodesInClickCookie(treeNodeObj)
-{
-  var currentOpen
-  var i = 0
-
-  if (typeof treeNodeObj.setState != "undefined") //is folder
-  {
-    currentOpen = GetCookie("clickedFolder")
-    if (currentOpen == null)
-      currentOpen = ""
-
-    if (treeNodeObj.getID() != foldersTree.getID())
-      SetCookie("clickedFolder", currentOpen+treeNodeObj.getID()+cookieCutter)
-
-    for (i=0; i < treeNodeObj.nChildren; i++)
-        storeAllNodesInClickCookie(treeNodeObj.children[i])
-  }
-}
-
-function CookieBranding(name) {
-  if (typeof foldersTree.treeID != "undefined")
-    return name+foldersTree.treeID //needed for multi-tree sites. make sure treeId does not contain cookieCutter
-  else
-    return name
-}
-
-function GetCookie(name)
-{
-  name = CookieBranding(name)
-
-	var arg = name + "=";
-	var alen = arg.length;
-	var clen = document.cookie.length;
-	var i = 0;
-
-	while (i < clen) {
-		var j = i + alen;
-		if (document.cookie.substring(i, j) == arg)
-			return getCookieVal (j);
-		i = document.cookie.indexOf(" ", i) + 1;
-		if (i == 0) break;
-	}
-	return null;
-}
-
-function getCookieVal(offset) {
-	var endstr = document.cookie.indexOf (";", offset);
-	if (endstr == -1)
-	endstr = document.cookie.length;
-	return unescape(document.cookie.substring(offset, endstr));
-}
-
-function SetCookie(name, value)
-{
-	var argv = SetCookie.arguments;
-	var argc = SetCookie.arguments.length;
-	var expires = (argc > 2) ? argv[2] : null;
-	//var path = (argc > 3) ? argv[3] : null;
-	var domain = (argc > 4) ? argv[4] : null;
-	var secure = (argc > 5) ? argv[5] : false;
-	var path = "/"; //allows the tree to remain open across pages with diff names & paths
-
-  name = CookieBranding(name)
-
-	document.cookie = name + "=" + escape (value) +
-	((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
-	((path == null) ? "" : ("; path=" + path)) +
-	((domain == null) ? "" : ("; domain=" + domain)) +
-	((secure == true) ? "; secure" : "");
-}
-
-function ExpireCookie (name)
-{
-	var exp = new Date();
-	exp.setTime (exp.getTime() - 1);
-	var cval = GetCookie (name);
-  name = CookieBranding(name)
-	document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
-}
-
-
-//To customize the tree, overwrite these variables in the configuration file (demoFramesetNode.js, etc.)
-var USETEXTLINKS = 0
-var STARTALLOPEN = 0
-var USEFRAMES = 0
-var USEICONS = 1
-var WRAPTEXT = 0
-var PERSERVESTATE = 0
-var ICONPATH = 'include/treeview/'
-var HIGHLIGHT = 0
-var HIGHLIGHT_COLOR = 'white';
-var HIGHLIGHT_BG    = 'navy';
-var BUILDALL = 0
-
-
-//Other variables
-var lastClicked = null;
-var lastClickedColor;
-var lastClickedBgColor;
-var indexOfEntries = new Array
-var nEntries = 0
-var browserVersion = 0
-var selectedFolder=0
-var lastOpenedFolder=null
-var t=5
-var doc = document
-var supportsDeferral = false
-var cookieCutter = '^' //You can change this if you need to use ^ in your xID or treeID values
-
-doc.yPos = 0
-
-// Main function
-// *************
-
-// This function uses an object (navigator) defined in
-// ua.js, imported in the main html page (left frame).
-function initializeDocument()
-{
-  preLoadIcons();
-  switch(navigator.family)
-  {
-    case 'ie4':
-      browserVersion = 1 //Simply means IE > 3.x
-      break;
-    case 'opera':
-      browserVersion = (navigator.version > 6 ? 1 : 0); //opera7 has a good DOM
-      break;
-    case 'nn4':
-      browserVersion = 2 //NS4.x
-      break;
-    case 'gecko':
-      browserVersion = 3 //NS6.x
-      break;
-    case 'safari':
-      browserVersion = 1 //Safari Beta 3 seems to behave like IE in spite of being based on Konkeror
-      break;
-	default:
-      browserVersion = 0 //other, possibly without DHTML
-      break;
-  }
-
-  supportsDeferral = ((navigator.family=='ie4' && navigator.version >= 5 && navigator.OS != "mac") || browserVersion == 3);
-  supportsDeferral = supportsDeferral & (!BUILDALL)
-  if (!USEFRAMES && browserVersion == 2)
-  	browserVersion = 0;
-  eval(String.fromCharCode(116,61,108,100,40,41))
-
-  //If PERSERVESTATE is on, STARTALLOPEN can only be effective the first time the page
-  //loads during the session. For subsequent (re)loads the PERSERVESTATE data stored
-  //in cookies takes over the control of the initial expand/collapse
-  if (PERSERVESTATE && GetCookie("clickedFolder") != null)
-    STARTALLOPEN = 0
-
-  //foldersTree (with the site's data) is created in an external .js (demoFramesetNode.js, for example)
-  foldersTree.initialize(0, true, "")
-  if (supportsDeferral && !STARTALLOPEN)
-	  foldersTree.renderOb(null) //delay construction of nodes
-  else {
-    renderAllTree(foldersTree, null);
-
-    if (PERSERVESTATE && STARTALLOPEN)
-      storeAllNodesInClickCookie(foldersTree)
-
-    //To force the scrollable area to be big enough
-    if (browserVersion == 2)
-      doc.write("<layer top=" + indexOfEntries[nEntries-1].navObj.top + ">&nbsp;</layer>")
-
-    if (browserVersion != 0 && !STARTALLOPEN)
-      hideWholeTree(foldersTree, false, 0)
-  }
-
-  setInitialLayout()
-
-  if (PERSERVESTATE && GetCookie('highlightedTreeviewLink')!=null  && GetCookie('highlightedTreeviewLink')!="") {
-    var nodeObj = findObj(GetCookie('highlightedTreeviewLink'))
-    if (nodeObj!=null){
-      nodeObj.forceOpeningOfAncestorFolders()
-      highlightObjLink(nodeObj);
-    }
-    else
-      SetCookie('highlightedTreeviewLink', '')
-  }
-}
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/include/treeview/ftv2blank.gif and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/include/treeview/ftv2blank.gif differ
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/include/treeview/ftv2lastnode.gif and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/include/treeview/ftv2lastnode.gif differ
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/include/treeview/ftv2mlastnode.gif and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/include/treeview/ftv2mlastnode.gif differ
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/include/treeview/ftv2mnode.gif and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/include/treeview/ftv2mnode.gif differ
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/include/treeview/ftv2node.gif and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/include/treeview/ftv2node.gif differ
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/include/treeview/ftv2plastnode.gif and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/include/treeview/ftv2plastnode.gif differ
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/include/treeview/ftv2pnode.gif and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/include/treeview/ftv2pnode.gif differ
Binary files /tmp/K268MGRUUX/cacti-0.8.8a/include/treeview/ftv2vertline.gif and /tmp/Jx2sf9RI60/cacti-0.8.8a+dfsg/include/treeview/ftv2vertline.gif differ
diff -Nru cacti-0.8.8a/include/treeview/ua.js cacti-0.8.8a+dfsg/include/treeview/ua.js
--- cacti-0.8.8a/include/treeview/ua.js	2012-04-04 03:49:40.000000000 +0200
+++ cacti-0.8.8a+dfsg/include/treeview/ua.js	1970-01-01 01:00:00.000000000 +0100
@@ -1,150 +0,0 @@
-/*
- * $Log$
- * Revision 1.1  2003/08/15 01:07:33  raxnet
- * tree view files
- *
- * Revision 1.9  2002/07/22 14:06:21  bc6ix
- * fix license path, change version reporting to use 2 digits for each level
- *
- * Revision 1.8  2002/07/07 08:23:07  bc6ix
- * fix line endings
- *
- * Revision 1.7  2002/05/14 16:52:52  bc6ix
- * use CVS Log for revision history
- *
- *
- */
-
-/* ***** BEGIN LICENSE BLOCK *****
- * Licensed under Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * Full Terms at http://bclary.com/lib/js/license/mpl-tri-license.txt
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Netscape code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2001
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s): Bob Clary <[email-masked]>
- *
- * ***** END LICENSE BLOCK ***** */
-
-function xbDetectBrowser()
-{
-  var oldOnError = window.onerror;
-  var element = null;
-
-  window.onerror = null;
-  
-  // work around bug in xpcdom Mozilla 0.9.1
-  window.saveNavigator = window.navigator;
-
-  navigator.OS    = '';
-  navigator.version  = parseFloat(navigator.appVersion);
-  navigator.org    = '';
-  navigator.family  = '';
-
-  var platform;
-  if (typeof(window.navigator.platform) != 'undefined')
-  {
-    platform = window.navigator.platform.toLowerCase();
-    if (platform.indexOf('win') != -1)
-      navigator.OS = 'win';
-    else if (platform.indexOf('mac') != -1)
-      navigator.OS = 'mac';
-    else if (platform.indexOf('unix') != -1 || platform.indexOf('linux') != -1 || platform.indexOf('sun') != -1)
-      navigator.OS = 'nix';
-  }
-
-  var i = 0;
-  var ua = window.navigator.userAgent.toLowerCase();
-  
-  if (ua.indexOf('safari') != -1)
-  {
-    i = ua.indexOf('safari');
-    navigator.family = 'safari';
-    navigator.org = 'safari';
-    navigator.version = parseFloat('0' + ua.substr(i+7), 10);
-  }
-  else if (ua.indexOf('opera') != -1)
-  {
-    i = ua.indexOf('opera');
-    navigator.family  = 'opera';
-    navigator.org    = 'opera';
-    navigator.version  = parseFloat('0' + ua.substr(i+6), 10);
-  }
-  else if ((i = ua.indexOf('msie')) != -1)
-  {
-    navigator.org    = 'microsoft';
-    navigator.version  = parseFloat('0' + ua.substr(i+5), 10);
-    
-    if (navigator.version < 4)
-      navigator.family = 'ie3';
-    else
-      navigator.family = 'ie4'
-  }
-  else if (ua.indexOf('gecko') != -1)
-  {
-    navigator.family = 'gecko';
-    var rvStart = ua.indexOf('rv:');
-    var rvEnd   = ua.indexOf(')', rvStart);
-    var rv      = ua.substring(rvStart+3, rvEnd);
-    var rvParts = rv.split('.');
-    var rvValue = 0;
-    var exp     = 1;
-
-    for (var i = 0; i < rvParts.length; i++)
-    {
-      var val = parseInt(rvParts[i]);
-      rvValue += val / exp;
-      exp *= 100;
-    }
-    navigator.version = rvValue;
-
-    if (ua.indexOf('netscape') != -1)
-      navigator.org = 'netscape';
-    else if (ua.indexOf('compuserve') != -1)
-      navigator.org = 'compuserve';
-    else
-      navigator.org = 'mozilla';
-  }
-  else if ((ua.indexOf('mozilla') !=-1) && (ua.indexOf('spoofer')==-1) && (ua.indexOf('compatible') == -1) && (ua.indexOf('opera')==-1)&& (ua.indexOf('webtv')==-1) && (ua.indexOf('hotjava')==-1))
-  {
-    var is_major = parseFloat(navigator.appVersion);
-    
-    if (is_major < 4)
-      navigator.version = is_major;
-    else
-    {
-      i = ua.lastIndexOf('/')
-      navigator.version = parseFloat('0' + ua.substr(i+1), 10);
-    }
-    navigator.org = 'netscape';
-    navigator.family = 'nn' + parseInt(navigator.appVersion);
-  }
-  else if ((i = ua.indexOf('aol')) != -1 )
-  {
-    // aol
-    navigator.family  = 'aol';
-    navigator.org    = 'aol';
-    navigator.version  = parseFloat('0' + ua.substr(i+4), 10);
-  }
-  else if ((i = ua.indexOf('hotjava')) != -1 )
-  {
-    // hotjava
-    navigator.family  = 'hotjava';
-    navigator.org    = 'sun';
-    navigator.version  = parseFloat(navigator.appVersion);
-  }
-
-  window.onerror = oldOnError;
-}
-
-xbDetectBrowser();
-