Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision ecb7a87d

Von Moritz Bunkus vor mehr als 11 Jahren hinzugefügt

  • ID ecb7a87d9d5e81e4776ac7104b645440f6539c0a
  • Vorgänger baf1e895
  • Nachfolger 3dee3e56

jstree-jQuery-Plugin hinzugefügt

Unterschiede anzeigen:

doc/js/License.jstree.txt
1
Copyright 2012 jQuery Foundation and other contributors,
2
http://jqueryui.com/
3

  
4
This software consists of voluntary contributions made by many
5
individuals (AUTHORS.txt, http://jqueryui.com/about) For exact
6
contribution history, see the revision history and logs, available
7
at http://jquery-ui.googlecode.com/svn/
8

  
9
Permission is hereby granted, free of charge, to any person obtaining
10
a copy of this software and associated documentation files (the
11
"Software"), to deal in the Software without restriction, including
12
without limitation the rights to use, copy, modify, merge, publish,
13
distribute, sublicense, and/or sell copies of the Software, and to
14
permit persons to whom the Software is furnished to do so, subject to
15
the following conditions:
16

  
17
The above copyright notice and this permission notice shall be
18
included in all copies or substantial portions of the Software.
19

  
20
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
js/jquery.jstree.js
1
/*
2
 * jsTree 1.0-rc3
3
 * http://jstree.com/
4
 *
5
 * Copyright (c) 2010 Ivan Bozhanov (vakata.com)
6
 *
7
 * Licensed same as jquery - under the terms of either the MIT License or the GPL Version 2 License
8
 *   http://www.opensource.org/licenses/mit-license.php
9
 *   http://www.gnu.org/licenses/gpl.html
10
 *
11
 * $Date: 2011-02-09 01:17:14 +0200 (ср, 09 февр 2011) $
12
 * $Revision: 236 $
13
 */
14

  
15
/*jslint browser: true, onevar: true, undef: true, bitwise: true, strict: true */
16
/*global window : false, clearInterval: false, clearTimeout: false, document: false, setInterval: false, setTimeout: false, jQuery: false, navigator: false, XSLTProcessor: false, DOMParser: false, XMLSerializer: false, ActiveXObject: false */
17

  
18
"use strict";
19

  
20
// top wrapper to prevent multiple inclusion (is this OK?)
21
(function () { if(jQuery && jQuery.jstree) { return; }
22
	var is_ie6 = false, is_ie7 = false, is_ff2 = false;
23

  
24
/* 
25
 * jsTree core
26
 */
27
(function ($) {
28
	// Common functions not related to jsTree 
29
	// decided to move them to a `vakata` "namespace"
30
	$.vakata = {};
31
	// CSS related functions
32
	$.vakata.css = {
33
		get_css : function(rule_name, delete_flag, sheet) {
34
			rule_name = rule_name.toLowerCase();
35
			var css_rules = sheet.cssRules || sheet.rules,
36
				j = 0;
37
			do {
38
				if(css_rules.length && j > css_rules.length + 5) { return false; }
39
				if(css_rules[j].selectorText && css_rules[j].selectorText.toLowerCase() == rule_name) {
40
					if(delete_flag === true) {
41
						if(sheet.removeRule) { sheet.removeRule(j); }
42
						if(sheet.deleteRule) { sheet.deleteRule(j); }
43
						return true;
44
					}
45
					else { return css_rules[j]; }
46
				}
47
			}
48
			while (css_rules[++j]);
49
			return false;
50
		},
51
		add_css : function(rule_name, sheet) {
52
			if($.jstree.css.get_css(rule_name, false, sheet)) { return false; }
53
			if(sheet.insertRule) { sheet.insertRule(rule_name + ' { }', 0); } else { sheet.addRule(rule_name, null, 0); }
54
			return $.vakata.css.get_css(rule_name);
55
		},
56
		remove_css : function(rule_name, sheet) { 
57
			return $.vakata.css.get_css(rule_name, true, sheet); 
58
		},
59
		add_sheet : function(opts) {
60
			var tmp = false, is_new = true;
61
			if(opts.str) {
62
				if(opts.title) { tmp = $("style[id='" + opts.title + "-stylesheet']")[0]; }
63
				if(tmp) { is_new = false; }
64
				else {
65
					tmp = document.createElement("style");
66
					tmp.setAttribute('type',"text/css");
67
					if(opts.title) { tmp.setAttribute("id", opts.title + "-stylesheet"); }
68
				}
69
				if(tmp.styleSheet) {
70
					if(is_new) { 
71
						document.getElementsByTagName("head")[0].appendChild(tmp); 
72
						tmp.styleSheet.cssText = opts.str; 
73
					}
74
					else {
75
						tmp.styleSheet.cssText = tmp.styleSheet.cssText + " " + opts.str; 
76
					}
77
				}
78
				else {
79
					tmp.appendChild(document.createTextNode(opts.str));
80
					document.getElementsByTagName("head")[0].appendChild(tmp);
81
				}
82
				return tmp.sheet || tmp.styleSheet;
83
			}
84
			if(opts.url) {
85
				if(document.createStyleSheet) {
86
					try { tmp = document.createStyleSheet(opts.url); } catch (e) { }
87
				}
88
				else {
89
					tmp			= document.createElement('link');
90
					tmp.rel		= 'stylesheet';
91
					tmp.type	= 'text/css';
92
					tmp.media	= "all";
93
					tmp.href	= opts.url;
94
					document.getElementsByTagName("head")[0].appendChild(tmp);
95
					return tmp.styleSheet;
96
				}
97
			}
98
		}
99
	};
100

  
101
	// private variables 
102
	var instances = [],			// instance array (used by $.jstree.reference/create/focused)
103
		focused_instance = -1,	// the index in the instance array of the currently focused instance
104
		plugins = {},			// list of included plugins
105
		prepared_move = {};		// for the move_node function
106

  
107
	// jQuery plugin wrapper (thanks to jquery UI widget function)
108
	$.fn.jstree = function (settings) {
109
		var isMethodCall = (typeof settings == 'string'), // is this a method call like $().jstree("open_node")
110
			args = Array.prototype.slice.call(arguments, 1), 
111
			returnValue = this;
112

  
113
		// if a method call execute the method on all selected instances
114
		if(isMethodCall) {
115
			if(settings.substring(0, 1) == '_') { return returnValue; }
116
			this.each(function() {
117
				var instance = instances[$.data(this, "jstree_instance_id")],
118
					methodValue = (instance && $.isFunction(instance[settings])) ? instance[settings].apply(instance, args) : instance;
119
					if(typeof methodValue !== "undefined" && (settings.indexOf("is_") === 0 || (methodValue !== true && methodValue !== false))) { returnValue = methodValue; return false; }
120
			});
121
		}
122
		else {
123
			this.each(function() {
124
				// extend settings and allow for multiple hashes and $.data
125
				var instance_id = $.data(this, "jstree_instance_id"),
126
					a = [],
127
					b = settings ? $.extend({}, true, settings) : {},
128
					c = $(this), 
129
					s = false, 
130
					t = [];
131
				a = a.concat(args);
132
				if(c.data("jstree")) { a.push(c.data("jstree")); }
133
				b = a.length ? $.extend.apply(null, [true, b].concat(a)) : b;
134

  
135
				// if an instance already exists, destroy it first
136
				if(typeof instance_id !== "undefined" && instances[instance_id]) { instances[instance_id].destroy(); }
137
				// push a new empty object to the instances array
138
				instance_id = parseInt(instances.push({}),10) - 1;
139
				// store the jstree instance id to the container element
140
				$.data(this, "jstree_instance_id", instance_id);
141
				// clean up all plugins
142
				b.plugins = $.isArray(b.plugins) ? b.plugins : $.jstree.defaults.plugins.slice();
143
				b.plugins.unshift("core");
144
				// only unique plugins
145
				b.plugins = b.plugins.sort().join(",,").replace(/(,|^)([^,]+)(,,\2)+(,|$)/g,"$1$2$4").replace(/,,+/g,",").replace(/,$/,"").split(",");
146

  
147
				// extend defaults with passed data
148
				s = $.extend(true, {}, $.jstree.defaults, b);
149
				s.plugins = b.plugins;
150
				$.each(plugins, function (i, val) { 
151
					if($.inArray(i, s.plugins) === -1) { s[i] = null; delete s[i]; } 
152
					else { t.push(i); }
153
				});
154
				s.plugins = t;
155

  
156
				// push the new object to the instances array (at the same time set the default classes to the container) and init
157
				instances[instance_id] = new $.jstree._instance(instance_id, $(this).addClass("jstree jstree-" + instance_id), s); 
158
				// init all activated plugins for this instance
159
				$.each(instances[instance_id]._get_settings().plugins, function (i, val) { instances[instance_id].data[val] = {}; });
160
				$.each(instances[instance_id]._get_settings().plugins, function (i, val) { if(plugins[val]) { plugins[val].__init.apply(instances[instance_id]); } });
161
				// initialize the instance
162
				setTimeout(function() { if(instances[instance_id]) { instances[instance_id].init(); } }, 0);
163
			});
164
		}
165
		// return the jquery selection (or if it was a method call that returned a value - the returned value)
166
		return returnValue;
167
	};
168
	// object to store exposed functions and objects
169
	$.jstree = {
170
		defaults : {
171
			plugins : []
172
		},
173
		_focused : function () { return instances[focused_instance] || null; },
174
		_reference : function (needle) { 
175
			// get by instance id
176
			if(instances[needle]) { return instances[needle]; }
177
			// get by DOM (if still no luck - return null
178
			var o = $(needle); 
179
			if(!o.length && typeof needle === "string") { o = $("#" + needle); }
180
			if(!o.length) { return null; }
181
			return instances[o.closest(".jstree").data("jstree_instance_id")] || null; 
182
		},
183
		_instance : function (index, container, settings) { 
184
			// for plugins to store data in
185
			this.data = { core : {} };
186
			this.get_settings	= function () { return $.extend(true, {}, settings); };
187
			this._get_settings	= function () { return settings; };
188
			this.get_index		= function () { return index; };
189
			this.get_container	= function () { return container; };
190
			this.get_container_ul = function () { return container.children("ul:eq(0)"); };
191
			this._set_settings	= function (s) { 
192
				settings = $.extend(true, {}, settings, s);
193
			};
194
		},
195
		_fn : { },
196
		plugin : function (pname, pdata) {
197
			pdata = $.extend({}, {
198
				__init		: $.noop, 
199
				__destroy	: $.noop,
200
				_fn			: {},
201
				defaults	: false
202
			}, pdata);
203
			plugins[pname] = pdata;
204

  
205
			$.jstree.defaults[pname] = pdata.defaults;
206
			$.each(pdata._fn, function (i, val) {
207
				val.plugin		= pname;
208
				val.old			= $.jstree._fn[i];
209
				$.jstree._fn[i] = function () {
210
					var rslt,
211
						func = val,
212
						args = Array.prototype.slice.call(arguments),
213
						evnt = new $.Event("before.jstree"),
214
						rlbk = false;
215

  
216
					if(this.data.core.locked === true && i !== "unlock" && i !== "is_locked") { return; }
217

  
218
					// Check if function belongs to the included plugins of this instance
219
					do {
220
						if(func && func.plugin && $.inArray(func.plugin, this._get_settings().plugins) !== -1) { break; }
221
						func = func.old;
222
					} while(func);
223
					if(!func) { return; }
224

  
225
					// context and function to trigger events, then finally call the function
226
					if(i.indexOf("_") === 0) {
227
						rslt = func.apply(this, args);
228
					}
229
					else {
230
						rslt = this.get_container().triggerHandler(evnt, { "func" : i, "inst" : this, "args" : args, "plugin" : func.plugin });
231
						if(rslt === false) { return; }
232
						if(typeof rslt !== "undefined") { args = rslt; }
233

  
234
						rslt = func.apply(
235
							$.extend({}, this, { 
236
								__callback : function (data) { 
237
									this.get_container().triggerHandler( i + '.jstree', { "inst" : this, "args" : args, "rslt" : data, "rlbk" : rlbk });
238
								},
239
								__rollback : function () { 
240
									rlbk = this.get_rollback();
241
									return rlbk;
242
								},
243
								__call_old : function (replace_arguments) {
244
									return func.old.apply(this, (replace_arguments ? Array.prototype.slice.call(arguments, 1) : args ) );
245
								}
246
							}), args);
247
					}
248

  
249
					// return the result
250
					return rslt;
251
				};
252
				$.jstree._fn[i].old = val.old;
253
				$.jstree._fn[i].plugin = pname;
254
			});
255
		},
256
		rollback : function (rb) {
257
			if(rb) {
258
				if(!$.isArray(rb)) { rb = [ rb ]; }
259
				$.each(rb, function (i, val) {
260
					instances[val.i].set_rollback(val.h, val.d);
261
				});
262
			}
263
		}
264
	};
265
	// set the prototype for all instances
266
	$.jstree._fn = $.jstree._instance.prototype = {};
267

  
268
	// load the css when DOM is ready
269
	$(function() {
270
		// code is copied from jQuery ($.browser is deprecated + there is a bug in IE)
271
		var u = navigator.userAgent.toLowerCase(),
272
			v = (u.match( /.+?(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
273
			css_string = '' + 
274
				'.jstree ul, .jstree li { display:block; margin:0 0 0 0; padding:0 0 0 0; list-style-type:none; } ' + 
275
				'.jstree li { display:block; min-height:18px; line-height:18px; white-space:nowrap; margin-left:18px; min-width:18px; } ' + 
276
				'.jstree-rtl li { margin-left:0; margin-right:18px; } ' + 
277
				'.jstree > ul > li { margin-left:0px; } ' + 
278
				'.jstree-rtl > ul > li { margin-right:0px; } ' + 
279
				'.jstree ins { display:inline-block; text-decoration:none; width:18px; height:18px; margin:0 0 0 0; padding:0; } ' + 
280
				'.jstree a { display:inline-block; line-height:16px; height:16px; color:black; white-space:nowrap; text-decoration:none; padding:1px 2px; margin:0; } ' + 
281
				'.jstree a:focus { outline: none; } ' + 
282
				'.jstree a > ins { height:16px; width:16px; } ' + 
283
				'.jstree a > .jstree-icon { margin-right:3px; } ' + 
284
				'.jstree-rtl a > .jstree-icon { margin-left:3px; margin-right:0; } ' + 
285
				'li.jstree-open > ul { display:block; } ' + 
286
				'li.jstree-closed > ul { display:none; } ';
287
		// Correct IE 6 (does not support the > CSS selector)
288
		if(/msie/.test(u) && parseInt(v, 10) == 6) { 
289
			is_ie6 = true;
290

  
291
			// fix image flicker and lack of caching
292
			try {
293
				document.execCommand("BackgroundImageCache", false, true);
294
			} catch (err) { }
295

  
296
			css_string += '' + 
297
				'.jstree li { height:18px; margin-left:0; margin-right:0; } ' + 
298
				'.jstree li li { margin-left:18px; } ' + 
299
				'.jstree-rtl li li { margin-left:0px; margin-right:18px; } ' + 
300
				'li.jstree-open ul { display:block; } ' + 
301
				'li.jstree-closed ul { display:none !important; } ' + 
302
				'.jstree li a { display:inline; border-width:0 !important; padding:0px 2px !important; } ' + 
303
				'.jstree li a ins { height:16px; width:16px; margin-right:3px; } ' + 
304
				'.jstree-rtl li a ins { margin-right:0px; margin-left:3px; } ';
305
		}
306
		// Correct IE 7 (shifts anchor nodes onhover)
307
		if(/msie/.test(u) && parseInt(v, 10) == 7) { 
308
			is_ie7 = true;
309
			css_string += '.jstree li a { border-width:0 !important; padding:0px 2px !important; } ';
310
		}
311
		// correct ff2 lack of display:inline-block
312
		if(!/compatible/.test(u) && /mozilla/.test(u) && parseFloat(v, 10) < 1.9) {
313
			is_ff2 = true;
314
			css_string += '' + 
315
				'.jstree ins { display:-moz-inline-box; } ' + 
316
				'.jstree li { line-height:12px; } ' + // WHY??
317
				'.jstree a { display:-moz-inline-box; } ' + 
318
				'.jstree .jstree-no-icons .jstree-checkbox { display:-moz-inline-stack !important; } ';
319
				/* this shouldn't be here as it is theme specific */
320
		}
321
		// the default stylesheet
322
		$.vakata.css.add_sheet({ str : css_string, title : "jstree" });
323
	});
324

  
325
	// core functions (open, close, create, update, delete)
326
	$.jstree.plugin("core", {
327
		__init : function () {
328
			this.data.core.locked = false;
329
			this.data.core.to_open = this.get_settings().core.initially_open;
330
			this.data.core.to_load = this.get_settings().core.initially_load;
331
		},
332
		defaults : { 
333
			html_titles	: false,
334
			animation	: 500,
335
			initially_open : [],
336
			initially_load : [],
337
			open_parents : true,
338
			notify_plugins : true,
339
			rtl			: false,
340
			load_open	: false,
341
			strings		: {
342
				loading		: "Loading ...",
343
				new_node	: "New node",
344
				multiple_selection : "Multiple selection"
345
			}
346
		},
347
		_fn : { 
348
			init	: function () { 
349
				this.set_focus(); 
350
				if(this._get_settings().core.rtl) {
351
					this.get_container().addClass("jstree-rtl").css("direction", "rtl");
352
				}
353
				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>");
354
				this.data.core.li_height = this.get_container_ul().find("li.jstree-closed, li.jstree-leaf").eq(0).height() || 18;
355

  
356
				this.get_container()
357
					.delegate("li > ins", "click.jstree", $.proxy(function (event) {
358
							var trgt = $(event.target);
359
							// if(trgt.is("ins") && event.pageY - trgt.offset().top < this.data.core.li_height) { this.toggle_node(trgt); }
360
							this.toggle_node(trgt);
361
						}, this))
362
					.bind("mousedown.jstree", $.proxy(function () { 
363
							this.set_focus(); // This used to be setTimeout(set_focus,0) - why?
364
						}, this))
365
					.bind("dblclick.jstree", function (event) { 
366
						var sel;
367
						if(document.selection && document.selection.empty) { document.selection.empty(); }
368
						else {
369
							if(window.getSelection) {
370
								sel = window.getSelection();
371
								try { 
372
									sel.removeAllRanges();
373
									sel.collapse();
374
								} catch (err) { }
375
							}
376
						}
377
					});
378
				if(this._get_settings().core.notify_plugins) {
379
					this.get_container()
380
						.bind("load_node.jstree", $.proxy(function (e, data) { 
381
								var o = this._get_node(data.rslt.obj),
382
									t = this;
383
								if(o === -1) { o = this.get_container_ul(); }
384
								if(!o.length) { return; }
385
								o.find("li").each(function () {
386
									var th = $(this);
387
									if(th.data("jstree")) {
388
										$.each(th.data("jstree"), function (plugin, values) {
389
											if(t.data[plugin] && $.isFunction(t["_" + plugin + "_notify"])) {
390
												t["_" + plugin + "_notify"].call(t, th, values);
391
											}
392
										});
393
									}
394
								});
395
							}, this));
396
				}
397
				if(this._get_settings().core.load_open) {
398
					this.get_container()
399
						.bind("load_node.jstree", $.proxy(function (e, data) { 
400
								var o = this._get_node(data.rslt.obj),
401
									t = this;
402
								if(o === -1) { o = this.get_container_ul(); }
403
								if(!o.length) { return; }
404
								o.find("li.jstree-open:not(:has(ul))").each(function () {
405
									t.load_node(this, $.noop, $.noop);
406
								});
407
							}, this));
408
				}
409
				this.__callback();
410
				this.load_node(-1, function () { this.loaded(); this.reload_nodes(); });
411
			},
412
			destroy	: function () { 
413
				var i,
414
					n = this.get_index(),
415
					s = this._get_settings(),
416
					_this = this;
417

  
418
				$.each(s.plugins, function (i, val) {
419
					try { plugins[val].__destroy.apply(_this); } catch(err) { }
420
				});
421
				this.__callback();
422
				// set focus to another instance if this one is focused
423
				if(this.is_focused()) { 
424
					for(i in instances) { 
425
						if(instances.hasOwnProperty(i) && i != n) { 
426
							instances[i].set_focus(); 
427
							break; 
428
						} 
429
					}
430
				}
431
				// if no other instance found
432
				if(n === focused_instance) { focused_instance = -1; }
433
				// remove all traces of jstree in the DOM (only the ones set using jstree*) and cleans all events
434
				this.get_container()
435
					.unbind(".jstree")
436
					.undelegate(".jstree")
437
					.removeData("jstree_instance_id")
438
					.find("[class^='jstree']")
439
						.andSelf()
440
						.attr("class", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); });
441
				$(document)
442
					.unbind(".jstree-" + n)
443
					.undelegate(".jstree-" + n);
444
				// remove the actual data
445
				instances[n] = null;
446
				delete instances[n];
447
			},
448

  
449
			_core_notify : function (n, data) {
450
				if(data.opened) {
451
					this.open_node(n, false, true);
452
				}
453
			},
454

  
455
			lock : function () {
456
				this.data.core.locked = true;
457
				this.get_container().children("ul").addClass("jstree-locked").css("opacity","0.7");
458
				this.__callback({});
459
			},
460
			unlock : function () {
461
				this.data.core.locked = false;
462
				this.get_container().children("ul").removeClass("jstree-locked").css("opacity","1");
463
				this.__callback({});
464
			},
465
			is_locked : function () { return this.data.core.locked; },
466
			save_opened : function () {
467
				var _this = this;
468
				this.data.core.to_open = [];
469
				this.get_container_ul().find("li.jstree-open").each(function () { 
470
					if(this.id) { _this.data.core.to_open.push("#" + this.id.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:")); }
471
				});
472
				this.__callback(_this.data.core.to_open);
473
			},
474
			save_loaded : function () { },
475
			reload_nodes : function (is_callback) {
476
				var _this = this,
477
					done = true,
478
					current = [],
479
					remaining = [];
480
				if(!is_callback) { 
481
					this.data.core.reopen = false; 
482
					this.data.core.refreshing = true; 
483
					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,"\\:"); });
484
					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,"\\:"); });
485
					if(this.data.core.to_open.length) {
486
						this.data.core.to_load = this.data.core.to_load.concat(this.data.core.to_open);
487
					}
488
				}
489
				if(this.data.core.to_load.length) {
490
					$.each(this.data.core.to_load, function (i, val) {
491
						if(val == "#") { return true; }
492
						if($(val).length) { current.push(val); }
493
						else { remaining.push(val); }
494
					});
495
					if(current.length) {
496
						this.data.core.to_load = remaining;
497
						$.each(current, function (i, val) { 
498
							if(!_this._is_loaded(val)) {
499
								_this.load_node(val, function () { _this.reload_nodes(true); }, function () { _this.reload_nodes(true); });
500
								done = false;
501
							}
502
						});
503
					}
504
				}
505
				if(this.data.core.to_open.length) {
506
					$.each(this.data.core.to_open, function (i, val) {
507
						_this.open_node(val, false, true); 
508
					});
509
				}
510
				if(done) { 
511
					// TODO: find a more elegant approach to syncronizing returning requests
512
					if(this.data.core.reopen) { clearTimeout(this.data.core.reopen); }
513
					this.data.core.reopen = setTimeout(function () { _this.__callback({}, _this); }, 50);
514
					this.data.core.refreshing = false;
515
					this.reopen();
516
				}
517
			},
518
			reopen : function () {
519
				var _this = this;
520
				if(this.data.core.to_open.length) {
521
					$.each(this.data.core.to_open, function (i, val) {
522
						_this.open_node(val, false, true); 
523
					});
524
				}
525
				this.__callback({});
526
			},
527
			refresh : function (obj) {
528
				var _this = this;
529
				this.save_opened();
530
				if(!obj) { obj = -1; }
531
				obj = this._get_node(obj);
532
				if(!obj) { obj = -1; }
533
				if(obj !== -1) { obj.children("UL").remove(); }
534
				else { this.get_container_ul().empty(); }
535
				this.load_node(obj, function () { _this.__callback({ "obj" : obj}); _this.reload_nodes(); });
536
			},
537
			// Dummy function to fire after the first load (so that there is a jstree.loaded event)
538
			loaded	: function () { 
539
				this.__callback(); 
540
			},
541
			// deal with focus
542
			set_focus	: function () { 
543
				if(this.is_focused()) { return; }
544
				var f = $.jstree._focused();
545
				if(f) { f.unset_focus(); }
546

  
547
				this.get_container().addClass("jstree-focused"); 
548
				focused_instance = this.get_index(); 
549
				this.__callback();
550
			},
551
			is_focused	: function () { 
552
				return focused_instance == this.get_index(); 
553
			},
554
			unset_focus	: function () {
555
				if(this.is_focused()) {
556
					this.get_container().removeClass("jstree-focused"); 
557
					focused_instance = -1; 
558
				}
559
				this.__callback();
560
			},
561

  
562
			// traverse
563
			_get_node		: function (obj) { 
564
				var $obj = $(obj, this.get_container()); 
565
				if($obj.is(".jstree") || obj == -1) { return -1; } 
566
				$obj = $obj.closest("li", this.get_container()); 
567
				return $obj.length ? $obj : false; 
568
			},
569
			_get_next		: function (obj, strict) {
570
				obj = this._get_node(obj);
571
				if(obj === -1) { return this.get_container().find("> ul > li:first-child"); }
572
				if(!obj.length) { return false; }
573
				if(strict) { return (obj.nextAll("li").size() > 0) ? obj.nextAll("li:eq(0)") : false; }
574

  
575
				if(obj.hasClass("jstree-open")) { return obj.find("li:eq(0)"); }
576
				else if(obj.nextAll("li").size() > 0) { return obj.nextAll("li:eq(0)"); }
577
				else { return obj.parentsUntil(".jstree","li").next("li").eq(0); }
578
			},
579
			_get_prev		: function (obj, strict) {
580
				obj = this._get_node(obj);
581
				if(obj === -1) { return this.get_container().find("> ul > li:last-child"); }
582
				if(!obj.length) { return false; }
583
				if(strict) { return (obj.prevAll("li").length > 0) ? obj.prevAll("li:eq(0)") : false; }
584

  
585
				if(obj.prev("li").length) {
586
					obj = obj.prev("li").eq(0);
587
					while(obj.hasClass("jstree-open")) { obj = obj.children("ul:eq(0)").children("li:last"); }
588
					return obj;
589
				}
590
				else { var o = obj.parentsUntil(".jstree","li:eq(0)"); return o.length ? o : false; }
591
			},
592
			_get_parent		: function (obj) {
593
				obj = this._get_node(obj);
594
				if(obj == -1 || !obj.length) { return false; }
595
				var o = obj.parentsUntil(".jstree", "li:eq(0)");
596
				return o.length ? o : -1;
597
			},
598
			_get_children	: function (obj) {
599
				obj = this._get_node(obj);
600
				if(obj === -1) { return this.get_container().children("ul:eq(0)").children("li"); }
601
				if(!obj.length) { return false; }
602
				return obj.children("ul:eq(0)").children("li");
603
			},
604
			get_path		: function (obj, id_mode) {
605
				var p = [],
606
					_this = this;
607
				obj = this._get_node(obj);
608
				if(obj === -1 || !obj || !obj.length) { return false; }
609
				obj.parentsUntil(".jstree", "li").each(function () {
610
					p.push( id_mode ? this.id : _this.get_text(this) );
611
				});
612
				p.reverse();
613
				p.push( id_mode ? obj.attr("id") : this.get_text(obj) );
614
				return p;
615
			},
616

  
617
			// string functions
618
			_get_string : function (key) {
619
				return this._get_settings().core.strings[key] || key;
620
			},
621

  
622
			is_open		: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-open"); },
623
			is_closed	: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-closed"); },
624
			is_leaf		: function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-leaf"); },
625
			correct_state	: function (obj) {
626
				obj = this._get_node(obj);
627
				if(!obj || obj === -1) { return false; }
628
				obj.removeClass("jstree-closed jstree-open").addClass("jstree-leaf").children("ul").remove();
629
				this.__callback({ "obj" : obj });
630
			},
631
			// open/close
632
			open_node	: function (obj, callback, skip_animation) {
633
				obj = this._get_node(obj);
634
				if(!obj.length) { return false; }
635
				if(!obj.hasClass("jstree-closed")) { if(callback) { callback.call(); } return false; }
636
				var s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation,
637
					t = this;
638
				if(!this._is_loaded(obj)) {
639
					obj.children("a").addClass("jstree-loading");
640
					this.load_node(obj, function () { t.open_node(obj, callback, skip_animation); }, callback);
641
				}
642
				else {
643
					if(this._get_settings().core.open_parents) {
644
						obj.parentsUntil(".jstree",".jstree-closed").each(function () {
645
							t.open_node(this, false, true);
646
						});
647
					}
648
					if(s) { obj.children("ul").css("display","none"); }
649
					obj.removeClass("jstree-closed").addClass("jstree-open").children("a").removeClass("jstree-loading");
650
					if(s) { obj.children("ul").stop(true, true).slideDown(s, function () { this.style.display = ""; t.after_open(obj); }); }
651
					else { t.after_open(obj); }
652
					this.__callback({ "obj" : obj });
653
					if(callback) { callback.call(); }
654
				}
655
			},
656
			after_open	: function (obj) { this.__callback({ "obj" : obj }); },
657
			close_node	: function (obj, skip_animation) {
658
				obj = this._get_node(obj);
659
				var s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation,
660
					t = this;
661
				if(!obj.length || !obj.hasClass("jstree-open")) { return false; }
662
				if(s) { obj.children("ul").attr("style","display:block !important"); }
663
				obj.removeClass("jstree-open").addClass("jstree-closed");
664
				if(s) { obj.children("ul").stop(true, true).slideUp(s, function () { this.style.display = ""; t.after_close(obj); }); }
665
				else { t.after_close(obj); }
666
				this.__callback({ "obj" : obj });
667
			},
668
			after_close	: function (obj) { this.__callback({ "obj" : obj }); },
669
			toggle_node	: function (obj) {
670
				obj = this._get_node(obj);
671
				if(obj.hasClass("jstree-closed")) { return this.open_node(obj); }
672
				if(obj.hasClass("jstree-open")) { return this.close_node(obj); }
673
			},
674
			open_all	: function (obj, do_animation, original_obj) {
675
				obj = obj ? this._get_node(obj) : -1;
676
				if(!obj || obj === -1) { obj = this.get_container_ul(); }
677
				if(original_obj) { 
678
					obj = obj.find("li.jstree-closed");
679
				}
680
				else {
681
					original_obj = obj;
682
					if(obj.is(".jstree-closed")) { obj = obj.find("li.jstree-closed").andSelf(); }
683
					else { obj = obj.find("li.jstree-closed"); }
684
				}
685
				var _this = this;
686
				obj.each(function () { 
687
					var __this = this; 
688
					if(!_this._is_loaded(this)) { _this.open_node(this, function() { _this.open_all(__this, do_animation, original_obj); }, !do_animation); }
689
					else { _this.open_node(this, false, !do_animation); }
690
				});
691
				// so that callback is fired AFTER all nodes are open
692
				if(original_obj.find('li.jstree-closed').length === 0) { this.__callback({ "obj" : original_obj }); }
693
			},
694
			close_all	: function (obj, do_animation) {
695
				var _this = this;
696
				obj = obj ? this._get_node(obj) : this.get_container();
697
				if(!obj || obj === -1) { obj = this.get_container_ul(); }
698
				obj.find("li.jstree-open").andSelf().each(function () { _this.close_node(this, !do_animation); });
699
				this.__callback({ "obj" : obj });
700
			},
701
			clean_node	: function (obj) {
702
				obj = obj && obj != -1 ? $(obj) : this.get_container_ul();
703
				obj = obj.is("li") ? obj.find("li").andSelf() : obj.find("li");
704
				obj.removeClass("jstree-last")
705
					.filter("li:last-child").addClass("jstree-last").end()
706
					.filter(":has(li)")
707
						.not(".jstree-open").removeClass("jstree-leaf").addClass("jstree-closed");
708
				obj.not(".jstree-open, .jstree-closed").addClass("jstree-leaf").children("ul").remove();
709
				this.__callback({ "obj" : obj });
710
			},
711
			// rollback
712
			get_rollback : function () { 
713
				this.__callback();
714
				return { i : this.get_index(), h : this.get_container().children("ul").clone(true), d : this.data }; 
715
			},
716
			set_rollback : function (html, data) {
717
				this.get_container().empty().append(html);
718
				this.data = data;
719
				this.__callback();
720
			},
721
			// Dummy functions to be overwritten by any datastore plugin included
722
			load_node	: function (obj, s_call, e_call) { this.__callback({ "obj" : obj }); },
723
			_is_loaded	: function (obj) { return true; },
724

  
725
			// Basic operations: create
726
			create_node	: function (obj, position, js, callback, is_loaded) {
727
				obj = this._get_node(obj);
728
				position = typeof position === "undefined" ? "last" : position;
729
				var d = $("<li />"),
730
					s = this._get_settings().core,
731
					tmp;
732

  
733
				if(obj !== -1 && !obj.length) { return false; }
734
				if(!is_loaded && !this._is_loaded(obj)) { this.load_node(obj, function () { this.create_node(obj, position, js, callback, true); }); return false; }
735

  
736
				this.__rollback();
737

  
738
				if(typeof js === "string") { js = { "data" : js }; }
739
				if(!js) { js = {}; }
740
				if(js.attr) { d.attr(js.attr); }
741
				if(js.metadata) { d.data(js.metadata); }
742
				if(js.state) { d.addClass("jstree-" + js.state); }
743
				if(!js.data) { js.data = this._get_string("new_node"); }
744
				if(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); }
745
				$.each(js.data, function (i, m) {
746
					tmp = $("<a />");
747
					if($.isFunction(m)) { m = m.call(this, js); }
748
					if(typeof m == "string") { tmp.attr('href','#')[ s.html_titles ? "html" : "text" ](m); }
749
					else {
750
						if(!m.attr) { m.attr = {}; }
751
						if(!m.attr.href) { m.attr.href = '#'; }
752
						tmp.attr(m.attr)[ s.html_titles ? "html" : "text" ](m.title);
753
						if(m.language) { tmp.addClass(m.language); }
754
					}
755
					tmp.prepend("<ins class='jstree-icon'>&#160;</ins>");
756
					if(!m.icon && js.icon) { m.icon = js.icon; }
757
					if(m.icon) { 
758
						if(m.icon.indexOf("/") === -1) { tmp.children("ins").addClass(m.icon); }
759
						else { tmp.children("ins").css("background","url('" + m.icon + "') center center no-repeat"); }
760
					}
761
					d.append(tmp);
762
				});
763
				d.prepend("<ins class='jstree-icon'>&#160;</ins>");
764
				if(obj === -1) {
765
					obj = this.get_container();
766
					if(position === "before") { position = "first"; }
767
					if(position === "after") { position = "last"; }
768
				}
769
				switch(position) {
770
					case "before": obj.before(d); tmp = this._get_parent(obj); break;
771
					case "after" : obj.after(d);  tmp = this._get_parent(obj); break;
772
					case "inside":
773
					case "first" :
774
						if(!obj.children("ul").length) { obj.append("<ul />"); }
775
						obj.children("ul").prepend(d);
776
						tmp = obj;
777
						break;
778
					case "last":
779
						if(!obj.children("ul").length) { obj.append("<ul />"); }
780
						obj.children("ul").append(d);
781
						tmp = obj;
782
						break;
783
					default:
784
						if(!obj.children("ul").length) { obj.append("<ul />"); }
785
						if(!position) { position = 0; }
786
						tmp = obj.children("ul").children("li").eq(position);
787
						if(tmp.length) { tmp.before(d); }
788
						else { obj.children("ul").append(d); }
789
						tmp = obj;
790
						break;
791
				}
792
				if(tmp === -1 || tmp.get(0) === this.get_container().get(0)) { tmp = -1; }
793
				this.clean_node(tmp);
794
				this.__callback({ "obj" : d, "parent" : tmp });
795
				if(callback) { callback.call(this, d); }
796
				return d;
797
			},
798
			// Basic operations: rename (deal with text)
799
			get_text	: function (obj) {
800
				obj = this._get_node(obj);
801
				if(!obj.length) { return false; }
802
				var s = this._get_settings().core.html_titles;
803
				obj = obj.children("a:eq(0)");
804
				if(s) {
805
					obj = obj.clone();
806
					obj.children("INS").remove();
807
					return obj.html();
808
				}
809
				else {
810
					obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];
811
					return obj.nodeValue;
812
				}
813
			},
814
			set_text	: function (obj, val) {
815
				obj = this._get_node(obj);
816
				if(!obj.length) { return false; }
817
				obj = obj.children("a:eq(0)");
818
				if(this._get_settings().core.html_titles) {
819
					var tmp = obj.children("INS").clone();
820
					obj.html(val).prepend(tmp);
821
					this.__callback({ "obj" : obj, "name" : val });
822
					return true;
823
				}
824
				else {
825
					obj = obj.contents().filter(function() { return this.nodeType == 3; })[0];
826
					this.__callback({ "obj" : obj, "name" : val });
827
					return (obj.nodeValue = val);
828
				}
829
			},
830
			rename_node : function (obj, val) {
831
				obj = this._get_node(obj);
832
				this.__rollback();
833
				if(obj && obj.length && this.set_text.apply(this, Array.prototype.slice.call(arguments))) { this.__callback({ "obj" : obj, "name" : val }); }
834
			},
835
			// Basic operations: deleting nodes
836
			delete_node : function (obj) {
837
				obj = this._get_node(obj);
838
				if(!obj.length) { return false; }
839
				this.__rollback();
840
				var p = this._get_parent(obj), prev = $([]), t = this;
841
				obj.each(function () {
842
					prev = prev.add(t._get_prev(this));
843
				});
844
				obj = obj.detach();
845
				if(p !== -1 && p.find("> ul > li").length === 0) {
846
					p.removeClass("jstree-open jstree-closed").addClass("jstree-leaf");
847
				}
848
				this.clean_node(p);
849
				this.__callback({ "obj" : obj, "prev" : prev, "parent" : p });
850
				return obj;
851
			},
852
			prepare_move : function (o, r, pos, cb, is_cb) {
853
				var p = {};
854

  
855
				p.ot = $.jstree._reference(o) || this;
856
				p.o = p.ot._get_node(o);
857
				p.r = r === - 1 ? -1 : this._get_node(r);
858
				p.p = (typeof pos === "undefined" || pos === false) ? "last" : pos; // TODO: move to a setting
859
				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) {
860
					this.__callback(prepared_move);
861
					if(cb) { cb.call(this, prepared_move); }
862
					return;
863
				}
864
				p.ot = $.jstree._reference(p.o) || this;
865
				p.rt = $.jstree._reference(p.r) || this; // r === -1 ? p.ot : $.jstree._reference(p.r) || this
866
				if(p.r === -1 || !p.r) {
867
					p.cr = -1;
868
					switch(p.p) {
869
						case "first":
870
						case "before":
871
						case "inside":
872
							p.cp = 0; 
873
							break;
874
						case "after":
875
						case "last":
876
							p.cp = p.rt.get_container().find(" > ul > li").length; 
877
							break;
878
						default:
879
							p.cp = p.p;
880
							break;
881
					}
882
				}
883
				else {
884
					if(!/^(before|after)$/.test(p.p) && !this._is_loaded(p.r)) {
885
						return this.load_node(p.r, function () { this.prepare_move(o, r, pos, cb, true); });
886
					}
887
					switch(p.p) {
888
						case "before":
889
							p.cp = p.r.index();
890
							p.cr = p.rt._get_parent(p.r);
891
							break;
892
						case "after":
893
							p.cp = p.r.index() + 1;
894
							p.cr = p.rt._get_parent(p.r);
895
							break;
896
						case "inside":
897
						case "first":
898
							p.cp = 0;
899
							p.cr = p.r;
900
							break;
901
						case "last":
902
							p.cp = p.r.find(" > ul > li").length; 
903
							p.cr = p.r;
904
							break;
905
						default: 
906
							p.cp = p.p;
907
							p.cr = p.r;
908
							break;
909
					}
910
				}
911
				p.np = p.cr == -1 ? p.rt.get_container() : p.cr;
912
				p.op = p.ot._get_parent(p.o);
913
				p.cop = p.o.index();
914
				if(p.op === -1) { p.op = p.ot ? p.ot.get_container() : this.get_container(); }
915
				if(!/^(before|after)$/.test(p.p) && p.op && p.np && p.op[0] === p.np[0] && p.o.index() < p.cp) { p.cp++; }
916
				//if(p.p === "before" && p.op && p.np && p.op[0] === p.np[0] && p.o.index() < p.cp) { p.cp--; }
917
				p.or = p.np.find(" > ul > li:nth-child(" + (p.cp + 1) + ")");
918
				prepared_move = p;
919
				this.__callback(prepared_move);
920
				if(cb) { cb.call(this, prepared_move); }
921
			},
922
			check_move : function () {
923
				var obj = prepared_move, ret = true, r = obj.r === -1 ? this.get_container() : obj.r;
924
				if(!obj || !obj.o || obj.or[0] === obj.o[0]) { return false; }
925
				if(!obj.cy) {
926
					if(obj.op && obj.np && obj.op[0] === obj.np[0] && obj.cp - 1 === obj.o.index()) { return false; }
927
					obj.o.each(function () { 
928
						if(r.parentsUntil(".jstree", "li").andSelf().index(this) !== -1) { ret = false; return false; }
929
					});
930
				}
931
				return ret;
932
			},
933
			move_node : function (obj, ref, position, is_copy, is_prepared, skip_check) {
934
				if(!is_prepared) { 
935
					return this.prepare_move(obj, ref, position, function (p) {
936
						this.move_node(p, false, false, is_copy, true, skip_check);
937
					});
938
				}
939
				if(is_copy) { 
940
					prepared_move.cy = true;
941
				}
942
				if(!skip_check && !this.check_move()) { return false; }
943

  
944
				this.__rollback();
945
				var o = false;
946
				if(is_copy) {
947
					o = obj.o.clone(true);
948
					o.find("*[id]").andSelf().each(function () {
949
						if(this.id) { this.id = "copy_" + this.id; }
950
					});
951
				}
952
				else { o = obj.o; }
953

  
954
				if(obj.or.length) { obj.or.before(o); }
955
				else { 
956
					if(!obj.np.children("ul").length) { $("<ul />").appendTo(obj.np); }
957
					obj.np.children("ul:eq(0)").append(o); 
958
				}
959

  
960
				try { 
961
					obj.ot.clean_node(obj.op);
962
					obj.rt.clean_node(obj.np);
963
					if(!obj.op.find("> ul > li").length) {
964
						obj.op.removeClass("jstree-open jstree-closed").addClass("jstree-leaf").children("ul").remove();
965
					}
966
				} catch (e) { }
967

  
968
				if(is_copy) { 
969
					prepared_move.cy = true;
970
					prepared_move.oc = o; 
971
				}
972
				this.__callback(prepared_move);
973
				return prepared_move;
974
			},
975
			_get_move : function () { return prepared_move; }
976
		}
977
	});
978
})(jQuery);
979
//*/
980

  
981
/* 
982
 * jsTree ui plugin
983
 * This plugins handles selecting/deselecting/hovering/dehovering nodes
984
 */
985
(function ($) {
986
	var scrollbar_width, e1, e2;
987
	$(function() {
988
		if (/msie/.test(navigator.userAgent.toLowerCase())) {
989
			e1 = $('<textarea cols="10" rows="2"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body');
990
			e2 = $('<textarea cols="10" rows="2" style="overflow: hidden;"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body');
991
			scrollbar_width = e1.width() - e2.width();
992
			e1.add(e2).remove();
993
		} 
994
		else {
995
			e1 = $('<div />').css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: 0 })
996
					.prependTo('body').append('<div />').find('div').css({ width: '100%', height: 200 });
997
			scrollbar_width = 100 - e1.width();
998
			e1.parent().remove();
999
		}
1000
	});
1001
	$.jstree.plugin("ui", {
1002
		__init : function () { 
1003
			this.data.ui.selected = $(); 
1004
			this.data.ui.last_selected = false; 
1005
			this.data.ui.hovered = null;
1006
			this.data.ui.to_select = this.get_settings().ui.initially_select;
1007

  
1008
			this.get_container()
1009
				.delegate("a", "click.jstree", $.proxy(function (event) {
1010
						event.preventDefault();
1011
						event.currentTarget.blur();
1012
						if(!$(event.currentTarget).hasClass("jstree-loading")) {
1013
							this.select_node(event.currentTarget, true, event);
1014
						}
1015
					}, this))
1016
				.delegate("a", "mouseenter.jstree", $.proxy(function (event) {
1017
						if(!$(event.currentTarget).hasClass("jstree-loading")) {
1018
							this.hover_node(event.target);
1019
						}
1020
					}, this))
1021
				.delegate("a", "mouseleave.jstree", $.proxy(function (event) {
1022
						if(!$(event.currentTarget).hasClass("jstree-loading")) {
1023
							this.dehover_node(event.target);
1024
						}
1025
					}, this))
1026
				.bind("reopen.jstree", $.proxy(function () { 
1027
						this.reselect();
1028
					}, this))
1029
				.bind("get_rollback.jstree", $.proxy(function () { 
1030
						this.dehover_node();
1031
						this.save_selected();
1032
					}, this))
1033
				.bind("set_rollback.jstree", $.proxy(function () { 
1034
						this.reselect();
1035
					}, this))
1036
				.bind("close_node.jstree", $.proxy(function (event, data) { 
1037
						var s = this._get_settings().ui,
1038
							obj = this._get_node(data.rslt.obj),
1039
							clk = (obj && obj.length) ? obj.children("ul").find("a.jstree-clicked") : $(),
1040
							_this = this;
1041
						if(s.selected_parent_close === false || !clk.length) { return; }
1042
						clk.each(function () { 
1043
							_this.deselect_node(this);
1044
							if(s.selected_parent_close === "select_parent") { _this.select_node(obj); }
1045
						});
1046
					}, this))
1047
				.bind("delete_node.jstree", $.proxy(function (event, data) { 
1048
						var s = this._get_settings().ui.select_prev_on_delete,
1049
							obj = this._get_node(data.rslt.obj),
1050
							clk = (obj && obj.length) ? obj.find("a.jstree-clicked") : [],
1051
							_this = this;
1052
						clk.each(function () { _this.deselect_node(this); });
1053
						if(s && clk.length) { 
1054
							data.rslt.prev.each(function () { 
1055
								if(this.parentNode) { _this.select_node(this); return false; /* if return false is removed all prev nodes will be selected */}
1056
							});
1057
						}
1058
					}, this))
1059
				.bind("move_node.jstree", $.proxy(function (event, data) { 
1060
						if(data.rslt.cy) { 
1061
							data.rslt.oc.find("a.jstree-clicked").removeClass("jstree-clicked");
1062
						}
1063
					}, this));
1064
		},
1065
		defaults : {
1066
			select_limit : -1, // 0, 1, 2 ... or -1 for unlimited
1067
			select_multiple_modifier : "ctrl", // on, or ctrl, shift, alt
1068
			select_range_modifier : "shift",
1069
			selected_parent_close : "select_parent", // false, "deselect", "select_parent"
1070
			selected_parent_open : true,
1071
			select_prev_on_delete : true,
1072
			disable_selecting_children : false,
1073
			initially_select : []
1074
		},
1075
		_fn : { 
1076
			_get_node : function (obj, allow_multiple) {
1077
				if(typeof obj === "undefined" || obj === null) { return allow_multiple ? this.data.ui.selected : this.data.ui.last_selected; }
1078
				var $obj = $(obj, this.get_container()); 
1079
				if($obj.is(".jstree") || obj == -1) { return -1; } 
1080
				$obj = $obj.closest("li", this.get_container()); 
1081
				return $obj.length ? $obj : false; 
1082
			},
1083
			_ui_notify : function (n, data) {
1084
				if(data.selected) {
1085
					this.select_node(n, false);
1086
				}
1087
			},
1088
			save_selected : function () {
1089
				var _this = this;
1090
				this.data.ui.to_select = [];
1091
				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,"\\:")); } });
1092
				this.__callback(this.data.ui.to_select);
1093
			},
1094
			reselect : function () {
1095
				var _this = this,
1096
					s = this.data.ui.to_select;
1097
				s = $.map($.makeArray(s), function (n) { return "#" + n.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:"); });
1098
				// this.deselect_all(); WHY deselect, breaks plugin state notifier?
1099
				$.each(s, function (i, val) { if(val && val !== "#") { _this.select_node(val); } });
1100
				this.data.ui.selected = this.data.ui.selected.filter(function () { return this.parentNode; });
1101
				this.__callback();
1102
			},
1103
			refresh : function (obj) {
1104
				this.save_selected();
1105
				return this.__call_old();
1106
			},
1107
			hover_node : function (obj) {
1108
				obj = this._get_node(obj);
1109
				if(!obj.length) { return false; }
1110
				//if(this.data.ui.hovered && obj.get(0) === this.data.ui.hovered.get(0)) { return; }
1111
				if(!obj.hasClass("jstree-hovered")) { this.dehover_node(); }
1112
				this.data.ui.hovered = obj.children("a").addClass("jstree-hovered").parent();
1113
				this._fix_scroll(obj);
1114
				this.__callback({ "obj" : obj });
1115
			},
1116
			dehover_node : function () {
1117
				var obj = this.data.ui.hovered, p;
1118
				if(!obj || !obj.length) { return false; }
1119
				p = obj.children("a").removeClass("jstree-hovered").parent();
1120
				if(this.data.ui.hovered[0] === p[0]) { this.data.ui.hovered = null; }
1121
				this.__callback({ "obj" : obj });
1122
			},
1123
			select_node : function (obj, check, e) {
1124
				obj = this._get_node(obj);
1125
				if(obj == -1 || !obj || !obj.length) { return false; }
1126
				var s = this._get_settings().ui,
1127
					is_multiple = (s.select_multiple_modifier == "on" || (s.select_multiple_modifier !== false && e && e[s.select_multiple_modifier + "Key"])),
1128
					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]),
1129
					is_selected = this.is_selected(obj),
1130
					proceed = true,
1131
					t = this;
1132
				if(check) {
1133
					if(s.disable_selecting_children && is_multiple && 
1134
						(
1135
							(obj.parentsUntil(".jstree","li").children("a.jstree-clicked").length) ||
1136
							(obj.children("ul").find("a.jstree-clicked:eq(0)").length)
1137
						)
1138
					) {
1139
						return false;
1140
					}
1141
					proceed = false;
1142
					switch(!0) {
1143
						case (is_range):
1144
							this.data.ui.last_selected.addClass("jstree-last-selected");
1145
							obj = obj[ obj.index() < this.data.ui.last_selected.index() ? "nextUntil" : "prevUntil" ](".jstree-last-selected").andSelf();
1146
							if(s.select_limit == -1 || obj.length < s.select_limit) {
1147
								this.data.ui.last_selected.removeClass("jstree-last-selected");
1148
								this.data.ui.selected.each(function () {
1149
									if(this !== t.data.ui.last_selected[0]) { t.deselect_node(this); }
1150
								});
1151
								is_selected = false;
1152
								proceed = true;
1153
							}
1154
							else {
1155
								proceed = false;
1156
							}
1157
							break;
1158
						case (is_selected && !is_multiple): 
1159
							this.deselect_all();
1160
							is_selected = false;
1161
							proceed = true;
1162
							break;
1163
						case (!is_selected && !is_multiple): 
1164
							if(s.select_limit == -1 || s.select_limit > 0) {
1165
								this.deselect_all();
1166
								proceed = true;
1167
							}
1168
							break;
1169
						case (is_selected && is_multiple): 
1170
							this.deselect_node(obj);
1171
							break;
1172
						case (!is_selected && is_multiple): 
1173
							if(s.select_limit == -1 || this.data.ui.selected.length + 1 <= s.select_limit) { 
1174
								proceed = true;
1175
							}
1176
							break;
1177
					}
1178
				}
1179
				if(proceed && !is_selected) {
1180
					if(!is_range) { this.data.ui.last_selected = obj; }
1181
					obj.children("a").addClass("jstree-clicked");
1182
					if(s.selected_parent_open) {
1183
						obj.parents(".jstree-closed").each(function () { t.open_node(this, false, true); });
1184
					}
1185
					this.data.ui.selected = this.data.ui.selected.add(obj);
1186
					this._fix_scroll(obj.eq(0));
1187
					this.__callback({ "obj" : obj, "e" : e });
1188
				}
1189
			},
1190
			_fix_scroll : function (obj) {
1191
				var c = this.get_container()[0], t;
1192
				if(c.scrollHeight > c.offsetHeight) {
1193
					obj = this._get_node(obj);
1194
					if(!obj || obj === -1 || !obj.length || !obj.is(":visible")) { return; }
1195
					t = obj.offset().top - this.get_container().offset().top;
1196
					if(t < 0) { 
1197
						c.scrollTop = c.scrollTop + t - 1; 
1198
					}
1199
					if(t + this.data.core.li_height + (c.scrollWidth > c.offsetWidth ? scrollbar_width : 0) > c.offsetHeight) { 
1200
						c.scrollTop = c.scrollTop + (t - c.offsetHeight + this.data.core.li_height + 1 + (c.scrollWidth > c.offsetWidth ? scrollbar_width : 0)); 
1201
					}
1202
				}
1203
			},
1204
			deselect_node : function (obj) {
1205
				obj = this._get_node(obj);
1206
				if(!obj.length) { return false; }
1207
				if(this.is_selected(obj)) {
1208
					obj.children("a").removeClass("jstree-clicked");
1209
					this.data.ui.selected = this.data.ui.selected.not(obj);
1210
					if(this.data.ui.last_selected.get(0) === obj.get(0)) { this.data.ui.last_selected = this.data.ui.selected.eq(0); }
1211
					this.__callback({ "obj" : obj });
1212
				}
1213
			},
1214
			toggle_select : function (obj) {
1215
				obj = this._get_node(obj);
1216
				if(!obj.length) { return false; }
1217
				if(this.is_selected(obj)) { this.deselect_node(obj); }
1218
				else { this.select_node(obj); }
1219
			},
1220
			is_selected : function (obj) { return this.data.ui.selected.index(this._get_node(obj)) >= 0; },
1221
			get_selected : function (context) { 
1222
				return context ? $(context).find("a.jstree-clicked").parent() : this.data.ui.selected; 
1223
			},
1224
			deselect_all : function (context) {
1225
				var ret = context ? $(context).find("a.jstree-clicked").parent() : this.get_container().find("a.jstree-clicked").parent();
1226
				ret.children("a.jstree-clicked").removeClass("jstree-clicked");
1227
				this.data.ui.selected = $([]);
1228
				this.data.ui.last_selected = false;
1229
				this.__callback({ "obj" : ret });
1230
			}
1231
		}
1232
	});
1233
	// include the selection plugin by default
1234
	$.jstree.defaults.plugins.push("ui");
1235
})(jQuery);
1236
//*/
1237

  
1238
/* 
1239
 * jsTree CRRM plugin
1240
 * Handles creating/renaming/removing/moving nodes by user interaction.
1241
 */
1242
(function ($) {
1243
	$.jstree.plugin("crrm", { 
1244
		__init : function () {
1245
			this.get_container()
1246
				.bind("move_node.jstree", $.proxy(function (e, data) {
1247
					if(this._get_settings().crrm.move.open_onmove) {
1248
						var t = this;
1249
						data.rslt.np.parentsUntil(".jstree").andSelf().filter(".jstree-closed").each(function () {
1250
							t.open_node(this, false, true);
1251
						});
1252
					}
1253
				}, this));
1254
		},
1255
		defaults : {
1256
			input_width_limit : 200,
1257
			move : {
1258
				always_copy			: false, // false, true or "multitree"
1259
				open_onmove			: true,
1260
				default_position	: "last",
1261
				check_move			: function (m) { return true; }
1262
			}
1263
		},
1264
		_fn : {
1265
			_show_input : function (obj, callback) {
1266
				obj = this._get_node(obj);
1267
				var rtl = this._get_settings().core.rtl,
1268
					w = this._get_settings().crrm.input_width_limit,
1269
					w1 = obj.children("ins").width(),
1270
					w2 = obj.find("> a:visible > ins").width() * obj.find("> a:visible > ins").length,
1271
					t = this.get_text(obj),
1272
					h1 = $("<div />", { css : { "position" : "absolute", "top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility" : "hidden" } }).appendTo("body"),
1273
					h2 = obj.css("position","relative").append(
1274
					$("<input />", { 
1275
						"value" : t,
1276
						"class" : "jstree-rename-input",
1277
						// "size" : t.length,
1278
						"css" : {
1279
							"padding" : "0",
1280
							"border" : "1px solid silver",
1281
							"position" : "absolute",
1282
							"left"  : (rtl ? "auto" : (w1 + w2 + 4) + "px"),
1283
							"right" : (rtl ? (w1 + w2 + 4) + "px" : "auto"),
1284
							"top" : "0px",
1285
							"height" : (this.data.core.li_height - 2) + "px",
1286
							"lineHeight" : (this.data.core.li_height - 2) + "px",
1287
							"width" : "150px" // will be set a bit further down
1288
						},
1289
						"blur" : $.proxy(function () {
1290
							var i = obj.children(".jstree-rename-input"),
1291
								v = i.val();
1292
							if(v === "") { v = t; }
1293
							h1.remove();
1294
							i.remove(); // rollback purposes
1295
							this.set_text(obj,t); // rollback purposes
1296
							this.rename_node(obj, v);
1297
							callback.call(this, obj, v, t);
1298
							obj.css("position","");
1299
						}, this),
1300
						"keyup" : function (event) {
1301
							var key = event.keyCode || event.which;
1302
							if(key == 27) { this.value = t; this.blur(); return; }
1303
							else if(key == 13) { this.blur(); return; }
1304
							else {
1305
								h2.width(Math.min(h1.text("pW" + this.value).width(),w));
1306
							}
1307
						},
1308
						"keypress" : function(event) {
1309
							var key = event.keyCode || event.which;
1310
							if(key == 13) { return false; }
1311
						}
1312
					})
1313
				).children(".jstree-rename-input"); 
1314
				this.set_text(obj, "");
1315
				h1.css({
1316
						fontFamily		: h2.css('fontFamily')		|| '',
1317
						fontSize		: h2.css('fontSize')		|| '',
1318
						fontWeight		: h2.css('fontWeight')		|| '',
1319
						fontStyle		: h2.css('fontStyle')		|| '',
1320
						fontStretch		: h2.css('fontStretch')		|| '',
1321
						fontVariant		: h2.css('fontVariant')		|| '',
1322
						letterSpacing	: h2.css('letterSpacing')	|| '',
1323
						wordSpacing		: h2.css('wordSpacing')		|| ''
1324
				});
1325
				h2.width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select();
1326
			},
1327
			rename : function (obj) {
1328
				obj = this._get_node(obj);
1329
				this.__rollback();
1330
				var f = this.__callback;
1331
				this._show_input(obj, function (obj, new_name, old_name) { 
1332
					f.call(this, { "obj" : obj, "new_name" : new_name, "old_name" : old_name });
1333
				});
1334
			},
1335
			create : function (obj, position, js, callback, skip_rename) {
1336
				var t, _this = this;
1337
				obj = this._get_node(obj);
1338
				if(!obj) { obj = -1; }
1339
				this.__rollback();
1340
				t = this.create_node(obj, position, js, function (t) {
1341
					var p = this._get_parent(t),
1342
						pos = $(t).index();
1343
					if(callback) { callback.call(this, t); }
1344
					if(p.length && p.hasClass("jstree-closed")) { this.open_node(p, false, true); }
1345
					if(!skip_rename) { 
1346
						this._show_input(t, function (obj, new_name, old_name) { 
1347
							_this.__callback({ "obj" : obj, "name" : new_name, "parent" : p, "position" : pos });
1348
						});
1349
					}
1350
					else { _this.__callback({ "obj" : t, "name" : this.get_text(t), "parent" : p, "position" : pos }); }
1351
				});
1352
				return t;
1353
			},
1354
			remove : function (obj) {
1355
				obj = this._get_node(obj, true);
1356
				var p = this._get_parent(obj), prev = this._get_prev(obj);
1357
				this.__rollback();
1358
				obj = this.delete_node(obj);
1359
				if(obj !== false) { this.__callback({ "obj" : obj, "prev" : prev, "parent" : p }); }
1360
			},
1361
			check_move : function () {
1362
				if(!this.__call_old()) { return false; }
1363
				var s = this._get_settings().crrm.move;
1364
				if(!s.check_move.call(this, this._get_move())) { return false; }
1365
				return true;
1366
			},
1367
			move_node : function (obj, ref, position, is_copy, is_prepared, skip_check) {
1368
				var s = this._get_settings().crrm.move;
1369
				if(!is_prepared) { 
1370
					if(typeof position === "undefined") { position = s.default_position; }
1371
					if(position === "inside" && !s.default_position.match(/^(before|after)$/)) { position = s.default_position; }
1372
					return this.__call_old(true, obj, ref, position, is_copy, false, skip_check);
1373
				}
1374
				// if the move is already prepared
1375
				if(s.always_copy === true || (s.always_copy === "multitree" && obj.rt.get_index() !== obj.ot.get_index() )) {
1376
					is_copy = true;
1377
				}
1378
				this.__call_old(true, obj, ref, position, is_copy, true, skip_check);
1379
			},
1380

  
1381
			cut : function (obj) {
1382
				obj = this._get_node(obj, true);
1383
				if(!obj || !obj.length) { return false; }
1384
				this.data.crrm.cp_nodes = false;
1385
				this.data.crrm.ct_nodes = obj;
1386
				this.__callback({ "obj" : obj });
1387
			},
1388
			copy : function (obj) {
1389
				obj = this._get_node(obj, true);
1390
				if(!obj || !obj.length) { return false; }
1391
				this.data.crrm.ct_nodes = false;
1392
				this.data.crrm.cp_nodes = obj;
1393
				this.__callback({ "obj" : obj });
1394
			},
1395
			paste : function (obj) { 
1396
				obj = this._get_node(obj);
1397
				if(!obj || !obj.length) { return false; }
1398
				var nodes = this.data.crrm.ct_nodes ? this.data.crrm.ct_nodes : this.data.crrm.cp_nodes;
1399
				if(!this.data.crrm.ct_nodes && !this.data.crrm.cp_nodes) { return false; }
1400
				if(this.data.crrm.ct_nodes) { this.move_node(this.data.crrm.ct_nodes, obj); this.data.crrm.ct_nodes = false; }
1401
				if(this.data.crrm.cp_nodes) { this.move_node(this.data.crrm.cp_nodes, obj, false, true); }
1402
				this.__callback({ "obj" : obj, "nodes" : nodes });
1403
			}
1404
		}
1405
	});
1406
	// include the crr plugin by default
1407
	// $.jstree.defaults.plugins.push("crrm");
1408
})(jQuery);
1409
//*/
1410

  
1411
/* 
1412
 * jsTree themes plugin
1413
 * Handles loading and setting themes, as well as detecting path to themes, etc.
1414
 */
1415
(function ($) {
1416
	var themes_loaded = [];
1417
	// this variable stores the path to the themes folder - if left as false - it will be autodetected
1418
	$.jstree._themes = false;
1419
	$.jstree.plugin("themes", {
1420
		__init : function () { 
1421
			this.get_container()
1422
				.bind("init.jstree", $.proxy(function () {
1423
						var s = this._get_settings().themes;
1424
						this.data.themes.dots = s.dots; 
1425
						this.data.themes.icons = s.icons; 
1426
						this.set_theme(s.theme, s.url);
1427
					}, this))
1428
				.bind("loaded.jstree", $.proxy(function () {
1429
						// bound here too, as simple HTML tree's won't honor dots & icons otherwise
1430
						if(!this.data.themes.dots) { this.hide_dots(); }
1431
						else { this.show_dots(); }
1432
						if(!this.data.themes.icons) { this.hide_icons(); }
1433
						else { this.show_icons(); }
1434
					}, this));
1435
		},
1436
		defaults : { 
1437
			theme : "default", 
1438
			url : false,
1439
			dots : true,
1440
			icons : true
1441
		},
1442
		_fn : {
1443
			set_theme : function (theme_name, theme_url) {
1444
				if(!theme_name) { return false; }
1445
				if(!theme_url) { theme_url = $.jstree._themes + theme_name + '/style.css'; }
1446
				if($.inArray(theme_url, themes_loaded) == -1) {
1447
					$.vakata.css.add_sheet({ "url" : theme_url });
1448
					themes_loaded.push(theme_url);
1449
				}
1450
				if(this.data.themes.theme != theme_name) {
1451
					this.get_container().removeClass('jstree-' + this.data.themes.theme);
1452
					this.data.themes.theme = theme_name;
1453
				}
1454
				this.get_container().addClass('jstree-' + theme_name);
1455
				if(!this.data.themes.dots) { this.hide_dots(); }
1456
				else { this.show_dots(); }
1457
				if(!this.data.themes.icons) { this.hide_icons(); }
... Dieser Diff wurde abgeschnitten, weil er die maximale Anzahl anzuzeigender Zeilen überschreitet.

Auch abrufbar als: Unified diff