[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Fmsystem-commits] [14436] update treeview from upstream
From: |
Sigurd Nes |
Subject: |
[Fmsystem-commits] [14436] update treeview from upstream |
Date: |
Fri, 20 Nov 2015 15:05:42 +0000 |
Revision: 14436
http://svn.sv.gnu.org/viewvc/?view=rev&root=fmsystem&revision=14436
Author: sigurdne
Date: 2015-11-20 15:05:42 +0000 (Fri, 20 Nov 2015)
Log Message:
-----------
update treeview from upstream
Modified Paths:
--------------
branches/dev-syncromind/phpgwapi/js/jquery/treeview/jstree.js
branches/dev-syncromind/phpgwapi/js/jquery/treeview/jstree.min.js
branches/dev-syncromind/phpgwapi/js/jquery/treeview/themes/default/style.css
branches/dev-syncromind/phpgwapi/js/jquery/treeview/themes/default/style.min.css
branches/dev-syncromind/phpgwapi/js/jquery/treeview/themes/default-dark/style.css
branches/dev-syncromind/phpgwapi/js/jquery/treeview/themes/default-dark/style.min.css
Modified: branches/dev-syncromind/phpgwapi/js/jquery/treeview/jstree.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/jquery/treeview/jstree.js
2015-11-20 15:01:27 UTC (rev 14435)
+++ branches/dev-syncromind/phpgwapi/js/jquery/treeview/jstree.js
2015-11-20 15:05:42 UTC (rev 14436)
@@ -1,11 +1,11 @@
-/*globals jQuery, define, exports, require, window, document, postMessage */
+/*globals jQuery, define, module, exports, require, window, document,
postMessage */
(function (factory) {
"use strict";
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
}
- else if(typeof exports === 'object') {
- factory(require('jquery'));
+ else if(typeof module !== 'undefined' && module.exports) {
+ module.exports = factory(require('jquery'));
}
else {
factory(jQuery);
@@ -13,7 +13,7 @@
}(function ($, undefined) {
"use strict";
/*!
- * jsTree 3.0.8
+ * jsTree 3.2.1
* http://jstree.com/
*
* Copyright (c) 2014 Ivan Bozhanov (http://vakata.com)
@@ -22,7 +22,7 @@
* http://www.opensource.org/licenses/mit-license.php
*/
/*!
- * if using jslint please allow for the jQuery global and use following
options:
+ * if using jslint please allow for the jQuery global and use following
options:
* jslint: browser: true, ass: true, bitwise: true, continue: true, nomen:
true, plusplus: true, regexp: true, unparam: true, todo: true, white: true
*/
@@ -42,18 +42,19 @@
ccp_inst = false,
themes_loaded = [],
src = $('script:last').attr('src'),
- _d = document, _node = _d.createElement('LI'), _temp1, _temp2;
+ document = window.document, // local variable is always faster
to access then a global
+ _node = document.createElement('LI'), _temp1, _temp2;
_node.setAttribute('role', 'treeitem');
- _temp1 = _d.createElement('I');
+ _temp1 = document.createElement('I');
_temp1.className = 'jstree-icon jstree-ocl';
_temp1.setAttribute('role', 'presentation');
_node.appendChild(_temp1);
- _temp1 = _d.createElement('A');
+ _temp1 = document.createElement('A');
_temp1.className = 'jstree-anchor';
_temp1.setAttribute('href','#');
_temp1.setAttribute('tabindex','-1');
- _temp2 = _d.createElement('I');
+ _temp2 = document.createElement('I');
_temp2.className = 'jstree-icon jstree-themeicon';
_temp2.setAttribute('role', 'presentation');
_temp1.appendChild(_temp2);
@@ -66,11 +67,11 @@
* @name $.jstree
*/
$.jstree = {
- /**
+ /**
* specifies the jstree version in use
* @name $.jstree.version
*/
- version : '3.0.8',
+ version : '3.2.1',
/**
* holds all the default options used when creating new
instances
* @name $.jstree.defaults
@@ -88,7 +89,8 @@
*/
plugins : {},
path : src && src.indexOf('/') !== -1 ?
src.replace(/\/[^\/]+$/,'') : '',
- idregex : /[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%]/g
+ idregex : /[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g,
+ root : '#'
};
/**
* creates a jstree instance
@@ -109,6 +111,7 @@
tmp = tmp.plugin(k, options[k]);
}
});
+ $(el).data('jstree', tmp);
tmp.init(el, options);
return tmp;
};
@@ -168,7 +171,7 @@
$.jstree.reference = function (needle) {
var tmp = null,
obj = null;
- if(needle && needle.id) { needle = needle.id; }
+ if(needle && needle.id && (!needle.tagName ||
!needle.nodeType)) { needle = needle.id; }
if(!obj || !obj.length) {
try { obj = $(needle); } catch (ignore) { }
@@ -191,14 +194,14 @@
return tmp;
};
/**
- * Create an instance, get an instance or invoke a command on a
instance.
- *
+ * Create an instance, get an instance or invoke a command on a
instance.
+ *
* If there is no instance associated with the current node a new one
is created and `arg` is used to extend `$.jstree.defaults` for this new
instance. There would be no return value (chaining is not broken).
- *
+ *
* If there is an existing instance and `arg` is a string the command
specified by `arg` is executed on the instance, with any additional arguments
passed to the function. If the function returns a value it will be returned
(chaining could break depending on function).
- *
+ *
* If there is an existing instance and `arg` is not a string the
instance itself is returned (similar to `$.jstree.reference`).
- *
+ *
* In any other case - nothing is returned and chaining is not broken.
*
* __Examples__
@@ -230,7 +233,7 @@
null;
// if there is no instance and no method is being
called - create one
if(!instance && !is_method && (arg === undefined ||
$.isPlainObject(arg))) {
- $(this).data('jstree', new
$.jstree.create(this, arg));
+ $.jstree.create(this, arg);
}
// if there is an instance and no method is called -
return the instance
if( (instance && !is_method) || arg === true ) {
@@ -271,14 +274,14 @@
$.jstree.defaults.core = {
/**
* data configuration
- *
+ *
* If left as `false` the HTML inside the jstree container
element is used to populate the tree (that should be an unordered list with
list items).
*
* You can also pass in a HTML string or a JSON array here.
- *
- * It is possible to pass in a standard jQuery-like AJAX config
and jstree will automatically determine if the response is JSON or HTML and use
that to populate the tree.
+ *
+ * It is possible to pass in a standard jQuery-like AJAX config
and jstree will automatically determine if the response is JSON or HTML and use
that to populate the tree.
* In addition to the standard jQuery ajax options here you can
suppy functions for `data` and `url`, the functions will be run in the current
instance's scope and a param will be passed indicating which node is being
loaded, the return value of those functions will be used.
- *
+ *
* The last option is to specify a function, that function will
receive the node being loaded as argument and a second param which is a
function which should be called with the result.
*
* __Examples__
@@ -307,7 +310,7 @@
* }
* ]
* });
- *
+ *
* // function
* $('#tree').jstree({
* 'core' : {
@@ -315,7 +318,7 @@
* callback.call(this, ['Root 1',
'Root 2']);
* }
* });
- *
+ *
* @name $.jstree.defaults.core.data
*/
data : false,
@@ -355,7 +358,7 @@
* }
* }
* });
- *
+ *
* @name $.jstree.defaults.core.check_callback
*/
check_callback : false,
@@ -434,7 +437,12 @@
* Force node text to plain text (and escape HTML). Defaults to
`false`
* @name $.jstree.defaults.core.force_text
*/
- force_text : false
+ force_text : false,
+ /**
+ * Should the node should be toggled if the text is double
clicked . Defaults to `true`
+ * @name $.jstree.defaults.core.dblclick_toggle
+ */
+ dblclick_toggle : true
};
$.jstree.core.prototype = {
/**
@@ -455,7 +463,7 @@
return this;
},
/**
- * used to decorate an instance with a plugin. Used internally.
+ * initialize the instance. Used internally.
* @private
* @name init(el, optons)
* @param {DOMElement|jQuery|String} el the element we are
transforming
@@ -464,16 +472,7 @@
*/
init : function (el, options) {
this._model = {
- data : {
- '#' : {
- id : '#',
- parent : null,
- parents : [],
- children : [],
- children_d : [],
- state : { loaded : false }
- }
- },
+ data : {},
changed : [],
force_full_redraw : false,
redraw_timeout : false,
@@ -484,10 +483,17 @@
disabled : false
}
};
+ this._model.data[$.jstree.root] = {
+ id : $.jstree.root,
+ parent : null,
+ parents : [],
+ children : [],
+ children_d : [],
+ state : { loaded : false }
+ };
this.element = $(el).addClass('jstree jstree-' +
this._id);
this.settings = options;
- this.element.bind("destroyed", $.proxy(this.teardown,
this));
this._data.core.ready = false;
this._data.core.loaded = false;
@@ -525,7 +531,7 @@
* @name loading.jstree
*/
this.trigger("loading");
- this.load_node('#');
+ this.load_node($.jstree.root);
},
/**
* destroy an instance
@@ -541,7 +547,6 @@
catch (ignore) { }
}
if(!keep_html) { this.element.empty(); }
- this.element.unbind("destroyed", this.teardown);
this.teardown();
},
/**
@@ -566,9 +571,11 @@
*/
bind : function () {
var word = '',
- tout = null;
+ tout = null,
+ was_click = 0;
this.element
- .on("dblclick.jstree", function () {
+ .on("dblclick.jstree", function (e) {
+ if(e.target.tagName &&
e.target.tagName.toLowerCase() === "input") { return true; }
if(document.selection &&
document.selection.empty) {
document.selection.empty();
}
@@ -582,16 +589,32 @@
}
}
})
+ .on("mousedown.jstree", $.proxy(function (e) {
+ if(e.target ===
this.element[0]) {
+ e.preventDefault(); //
prevent losing focus when clicking scroll arrows (FF, Chrome)
+ was_click = +(new
Date()); // ie does not allow to prevent losing focus
+ }
+ }, this))
+ .on("mousedown.jstree", ".jstree-ocl", function
(e) {
+ e.preventDefault(); // prevent
any node inside from losing focus when clicking the open/close icon
+ })
.on("click.jstree", ".jstree-ocl",
$.proxy(function (e) {
this.toggle_node(e.target);
}, this))
+ .on("dblclick.jstree", ".jstree-anchor",
$.proxy(function (e) {
+ if(e.target.tagName &&
e.target.tagName.toLowerCase() === "input") { return true; }
+
if(this.settings.core.dblclick_toggle) {
+
this.toggle_node(e.target);
+ }
+ }, this))
.on("click.jstree", ".jstree-anchor",
$.proxy(function (e) {
e.preventDefault();
if(e.currentTarget !==
document.activeElement) { $(e.currentTarget).focus(); }
this.activate_node(e.currentTarget, e);
}, this))
.on('keydown.jstree', '.jstree-anchor',
$.proxy(function (e) {
- if(e.target.tagName ===
"INPUT") { return true; }
+ if(e.target.tagName &&
e.target.tagName.toLowerCase() === "input") { return true; }
+ if(e.which !== 32 && e.which
!== 13 && (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey)) { return true; }
var o = null;
if(this._data.core.rtl) {
if(e.which === 37) {
e.which = 39; }
@@ -615,7 +638,7 @@
}
else {
o =
this.get_parent(e.currentTarget);
- if(o &&
o.id !== '#') { this.get_node(o, true).children('.jstree-anchor').focus(); }
+ if(o &&
o.id !== $.jstree.root) { this.get_node(o,
true).children('.jstree-anchor').focus(); }
}
break;
case 38: // up
@@ -650,12 +673,12 @@
e.preventDefault();
this.element.find('.jstree-anchor').filter(':visible').last().focus();
break;
- /*
+ /*!
// delete
case 46:
e.preventDefault();
o =
this.get_node(e.currentTarget);
- if(o && o.id &&
o.id !== '#') {
+ if(o && o.id &&
o.id !== $.jstree.root) {
o =
this.is_selected(o) ? this.get_selected() : o;
this.delete_node(o);
}
@@ -664,7 +687,7 @@
case 113:
e.preventDefault();
o =
this.get_node(e.currentTarget);
- if(o && o.id &&
o.id !== '#') {
+ if(o && o.id &&
o.id !== $.jstree.root) {
//
this.edit(o);
}
break;
@@ -676,7 +699,7 @@
}, this))
.on("load_node.jstree", $.proxy(function (e,
data) {
if(data.status) {
- if(data.node.id === '#'
&& !this._data.core.loaded) {
+ if(data.node.id ===
$.jstree.root && !this._data.core.loaded) {
this._data.core.loaded = true;
if(this._firstChild(this.get_container_ul()[0])) {
this.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).id);
@@ -688,33 +711,37 @@
*/
this.trigger("loaded");
}
-
if(!this._data.core.ready &&
!this.get_container_ul().find('.jstree-loading').length) {
-
this._data.core.ready = true;
-
if(this._data.core.selected.length) {
-
if(this.settings.core.expand_selected_onload) {
-
var tmp = [], i, j;
-
for(i = 0, j = this._data.core.selected.length; i < j; i++) {
-
tmp = tmp.concat(this._model.data[this._data.core.selected[i]].parents);
+
if(!this._data.core.ready) {
+
setTimeout($.proxy(function() {
+
if(this.element && !this.get_container_ul().find('.jstree-loading').length) {
+
this._data.core.ready = true;
+
if(this._data.core.selected.length) {
+
if(this.settings.core.expand_selected_onload) {
+
var tmp = [], i, j;
+
for(i = 0, j = this._data.core.selected.length; i < j; i++) {
+
tmp =
tmp.concat(this._model.data[this._data.core.selected[i]].parents);
+
}
+
tmp = $.vakata.array_unique(tmp);
+
for(i = 0, j = tmp.length; i < j; i++) {
+
this.open_node(tmp[i], false, 0);
+
}
+
}
+
this.trigger('changed', { 'action' : 'ready', 'selected' :
this._data.core.selected });
}
-
tmp = $.vakata.array_unique(tmp);
-
for(i = 0, j = tmp.length; i < j; i++) {
-
this.open_node(tmp[i], false, 0);
-
}
+
/**
+
* triggered after all nodes are finished loading
+
* @event
+
* @name ready.jstree
+
*/
+
this.trigger("ready");
}
-
this.trigger('changed', { 'action' : 'ready', 'selected' :
this._data.core.selected });
- }
- /**
- * triggered
after all nodes are finished loading
- * @event
- * @name
ready.jstree
- */
-
setTimeout($.proxy(function () { this.trigger("ready"); }, this), 0);
+ }, this), 0);
}
}
}, this))
// quick searching when the tree is focused
.on('keypress.jstree', $.proxy(function (e) {
- if(e.target.tagName ===
"INPUT") { return true; }
+ if(e.target.tagName &&
e.target.tagName.toLowerCase() === "input") { return true; }
if(tout) { clearTimeout(tout); }
tout = setTimeout(function () {
word = '';
@@ -748,7 +775,7 @@
if(end) { return; }
}
// list nodes that start with
that letter (only if word consists of a single char)
- if(new RegExp('^' + chr +
'+$').test(word)) {
+ if(new RegExp('^' +
chr.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '+$').test(word)) {
// search for the next
node starting with that letter
col.slice(ind +
1).each($.proxy(function (i, v) {
if($(v).text().toLowerCase().charAt(0) === chr) {
@@ -787,6 +814,7 @@
.on('blur.jstree', '.jstree-anchor',
$.proxy(function (e) {
this._data.core.focused = null;
$(e.currentTarget).filter('.jstree-hovered').mouseleave();
+ this.element.attr('tabindex',
'0');
}, this))
.on('focus.jstree', '.jstree-anchor',
$.proxy(function (e) {
var tmp =
this.get_node(e.currentTarget);
@@ -795,10 +823,15 @@
}
this.element.find('.jstree-hovered').not(e.currentTarget).mouseleave();
$(e.currentTarget).mouseenter();
+ this.element.attr('tabindex',
'-1');
}, this))
.on('focus.jstree', $.proxy(function () {
- if(!this._data.core.focused) {
-
this.get_node(this.element.attr('aria-activedescendant'), true).find('>
.jstree-anchor').focus();
+ if(+(new Date()) - was_click >
500 && !this._data.core.focused) {
+ was_click = 0;
+ var act =
this.get_node(this.element.attr('aria-activedescendant'), true);
+ if(act) {
+ act.find('>
.jstree-anchor').focus();
+ }
}
}, this))
.on('mouseenter.jstree', '.jstree-anchor',
$.proxy(function (e) {
@@ -929,14 +962,14 @@
obj =
this._model.data[dom.closest('.jstree-node').attr('id')];
}
else if((dom = $(obj, this.element)).length &&
dom.hasClass('jstree')) {
- obj = this._model.data['#'];
+ obj = this._model.data[$.jstree.root];
}
else {
return false;
}
if(as_dom) {
- obj = obj.id === '#' ? this.element :
$('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element);
+ obj = obj.id === $.jstree.root ?
this.element : $('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element);
}
return obj;
} catch (ex) { return false; }
@@ -951,7 +984,7 @@
*/
get_path : function (obj, glue, ids) {
obj = obj.parents ? obj : this.get_node(obj);
- if(!obj || obj.id === '#' || !obj.parents) {
+ if(!obj || obj.id === $.jstree.root || !obj.parents) {
return false;
}
var i, j, p = [];
@@ -1005,7 +1038,7 @@
if(tmp !== null) {
return $(tmp);
}
- return
obj.parentsUntil(".jstree",".jstree-node").next(".jstree-node:visible").first();
+ return
obj.parentsUntil(".jstree",".jstree-node").nextAll(".jstree-node:visible").first();
},
/**
* get the previous visible node that is above the `obj` node.
If `strict` is set to `true` only sibling nodes are returned.
@@ -1056,7 +1089,7 @@
*/
get_parent : function (obj) {
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
return obj.parent;
@@ -1174,14 +1207,22 @@
this.trigger('changed', { 'action' :
'load_node', 'node' : obj, 'selected' : this._data.core.selected });
}
}
+ obj.state.failed = false;
obj.state.loading = true;
this.get_node(obj,
true).addClass("jstree-loading").attr('aria-busy',true);
this._load_node(obj, $.proxy(function (status) {
obj = this._model.data[obj.id];
obj.state.loading = false;
obj.state.loaded = status;
- var dom = this.get_node(obj, true);
- if(obj.state.loaded && !obj.children.length &&
dom && dom.length && !dom.hasClass('jstree-leaf')) {
+ obj.state.failed = !obj.state.loaded;
+ var dom = this.get_node(obj, true), i = 0, j =
0, m = this._model.data, has_children = false;
+ for(i = 0, j = obj.children.length; i < j; i++)
{
+ if(m[obj.children[i]] &&
!m[obj.children[i]].state.hidden) {
+ has_children = true;
+ break;
+ }
+ }
+ if(obj.state.loaded && !has_children && dom &&
dom.length && !dom.hasClass('jstree-leaf')) {
dom.removeClass('jstree-closed
jstree-open').addClass('jstree-leaf');
}
dom.removeClass("jstree-loading").attr('aria-busy',false);
@@ -1209,9 +1250,9 @@
_load_nodes : function (nodes, callback, is_callback) {
var r = true,
c = function () { this._load_nodes(nodes,
callback, true); },
- m = this._model.data, i, j;
+ m = this._model.data, i, j, tmp = [];
for(i = 0, j = nodes.length; i < j; i++) {
- if(m[nodes[i]] && (!m[nodes[i]].state.loaded ||
!is_callback)) {
+ if(m[nodes[i]] && ( (!m[nodes[i]].state.loaded
&& !m[nodes[i]].state.failed) || !is_callback)) {
if(!this.is_loading(nodes[i])) {
this.load_node(nodes[i], c);
}
@@ -1219,8 +1260,13 @@
}
}
if(r) {
+ for(i = 0, j = nodes.length; i < j; i++) {
+ if(m[nodes[i]] &&
m[nodes[i]].state.loaded) {
+ tmp.push(nodes[i]);
+ }
+ }
if(callback && !callback.done) {
- callback.call(this, nodes);
+ callback.call(this, tmp);
callback.done = true;
}
}
@@ -1233,7 +1279,7 @@
* @trigger load_all.jstree
*/
load_all : function (obj, callback) {
- if(!obj) { obj = '#'; }
+ if(!obj) { obj = $.jstree.root; }
obj = this.get_node(obj);
if(!obj) { return false; }
var to_load = [],
@@ -1276,7 +1322,7 @@
var s = this.settings.core.data, t;
// use original HTML
if(!s) {
- if(obj.id === '#') {
+ if(obj.id === $.jstree.root) {
return this._append_html_data(obj,
this._data.core.original_container_html.clone(true), function (status) {
callback.call(this, status);
});
@@ -1284,14 +1330,14 @@
else {
return callback.call(this, false);
}
- // return callback.call(this, obj.id === '#' ?
this._append_html_data(obj,
this._data.core.original_container_html.clone(true)) : false);
+ // return callback.call(this, obj.id ===
$.jstree.root ? this._append_html_data(obj,
this._data.core.original_container_html.clone(true)) : false);
}
if($.isFunction(s)) {
return s.call(this, obj, $.proxy(function (d) {
if(d === false) {
callback.call(this, false);
}
- this[typeof d === 'string' ?
'_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $(d) :
d, function (status) {
+ this[typeof d === 'string' ?
'_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ?
$($.parseHTML(d)).filter(function () { return this.nodeType !== 3; }) : d,
function (status) {
callback.call(this, status);
});
// return d === false ?
callback.call(this, false) : callback.call(this, this[typeof d === 'string' ?
'_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $(d) :
d));
@@ -1309,12 +1355,12 @@
return $.ajax(s)
.done($.proxy(function (d,t,x) {
var type =
x.getResponseHeader('Content-Type');
-
if(type.indexOf('json') !== -1 || typeof d === "object") {
+ if((type &&
type.indexOf('json') !== -1) || typeof d === "object") {
return
this._append_json_data(obj, d, function (status) { callback.call(this, status);
});
//return callback.call(this, this._append_json_data(obj, d));
}
-
if(type.indexOf('html') !== -1 || typeof d === "string") {
- return
this._append_html_data(obj, $(d), function (status) { callback.call(this,
status); });
+ if((type &&
type.indexOf('html') !== -1) || typeof d === "string") {
+ return
this._append_html_data(obj, $($.parseHTML(d)).filter(function () { return
this.nodeType !== 3; }), function (status) { callback.call(this, status); });
//
return callback.call(this, this._append_html_data(obj, $(d)));
}
this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' :
'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' :
obj.id, 'xhr' : x }) };
@@ -1328,7 +1374,7 @@
}, this));
}
t = ($.isArray(s) || $.isPlainObject(s)) ?
JSON.parse(JSON.stringify(s)) : s;
- if(obj.id === '#') {
+ if(obj.id === $.jstree.root) {
return this._append_json_data(obj, t,
function (status) {
callback.call(this, status);
});
@@ -1338,11 +1384,11 @@
this.settings.core.error.call(this,
this._data.core.last_error);
return callback.call(this, false);
}
- //return callback.call(this, (obj.id === "#" ?
this._append_json_data(obj, t) : false) );
+ //return callback.call(this, (obj.id ===
$.jstree.root ? this._append_json_data(obj, t) : false) );
}
if(typeof s === 'string') {
- if(obj.id === '#') {
- return this._append_html_data(obj,
$(s), function (status) {
+ if(obj.id === $.jstree.root) {
+ return this._append_html_data(obj,
$($.parseHTML(s)).filter(function () { return this.nodeType !== 3; }), function
(status) {
callback.call(this, status);
});
}
@@ -1351,7 +1397,7 @@
this.settings.core.error.call(this,
this._data.core.last_error);
return callback.call(this, false);
}
- //return callback.call(this, (obj.id === "#" ?
this._append_html_data(obj, $(s)) : false) );
+ //return callback.call(this, (obj.id ===
$.jstree.root ? this._append_html_data(obj, $(s)) : false) );
}
return callback.call(this, false);
},
@@ -1410,7 +1456,7 @@
* @param {String} parent the parent ID of the nodes
*/
this.trigger('model', { "nodes" : dpc, 'parent' : par
});
- if(par !== '#') {
+ if(par !== $.jstree.root) {
this._node_changed(par);
this.redraw();
}
@@ -1433,6 +1479,7 @@
* @trigger model.jstree, changed.jstree
*/
_append_json_data : function (dom, data, cb, force_processing) {
+ if(this.element === null) { return; }
dom = this.get_node(dom);
dom.children = [];
dom.children_d = [];
@@ -1496,6 +1543,9 @@
if(d && d.data &&
d.data.jstree && d.data.jstree.icon) {
tmp.icon =
d.data.jstree.icon;
}
+ if(tmp.icon ===
undefined || tmp.icon === null || tmp.icon === "") {
+ tmp.icon = true;
+ }
if(d && d.data) {
tmp.data =
d.data;
if(d.data.jstree) {
@@ -1585,6 +1635,9 @@
if(d && d.data &&
d.data.jstree && d.data.jstree.icon) {
tmp.icon =
d.data.jstree.icon;
}
+ if(tmp.icon ===
undefined || tmp.icon === null || tmp.icon === "") {
+ tmp.icon = true;
+ }
if(d && d.data) {
tmp.data =
d.data;
if(d.data.jstree) {
@@ -1720,6 +1773,7 @@
}
},
rslt = function (rslt, worker) {
+ if(this.element === null) { return; }
this._cnt = rslt.cnt;
this._model.data = rslt.mod; // breaks
the reference in load_node - careful
@@ -1747,7 +1801,7 @@
this.trigger('model', { "nodes" :
rslt.dpc, 'parent' : rslt.par });
- if(rslt.par !== '#') {
+ if(rslt.par !== $.jstree.root) {
this._node_changed(rslt.par);
this.redraw();
}
@@ -1886,9 +1940,12 @@
if(tmp.length) {
data.icon =
tmp.hasClass('jstree-themeicon-hidden') ? false : tmp.attr('rel');
}
- if(data.state.icon) {
+ if(data.state.icon !== undefined) {
data.icon = data.state.icon;
}
+ if(data.icon === undefined || data.icon === null ||
data.icon === "") {
+ data.icon = true;
+ }
tmp = d.children("ul").children("li");
do {
tid = 'j' + this._id + '_' + (++this._cnt);
@@ -1961,6 +2018,9 @@
if(d && d.data && d.data.jstree && d.data.jstree.icon) {
tmp.icon = d.data.jstree.icon;
}
+ if(tmp.icon === undefined || tmp.icon === null ||
tmp.icon === "") {
+ tmp.icon = true;
+ }
if(d && d.data) {
tmp.data = d.data;
if(d.data.jstree) {
@@ -2059,6 +2119,9 @@
if(d && d.data && d.data.jstree && d.data.jstree.icon) {
tmp.icon = d.data.jstree.icon;
}
+ if(tmp.icon === undefined || tmp.icon === null ||
tmp.icon === "") {
+ tmp.icon = true;
+ }
if(d && d.data) {
tmp.data = d.data;
if(d.data.jstree) {
@@ -2131,7 +2194,7 @@
* @trigger redraw.jstree
*/
_redraw : function () {
- var nodes = this._model.force_full_redraw ?
this._model.data['#'].children.concat([]) : this._model.changed.concat([]),
+ var nodes = this._model.force_full_redraw ?
this._model.data[$.jstree.root].children.concat([]) :
this._model.changed.concat([]),
f = document.createElement('UL'), tmp, i, j, fe
= this._data.core.focused;
for(i = 0, j = nodes.length; i < j; i++) {
tmp = this.redraw_node(nodes[i], true,
this._model.force_full_redraw);
@@ -2180,6 +2243,35 @@
this._redraw();
},
/**
+ * redraws a single node's children. Used internally.
+ * @private
+ * @name draw_children(node)
+ * @param {mixed} node the node whose children will be redrawn
+ */
+ draw_children : function (node) {
+ var obj = this.get_node(node),
+ i = false,
+ j = false,
+ k = false,
+ d = document;
+ if(!obj) { return false; }
+ if(obj.id === $.jstree.root) { return
this.redraw(true); }
+ node = this.get_node(node, true);
+ if(!node || !node.length) { return false; } // TODO:
quick toggle
+
+ node.children('.jstree-children').remove();
+ node = node[0];
+ if(obj.children.length && obj.state.loaded) {
+ k = d.createElement('UL');
+ k.setAttribute('role', 'group');
+ k.className = 'jstree-children';
+ for(i = 0, j = obj.children.length; i < j; i++)
{
+
k.appendChild(this.redraw_node(obj.children[i], true, true));
+ }
+ node.appendChild(k);
+ }
+ },
+ /**
* redraws a single node. Used internally.
* @private
* @name redraw_node(node, deep, is_callback, force_render)
@@ -2201,20 +2293,24 @@
m = this._model.data,
f = false,
s = false,
- tmp = null;
+ tmp = null,
+ t = 0,
+ l = 0,
+ has_children = false,
+ last_sibling = false;
if(!obj) { return false; }
- if(obj.id === '#') { return this.redraw(true); }
+ if(obj.id === $.jstree.root) { return
this.redraw(true); }
deep = deep || obj.children.length === 0;
node = !document.querySelector ?
document.getElementById(obj.id) : this.element[0].querySelector('#' +
("0123456789".indexOf(obj.id[0]) !== -1 ? '\\3' + obj.id[0] + ' ' +
obj.id.substr(1).replace($.jstree.idregex,'\\$&') :
obj.id.replace($.jstree.idregex,'\\$&')) ); //, this.element);
if(!node) {
deep = true;
//node = d.createElement('LI');
if(!is_callback) {
- par = obj.parent !== '#' ? $('#' +
obj.parent.replace($.jstree.idregex,'\\$&'), this.element)[0] : null;
+ par = obj.parent !== $.jstree.root ?
$('#' + obj.parent.replace($.jstree.idregex,'\\$&'), this.element)[0] : null;
if(par !== null && (!par ||
!m[obj.parent].state.opened)) {
return false;
}
- ind = $.inArray(obj.id, par === null ?
m['#'].children : m[obj.parent].children);
+ ind = $.inArray(obj.id, par === null ?
m[$.jstree.root].children : m[obj.parent].children);
}
}
else {
@@ -2263,14 +2359,39 @@
node.setAttribute('aria-disabled', true);
}
- if(obj.state.loaded && !obj.children.length) {
+ for(i = 0, j = obj.children.length; i < j; i++) {
+ if(!m[obj.children[i]].state.hidden) {
+ has_children = true;
+ break;
+ }
+ }
+ if(obj.parent !== null && m[obj.parent] &&
!obj.state.hidden) {
+ i = $.inArray(obj.id, m[obj.parent].children);
+ last_sibling = obj.id;
+ if(i !== -1) {
+ i++;
+ for(j = m[obj.parent].children.length;
i < j; i++) {
+
if(!m[m[obj.parent].children[i]].state.hidden) {
+ last_sibling =
m[obj.parent].children[i];
+ }
+ if(last_sibling !== obj.id) {
+ break;
+ }
+ }
+ }
+ }
+
+ if(obj.state.hidden) {
+ c += ' jstree-hidden';
+ }
+ if(obj.state.loaded && !has_children) {
c += ' jstree-leaf';
}
else {
c += obj.state.opened && obj.state.loaded ? '
jstree-open' : ' jstree-closed';
node.setAttribute('aria-expanded',
(obj.state.opened && obj.state.loaded) );
}
- if(obj.parent !== null &&
m[obj.parent].children[m[obj.parent].children.length - 1] === obj.id) {
+ if(last_sibling === obj.id) {
c += ' jstree-last';
}
node.id = obj.id;
@@ -2312,6 +2433,7 @@
node.childNodes[1].innerHTML += obj.text;
}
+
if(deep && obj.children.length && (obj.state.opened ||
force_render) && obj.state.loaded) {
k = d.createElement('UL');
k.setAttribute('role', 'group');
@@ -2350,7 +2472,11 @@
par.appendChild(node);
}
if(f) {
+ t = this.element[0].scrollTop;
+ l = this.element[0].scrollLeft;
node.childNodes[1].focus();
+ this.element[0].scrollTop = t;
+ this.element[0].scrollLeft = l;
}
}
if(obj.state.opened && !obj.state.loaded) {
@@ -2379,7 +2505,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
animation = animation === undefined ?
this.settings.core.animation : animation;
@@ -2403,9 +2529,12 @@
d = this.get_node(obj, true);
t = this;
if(d.length) {
+ if(animation &&
d.children(".jstree-children").length) {
+
d.children(".jstree-children").stop(true, true);
+ }
if(obj.children.length &&
!this._firstChild(d.children('.jstree-children')[0])) {
- this.redraw_node(obj, true,
false, true);
- d = this.get_node(obj, true);
+ this.draw_children(obj);
+ //d = this.get_node(obj, true);
}
if(!animation) {
this.trigger('before_open', {
"node" : obj });
@@ -2453,6 +2582,7 @@
*/
this.trigger("after_open", { "node" :
obj });
}
+ return true;
}
},
/**
@@ -2463,12 +2593,12 @@
*/
_open_to : function (obj) {
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
var i, j, p = obj.parents;
for(i = 0, j = p.length; i < j; i+=1) {
- if(i !== '#') {
+ if(i !== $.jstree.root) {
this.open_node(p[i], false, 0);
}
}
@@ -2491,7 +2621,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
if(this.is_closed(obj)) {
@@ -2564,10 +2694,10 @@
* @trigger open_all.jstree
*/
open_all : function (obj, animation, original_obj) {
- if(!obj) { obj = '#'; }
+ if(!obj) { obj = $.jstree.root; }
obj = this.get_node(obj);
if(!obj) { return false; }
- var dom = obj.id === '#' ? this.get_container_ul() :
this.get_node(obj, true), i, j, _this;
+ var dom = obj.id === $.jstree.root ?
this.get_container_ul() : this.get_node(obj, true), i, j, _this;
if(!dom.length) {
for(i = 0, j = obj.children_d.length; i < j;
i++) {
if(this.is_closed(this._model.data[obj.children_d[i]])) {
@@ -2604,19 +2734,18 @@
* @trigger close_all.jstree
*/
close_all : function (obj, animation) {
- if(!obj) { obj = '#'; }
+ if(!obj) { obj = $.jstree.root; }
obj = this.get_node(obj);
if(!obj) { return false; }
- var dom = obj.id === '#' ? this.get_container_ul() :
this.get_node(obj, true),
+ var dom = obj.id === $.jstree.root ?
this.get_container_ul() : this.get_node(obj, true),
_this = this, i, j;
- if(!dom.length) {
- for(i = 0, j = obj.children_d.length; i < j;
i++) {
-
this._model.data[obj.children_d[i]].state.opened = false;
- }
- return this.trigger('close_all', { "node" : obj
});
+ if(dom.length) {
+ dom = this.is_open(obj) ?
dom.find('.jstree-open').addBack() : dom.find('.jstree-open');
+ $(dom.get().reverse()).each(function () {
_this.close_node(this, animation || 0); });
}
- dom = this.is_open(obj) ?
dom.find('.jstree-open').addBack() : dom.find('.jstree-open');
- $(dom.get().reverse()).each(function () {
_this.close_node(this, animation || 0); });
+ for(i = 0, j = obj.children_d.length; i < j; i++) {
+
this._model.data[obj.children_d[i]].state.opened = false;
+ }
/**
* triggered when an `close_all` call completes
* @event
@@ -2651,7 +2780,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
obj.state.disabled = false;
@@ -2680,7 +2809,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
obj.state.disabled = true;
@@ -2694,6 +2823,130 @@
this.trigger('disable_node', { 'node' : obj });
},
/**
+ * hides a node - it is still in the structure but will not be
visible
+ * @name hide_node(obj)
+ * @param {mixed} obj the node to hide
+ * @param {Boolean} redraw internal parameter controlling if
redraw is called
+ * @trigger hide_node.jstree
+ */
+ hide_node : function (obj, skip_redraw) {
+ var t1, t2;
+ if($.isArray(obj)) {
+ obj = obj.slice();
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
+ this.hide_node(obj[t1], true);
+ }
+ this.redraw();
+ return true;
+ }
+ obj = this.get_node(obj);
+ if(!obj || obj.id === $.jstree.root) {
+ return false;
+ }
+ if(!obj.state.hidden) {
+ obj.state.hidden = true;
+ this._node_changed(obj.parent);
+ if(!skip_redraw) {
+ this.redraw();
+ }
+ /**
+ * triggered when an node is hidden
+ * @event
+ * @name hide_node.jstree
+ * @param {Object} node the hidden node
+ */
+ this.trigger('hide_node', { 'node' : obj });
+ }
+ },
+ /**
+ * shows a node
+ * @name show_node(obj)
+ * @param {mixed} obj the node to show
+ * @param {Boolean} skip_redraw internal parameter controlling
if redraw is called
+ * @trigger show_node.jstree
+ */
+ show_node : function (obj, skip_redraw) {
+ var t1, t2;
+ if($.isArray(obj)) {
+ obj = obj.slice();
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
+ this.show_node(obj[t1], true);
+ }
+ this.redraw();
+ return true;
+ }
+ obj = this.get_node(obj);
+ if(!obj || obj.id === $.jstree.root) {
+ return false;
+ }
+ if(obj.state.hidden) {
+ obj.state.hidden = false;
+ this._node_changed(obj.parent);
+ if(!skip_redraw) {
+ this.redraw();
+ }
+ /**
+ * triggered when an node is shown
+ * @event
+ * @name show_node.jstree
+ * @param {Object} node the shown node
+ */
+ this.trigger('show_node', { 'node' : obj });
+ }
+ },
+ /**
+ * hides all nodes
+ * @name hide_all()
+ * @trigger hide_all.jstree
+ */
+ hide_all : function (skip_redraw) {
+ var i, m = this._model.data, ids = [];
+ for(i in m) {
+ if(m.hasOwnProperty(i) && i !== $.jstree.root
&& !m[i].state.hidden) {
+ m[i].state.hidden = true;
+ ids.push(i);
+ }
+ }
+ this._model.force_full_redraw = true;
+ if(!skip_redraw) {
+ this.redraw();
+ }
+ /**
+ * triggered when all nodes are hidden
+ * @event
+ * @name hide_all.jstree
+ * @param {Array} nodes the IDs of all hidden nodes
+ */
+ this.trigger('hide_all', { 'nodes' : ids });
+ return ids;
+ },
+ /**
+ * shows all nodes
+ * @name show_all()
+ * @trigger show_all.jstree
+ */
+ show_all : function (skip_redraw) {
+ var i, m = this._model.data, ids = [];
+ for(i in m) {
+ if(m.hasOwnProperty(i) && i !== $.jstree.root
&& m[i].state.hidden) {
+ m[i].state.hidden = false;
+ ids.push(i);
+ }
+ }
+ this._model.force_full_redraw = true;
+ if(!skip_redraw) {
+ this.redraw();
+ }
+ /**
+ * triggered when all nodes are shown
+ * @event
+ * @name show_all.jstree
+ * @param {Array} nodes the IDs of all shown nodes
+ */
+ this.trigger('show_all', { 'nodes' : ids });
+ return ids;
+ },
+ /**
* called when a node is selected by the user. Used internally.
* @private
* @name activate_node(obj, e)
@@ -2705,6 +2958,9 @@
if(this.is_disabled(obj)) {
return false;
}
+ if(!e || typeof e !== 'object') {
+ e = {};
+ }
// ensure last_clicked is still in the DOM, make it
fresh (maybe it was moved?) and make sure it is still selected, if not - make
last_clicked the last selected node
this._data.core.last_clicked =
this._data.core.last_clicked && this._data.core.last_clicked.id !== undefined ?
this.get_node(this._data.core.last_clicked.id) : null;
@@ -2736,7 +2992,7 @@
if(p[i] === l) {
c = !c;
}
- if(c || p[i] === o || p[i] ===
l) {
+ if(!this.is_disabled(p[i]) &&
(c || p[i] === o || p[i] === l)) {
this.select_node(p[i],
true, false, e);
}
else {
@@ -2759,8 +3015,9 @@
* @event
* @name activate_node.jstree
* @param {Object} node
+ * @param {Object} event the ooriginal event (if any)
which triggered the call (may be an empty object)
*/
- this.trigger('activate_node', { 'node' :
this.get_node(obj) });
+ this.trigger('activate_node', { 'node' :
this.get_node(obj), 'event' : e });
},
/**
* applies the hover state on a node, called when a node is
hovered by the user. Used internally.
@@ -2826,7 +3083,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
dom = this.get_node(obj, true);
@@ -2879,7 +3136,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
dom = this.get_node(obj, true);
@@ -2911,7 +3168,7 @@
*/
select_all : function (supress_event) {
var tmp = this._data.core.selected.concat([]), i, j;
- this._data.core.selected =
this._model.data['#'].children_d.concat();
+ this._data.core.selected =
this._model.data[$.jstree.root].children_d.concat();
for(i = 0, j = this._data.core.selected.length; i < j;
i++) {
if(this._model.data[this._data.core.selected[i]]) {
this._model.data[this._data.core.selected[i]].state.selected = true;
@@ -2964,7 +3221,7 @@
*/
is_selected : function (obj) {
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
return obj.state.selected;
@@ -3047,7 +3304,7 @@
}, i;
for(i in this._model.data) {
if(this._model.data.hasOwnProperty(i)) {
- if(i !== '#') {
+ if(i !== $.jstree.root) {
if(this._model.data[i].state.opened) {
state.core.open.push(i);
}
@@ -3063,51 +3320,25 @@
* sets the state of the tree. Used internally.
* @name set_state(state [, callback])
* @private
- * @param {Object} state the state to restore
+ * @param {Object} state the state to restore. Keep in mind
this object is passed by reference and jstree will modify it.
* @param {Function} callback an optional function to execute
once the state is restored.
* @trigger set_state.jstree
*/
set_state : function (state, callback) {
if(state) {
if(state.core) {
- var res, n, t, _this;
+ var res, n, t, _this, i;
if(state.core.open) {
- if(!$.isArray(state.core.open))
{
+ if(!$.isArray(state.core.open)
|| !state.core.open.length) {
delete state.core.open;
this.set_state(state,
callback);
- return false;
}
- res = true;
- n = false;
- t = this;
-
$.each(state.core.open.concat([]), function (i, v) {
- n = t.get_node(v);
- if(n) {
-
if(t.is_loaded(v)) {
-
if(t.is_closed(v)) {
-
t.open_node(v, false, 0);
- }
-
if(state && state.core && state.core.open) {
-
$.vakata.array_remove_item(state.core.open, v);
- }
- }
- else {
-
if(!t.is_loading(v)) {
-
t.open_node(v, $.proxy(function (o, s) {
-
if(!s && state && state.core && state.core.open) {
-
$.vakata.array_remove_item(state.core.open, o.id);
-
}
-
this.set_state(state, callback);
-
}, t), 0);
- }
- //
there will be some async activity - so wait for it
- res =
false;
- }
- }
- });
- if(res) {
- delete state.core.open;
- this.set_state(state,
callback);
+ else {
+
this._load_nodes(state.core.open, function (nodes) {
+
this.open_node(nodes, false, 0);
+ delete
state.core.open;
+
this.set_state(state, callback);
+ }, true);
}
return false;
}
@@ -3122,33 +3353,21 @@
this.set_state(state, callback);
return false;
}
- /*!
- if(state.core.themes) {
- if(state.core.themes.name) {
-
this.set_theme(state.core.themes.name);
- }
- if(typeof
state.core.themes.dots !== 'undefined') {
- this[
state.core.themes.dots ? "show_dots" : "hide_dots" ]();
- }
- if(typeof
state.core.themes.icons !== 'undefined') {
- this[
state.core.themes.icons ? "show_icons" : "hide_icons" ]();
- }
- delete state.core.themes;
- delete state.core.open;
- this.set_state(state, callback);
- return false;
- }
- */
if(state.core.selected) {
_this = this;
this.deselect_all();
$.each(state.core.selected,
function (i, v) {
- _this.select_node(v);
+ _this.select_node(v,
false, true);
});
delete state.core.selected;
this.set_state(state, callback);
return false;
}
+ for(i in state) {
+ if(state.hasOwnProperty(i) && i
!== "core" && $.inArray(i, this.settings.plugins) === -1) {
+ delete state[i];
+ }
+ }
if($.isEmptyObject(state.core)) {
delete state.core;
this.set_state(state, callback);
@@ -3181,22 +3400,25 @@
this._data.core.state = forget_state === true ? {} :
this.get_state();
if(forget_state && $.isFunction(forget_state)) {
this._data.core.state = forget_state.call(this, this._data.core.state); }
this._cnt = 0;
- this._model.data = {
- '#' : {
- id : '#',
- parent : null,
- parents : [],
- children : [],
- children_d : [],
- state : { loaded : false }
- }
+ this._model.data = {};
+ this._model.data[$.jstree.root] = {
+ id : $.jstree.root,
+ parent : null,
+ parents : [],
+ children : [],
+ children_d : [],
+ state : { loaded : false }
};
+ this._data.core.selected = [];
+ this._data.core.last_clicked = null;
+ this._data.core.focused = null;
+
var c = this.get_container_ul()[0].className;
if(!skip_loading) {
this.element.html("<"+"ul class='"+c+"'
role='group'><"+"li class='jstree-initial-node jstree-loading jstree-leaf
jstree-last' role='treeitem' id='j"+this._id+"_loading'><i class='jstree-icon
jstree-ocl'></i><"+"a class='jstree-anchor' href='#'><i class='jstree-icon
jstree-themeicon-hidden'></i>" + this.get_string("Loading ...") +
"</a></li></ul>");
this.element.attr('aria-activedescendant','j'+this._id+'_loading');
}
- this.load_node('#', function (o, s) {
+ this.load_node($.jstree.root, function (o, s) {
if(s) {
this.get_container_ul()[0].className =
c;
if(this._firstChild(this.get_container_ul()[0])) {
@@ -3222,7 +3444,7 @@
*/
refresh_node : function (obj) {
obj = this.get_node(obj);
- if(!obj || obj.id === '#') { return false; }
+ if(!obj || obj.id === $.jstree.root) { return false; }
var opened = [], to_load = [], s =
this._data.core.selected.concat([]);
to_load.push(obj.id);
if(obj.state.opened === true) { opened.push(obj.id); }
@@ -3249,7 +3471,7 @@
*/
set_id : function (obj, id) {
obj = this.get_node(obj);
- if(!obj || obj.id === '#') { return false; }
+ if(!obj || obj.id === $.jstree.root) { return false; }
var i, j, m = this._model.data;
id = id.toString();
// update parents (replace current ID with new one in
children and children_d)
@@ -3269,10 +3491,14 @@
// update model and obj itself (obj.id,
this._model.data[KEY])
i = this.get_node(obj.id, true);
if(i) {
- i.attr('id', id);
+ i.attr('id',
id).children('.jstree-anchor').attr('id', id +
'_anchor').end().attr('aria-labelledby', id + '_anchor');
+ if(this.element.attr('aria-activedescendant')
=== obj.id) {
+
this.element.attr('aria-activedescendant', id);
+ }
}
delete m[obj.id];
obj.id = id;
+ obj.li_attr.id = id;
m[id] = obj;
return true;
},
@@ -3284,7 +3510,7 @@
*/
get_text : function (obj) {
obj = this.get_node(obj);
- return (!obj || obj.id === '#') ? false : obj.text;
+ return (!obj || obj.id === $.jstree.root) ? false :
obj.text;
},
/**
* set the text value of a node. Used internally, please use
`rename_node(obj, val)`.
@@ -3305,7 +3531,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') { return false; }
+ if(!obj || obj.id === $.jstree.root) { return false; }
obj.text = val;
if(this.get_node(obj, true).length) {
this.redraw_node(obj.id);
@@ -3333,7 +3559,7 @@
* @return {Object}
*/
get_json : function (obj, options, flat) {
- obj = this.get_node(obj || '#');
+ obj = this.get_node(obj || $.jstree.root);
if(!obj) { return false; }
if(options && options.flat && !flat) { flat = []; }
var tmp = {
@@ -3368,7 +3594,7 @@
delete tmp.a_attr.id;
}
}
- if(options && options.flat && obj.id !== '#') {
+ if(options && options.flat && obj.id !== $.jstree.root)
{
flat.push(tmp);
}
if(!options || !options.no_children) {
@@ -3381,7 +3607,7 @@
}
}
}
- return options && options.flat ? flat : (obj.id === '#'
? tmp.children : tmp);
+ return options && options.flat ? flat : (obj.id ===
$.jstree.root ? tmp.children : tmp);
},
/**
* create a new node (do not confuse with load_node)
@@ -3395,7 +3621,7 @@
* @trigger model.jstree, create_node.jstree
*/
create_node : function (par, node, pos, callback, is_loaded) {
- if(par === null) { par = "#"; }
+ if(par === null) { par = $.jstree.root; }
par = this.get_node(par);
if(!par) { return false; }
pos = pos === undefined ? "last" : pos;
@@ -3403,10 +3629,11 @@
return this.load_node(par, function () {
this.create_node(par, node, pos, callback, true); });
}
if(!node) { node = { "text" : this.get_string('New
node') }; }
+ if(typeof node === "string") { node = { "text" : node
}; }
if(node.text === undefined) { node.text =
this.get_string('New node'); }
var tmp, dpc, i, j;
- if(par.id === '#') {
+ if(par.id === $.jstree.root) {
if(pos === "before") { pos = "first"; }
if(pos === "after") { pos = "last"; }
}
@@ -3490,7 +3717,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') { return false; }
+ if(!obj || obj.id === $.jstree.root) { return false; }
old = obj.text;
if(!this.check("rename_node", obj,
this.get_parent(obj), val)) {
this.settings.core.error.call(this,
this._data.core.last_error);
@@ -3516,7 +3743,7 @@
* @trigger delete_node.jstree, changed.jstree
*/
delete_node : function (obj) {
- var t1, t2, par, pos, tmp, i, j, k, l, c;
+ var t1, t2, par, pos, tmp, i, j, k, l, c, top, lft;
if($.isArray(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
@@ -3525,7 +3752,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') { return false; }
+ if(!obj || obj.id === $.jstree.root) { return false; }
par = this.get_node(obj.parent);
pos = $.inArray(obj.id, par.children);
c = false;
@@ -3567,6 +3794,19 @@
for(k = 0, l = tmp.length; k < l; k++) {
delete this._model.data[tmp[k]];
}
+ if($.inArray(this._data.core.focused, tmp) !== -1) {
+ this._data.core.focused = null;
+ top = this.element[0].scrollTop;
+ lft = this.element[0].scrollLeft;
+ if(par.id === $.jstree.root) {
+
this.get_node(this._model.data[$.jstree.root].children[0],
true).children('.jstree-anchor').focus();
+ }
+ else {
+ this.get_node(par,
true).children('.jstree-anchor').focus();
+ }
+ this.element[0].scrollTop = top;
+ this.element[0].scrollLeft = lft;
+ }
this.redraw_node(par, true);
return true;
},
@@ -3620,49 +3860,59 @@
* @param {mixed} par the new parent
* @param {mixed} pos the position to insert at (besides
integer values, "first" and "last" are supported, as well as "before" and
"after"), defaults to integer `0`
* @param {function} callback a function to call once the move
is completed, receives 3 arguments - the node, the new parent and the position
- * @param {Boolean} internal parameter indicating if the
parent node has been loaded
- * @param {Boolean} internal parameter indicating if the tree
should be redrawn
+ * @param {Boolean} is_loaded internal parameter indicating if
the parent node has been loaded
+ * @param {Boolean} skip_redraw internal parameter indicating
if the tree should be redrawn
+ * @param {Boolean} instance internal parameter indicating if
the node comes from another instance
* @trigger move_node.jstree
*/
- move_node : function (obj, par, pos, callback, is_loaded,
skip_redraw) {
+ move_node : function (obj, par, pos, callback, is_loaded,
skip_redraw, origin) {
var t1, t2, old_par, old_pos, new_par, old_ins,
is_multi, dpc, tmp, i, j, k, l, p;
par = this.get_node(par);
pos = pos === undefined ? 0 : pos;
if(!par) { return false; }
if(!pos.toString().match(/^(before|after)$/) &&
!is_loaded && !this.is_loaded(par)) {
- return this.load_node(par, function () {
this.move_node(obj, par, pos, callback, true); });
+ return this.load_node(par, function () {
this.move_node(obj, par, pos, callback, true, false, origin); });
}
if($.isArray(obj)) {
- obj = obj.slice();
- for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
- if(this.move_node(obj[t1], par, pos,
callback, is_loaded, true)) {
- par = obj[t1];
- pos = "after";
+ if(obj.length === 1) {
+ obj = obj[0];
+ }
+ else {
+ //obj = obj.slice();
+ for(t1 = 0, t2 = obj.length; t1 < t2;
t1++) {
+ if((tmp =
this.move_node(obj[t1], par, pos, callback, is_loaded, false, origin))) {
+ par = tmp;
+ pos = "after";
+ }
}
+ this.redraw();
+ return true;
}
- this.redraw();
- return true;
}
obj = obj && obj.id ? obj : this.get_node(obj);
- if(!obj || obj.id === '#') { return false; }
+ if(!obj || obj.id === $.jstree.root) { return false; }
- old_par = (obj.parent || '#').toString();
- new_par = (!pos.toString().match(/^(before|after)$/) ||
par.id === '#') ? par : this.get_node(par.parent);
- old_ins = obj.instance ? obj.instance :
(this._model.data[obj.id] ? this : $.jstree.reference(obj.id));
+ old_par = (obj.parent || $.jstree.root).toString();
+ new_par = (!pos.toString().match(/^(before|after)$/) ||
par.id === $.jstree.root) ? par : this.get_node(par.parent);
+ old_ins = origin ? origin : (this._model.data[obj.id] ?
this : $.jstree.reference(obj.id));
is_multi = !old_ins || !old_ins._id || (this._id !==
old_ins._id);
old_pos = old_ins && old_ins._id && old_par &&
old_ins._model.data[old_par] && old_ins._model.data[old_par].children ?
$.inArray(obj.id, old_ins._model.data[old_par].children) : -1;
+ if(old_ins && old_ins._id) {
+ obj = old_ins._model.data[obj.id];
+ }
+
if(is_multi) {
- if(this.copy_node(obj, par, pos, callback,
is_loaded)) {
+ if((tmp = this.copy_node(obj, par, pos,
callback, is_loaded, false, origin))) {
if(old_ins) { old_ins.delete_node(obj);
}
- return true;
+ return tmp;
}
return false;
}
//var m = this._model.data;
- if(par.id === '#') {
+ if(par.id === $.jstree.root) {
if(pos === "before") { pos = "first"; }
if(pos === "after") { pos = "last"; }
}
@@ -3685,7 +3935,7 @@
break;
}
if(pos > new_par.children.length) { pos =
new_par.children.length; }
- if(!this.check("move_node", obj, new_par, pos, { 'core'
: true, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id),
'is_foreign' : (!old_ins || !old_ins._id) })) {
+ if(!this.check("move_node", obj, new_par, pos, { 'core'
: true, 'origin' : origin, 'is_multi' : (old_ins && old_ins._id && old_ins._id
!== this._id), 'is_foreign' : (!old_ins || !old_ins._id) })) {
this.settings.core.error.call(this,
this._data.core.last_error);
return false;
}
@@ -3703,7 +3953,7 @@
tmp[pos] = obj.id;
new_par.children = tmp;
this._node_changed(new_par.id);
- this.redraw(new_par.id === '#');
+ this.redraw(new_par.id === $.jstree.root);
}
else {
// clean old parent and up
@@ -3748,7 +3998,7 @@
Array.prototype.push.apply(this._model.data[obj.children_d[i]].parents, tmp);
}
- if(old_par === '#' || new_par.id === '#') {
+ if(old_par === $.jstree.root || new_par.id ===
$.jstree.root) {
this._model.force_full_redraw = true;
}
if(!this._model.force_full_redraw) {
@@ -3774,7 +4024,7 @@
* @param {jsTree} new_instance the instance of the new
parent
*/
this.trigger('move_node', { "node" : obj, "parent" :
new_par.id, "position" : pos, "old_parent" : old_par, "old_position" : old_pos,
'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign'
: (!old_ins || !old_ins._id), 'old_instance' : old_ins, 'new_instance' : this
});
- return true;
+ return obj.id;
},
/**
* copy a node to a new parent
@@ -3783,40 +4033,50 @@
* @param {mixed} par the new parent
* @param {mixed} pos the position to insert at (besides
integer values, "first" and "last" are supported, as well as "before" and
"after"), defaults to integer `0`
* @param {function} callback a function to call once the move
is completed, receives 3 arguments - the node, the new parent and the position
- * @param {Boolean} internal parameter indicating if the
parent node has been loaded
- * @param {Boolean} internal parameter indicating if the tree
should be redrawn
+ * @param {Boolean} is_loaded internal parameter indicating if
the parent node has been loaded
+ * @param {Boolean} skip_redraw internal parameter indicating
if the tree should be redrawn
+ * @param {Boolean} instance internal parameter indicating if
the node comes from another instance
* @trigger model.jstree copy_node.jstree
*/
- copy_node : function (obj, par, pos, callback, is_loaded,
skip_redraw) {
+ copy_node : function (obj, par, pos, callback, is_loaded,
skip_redraw, origin) {
var t1, t2, dpc, tmp, i, j, node, old_par, new_par,
old_ins, is_multi;
par = this.get_node(par);
pos = pos === undefined ? 0 : pos;
if(!par) { return false; }
if(!pos.toString().match(/^(before|after)$/) &&
!is_loaded && !this.is_loaded(par)) {
- return this.load_node(par, function () {
this.copy_node(obj, par, pos, callback, true); });
+ return this.load_node(par, function () {
this.copy_node(obj, par, pos, callback, true, false, origin); });
}
if($.isArray(obj)) {
- obj = obj.slice();
- for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
- tmp = this.copy_node(obj[t1], par, pos,
callback, is_loaded, true);
- if(tmp) {
- par = tmp;
- pos = "after";
+ if(obj.length === 1) {
+ obj = obj[0];
+ }
+ else {
+ //obj = obj.slice();
+ for(t1 = 0, t2 = obj.length; t1 < t2;
t1++) {
+ if((tmp =
this.copy_node(obj[t1], par, pos, callback, is_loaded, true, origin))) {
+ par = tmp;
+ pos = "after";
+ }
}
+ this.redraw();
+ return true;
}
- this.redraw();
- return true;
}
obj = obj && obj.id ? obj : this.get_node(obj);
- if(!obj || obj.id === '#') { return false; }
+ if(!obj || obj.id === $.jstree.root) { return false; }
- old_par = (obj.parent || '#').toString();
- new_par = (!pos.toString().match(/^(before|after)$/) ||
par.id === '#') ? par : this.get_node(par.parent);
- old_ins = obj.instance ? obj.instance :
(this._model.data[obj.id] ? this : $.jstree.reference(obj.id));
+ old_par = (obj.parent || $.jstree.root).toString();
+ new_par = (!pos.toString().match(/^(before|after)$/) ||
par.id === $.jstree.root) ? par : this.get_node(par.parent);
+ old_ins = origin ? origin : (this._model.data[obj.id] ?
this : $.jstree.reference(obj.id));
is_multi = !old_ins || !old_ins._id || (this._id !==
old_ins._id);
- if(par.id === '#') {
+
+ if(old_ins && old_ins._id) {
+ obj = old_ins._model.data[obj.id];
+ }
+
+ if(par.id === $.jstree.root) {
if(pos === "before") { pos = "first"; }
if(pos === "after") { pos = "last"; }
}
@@ -3839,7 +4099,7 @@
break;
}
if(pos > new_par.children.length) { pos =
new_par.children.length; }
- if(!this.check("copy_node", obj, new_par, pos, { 'core'
: true, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id),
'is_foreign' : (!old_ins || !old_ins._id) })) {
+ if(!this.check("copy_node", obj, new_par, pos, { 'core'
: true, 'origin' : origin, 'is_multi' : (old_ins && old_ins._id && old_ins._id
!== this._id), 'is_foreign' : (!old_ins || !old_ins._id) })) {
this.settings.core.error.call(this,
this._data.core.last_error);
return false;
}
@@ -3868,14 +4128,14 @@
new_par.children_d.push(tmp.id);
new_par.children_d =
new_par.children_d.concat(tmp.children_d);
- if(new_par.id === '#') {
+ if(new_par.id === $.jstree.root) {
this._model.force_full_redraw = true;
}
if(!this._model.force_full_redraw) {
this._node_changed(new_par.id);
}
if(!skip_redraw) {
- this.redraw(new_par.id === '#');
+ this.redraw(new_par.id === $.jstree.root);
}
if(callback) { callback.call(this, tmp, new_par, pos); }
/**
@@ -3908,7 +4168,7 @@
var tmp = [], o, t1, t2;
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
o = this.get_node(obj[t1]);
- if(o && o.id && o.id !== '#') { tmp.push(o); }
+ if(o && o.id && o.id !== $.jstree.root) {
tmp.push(o); }
}
if(!tmp.length) { return false; }
ccp_node = tmp;
@@ -3926,7 +4186,7 @@
* copy a node (a later call to `paste(obj)` would copy the
node)
* @name copy(obj)
* @param {mixed} obj multiple objects can be passed using an
array
- * @trigger copy.jstre
+ * @trigger copy.jstree
*/
copy : function (obj) {
if(!obj) { obj = this._data.core.selected.concat(); }
@@ -3935,7 +4195,7 @@
var tmp = [], o, t1, t2;
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
o = this.get_node(obj[t1]);
- if(o && o.id && o.id !== '#') { tmp.push(o); }
+ if(o && o.id && o.id !== $.jstree.root) {
tmp.push(o); }
}
if(!tmp.length) { return false; }
ccp_node = tmp;
@@ -3975,7 +4235,7 @@
paste : function (obj, pos) {
obj = this.get_node(obj);
if(!obj || !ccp_mode ||
!ccp_mode.match(/^(copy_node|move_node)$/) || !ccp_node) { return false; }
- if(this[ccp_mode](ccp_node, obj, pos)) {
+ if(this[ccp_mode](ccp_node, obj, pos, false, false,
false, ccp_inst)) {
/**
* triggered when paste is invoked
* @event
@@ -4008,11 +4268,13 @@
},
/**
* put a node in edit mode (input field to rename the node)
- * @name edit(obj [, default_text])
+ * @name edit(obj [, default_text, callback])
* @param {mixed} obj
- * @param {String} default_text the text to populate the input
with (if omitted the node text value is used)
+ * @param {String} default_text the text to populate the input
with (if omitted or set to a non-string value the node's text value is used)
+ * @param {Function} callback a function to be called once the
text box is blurred, it is called in the instance's scope and receives the
node, a status parameter (true if the rename is successful, false otherwise)
and a boolean indicating if the user cancelled the edit. You can access the
node's title using .text
*/
- edit : function (obj, default_text) {
+ edit : function (obj, default_text, callback) {
+ var rtl, w, a, s, t, h1, h2, fn, tmp, cancel = false;
obj = this.get_node(obj);
if(!obj) { return false; }
if(this.settings.core.check_callback === false) {
@@ -4020,23 +4282,26 @@
this.settings.core.error.call(this,
this._data.core.last_error);
return false;
}
+ tmp = obj;
default_text = typeof default_text === 'string' ?
default_text : obj.text;
this.set_text(obj, "");
obj = this._open_to(obj);
+ tmp.text = default_text;
- var rtl = this._data.core.rtl,
- w = this.element.width(),
- a = obj.children('.jstree-anchor'),
- s = $('<span>'),
- /*!
- oi = obj.children("i:visible"),
- ai = a.children("i:visible"),
- w1 = oi.width() * oi.length,
- w2 = ai.width() * ai.length,
- */
- t = default_text,
- h1 = $("<"+"div />", { css : { "position" :
"absolute", "top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility"
: "hidden" } }).appendTo("body"),
- h2 = $("<"+"input />", {
+ rtl = this._data.core.rtl;
+ w = this.element.width();
+ this._data.core.focused = tmp.id;
+ a = obj.children('.jstree-anchor').focus();
+ s = $('<span>');
+ /*!
+ oi = obj.children("i:visible"),
+ ai = a.children("i:visible"),
+ w1 = oi.width() * oi.length,
+ w2 = ai.width() * ai.length,
+ */
+ t = default_text;
+ h1 = $("<"+"div />", { css : { "position" : "absolute",
"top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility" : "hidden" }
}).appendTo("body");
+ h2 = $("<"+"input />", {
"value" : t,
"class" : "jstree-rename-input",
// "size" : t.length,
@@ -4049,40 +4314,58 @@
"lineHeight" :
(this._data.core.li_height) + "px",
"width" : "150px" //
will be set a bit further down
},
- "blur" : $.proxy(function () {
+ "blur" : $.proxy(function (e) {
+
e.stopImmediatePropagation();
+ e.preventDefault();
var i =
s.children(".jstree-rename-input"),
- v = i.val();
+ v = i.val(),
+ f =
this.settings.core.force_text,
+ nv;
if(v === "") { v = t; }
h1.remove();
s.replaceWith(a);
s.remove();
+ t = f ? t :
$('<div></div>').append($.parseHTML(t)).html();
this.set_text(obj, t);
-
if(this.rename_node(obj, $('<div></div>').text(v)[this.settings.core.force_text
? 'text' : 'html']()) === false) {
+ nv =
!!this.rename_node(obj, f ? $('<div></div>').text(v).text() :
$('<div></div>').append($.parseHTML(v)).html());
+ if(!nv) {
this.set_text(obj, t); // move this up? and fix #483
}
+ this._data.core.focused
= tmp.id;
+
setTimeout($.proxy(function () {
+ var node =
this.get_node(tmp.id, true);
+ if(node.length)
{
+
this._data.core.focused = tmp.id;
+
node.children('.jstree-anchor').focus();
+ }
+ }, this), 0);
+ if(callback) {
+
callback.call(this, tmp, nv, cancel);
+ }
}, this),
- "keydown" : function (event) {
- var key = event.which;
+ "keydown" : function (e) {
+ var key = e.which;
if(key === 27) {
+ cancel = true;
this.value = t;
}
if(key === 27 || key
=== 13 || key === 37 || key === 38 || key === 39 || key === 40 || key === 32) {
-
event.stopImmediatePropagation();
+
e.stopImmediatePropagation();
}
if(key === 27 || key
=== 13) {
-
event.preventDefault();
+
e.preventDefault();
this.blur();
}
},
"click" : function (e) {
e.stopImmediatePropagation(); },
"mousedown" : function (e) {
e.stopImmediatePropagation(); },
- "keyup" : function (event) {
+ "keyup" : function (e) {
h2.width(Math.min(h1.text("pW" + this.value).width(),w));
},
- "keypress" : function(event) {
- if(event.which === 13)
{ return false; }
+ "keypress" : function(e) {
+ if(e.which === 13) {
return false; }
}
- }),
+ });
fn = {
fontFamily :
a.css('fontFamily') || '',
fontSize :
a.css('fontSize') || '',
@@ -4219,14 +4502,14 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') { return false; }
+ if(!obj || obj.id === $.jstree.root) { return false; }
old = obj.icon;
- obj.icon = icon;
+ obj.icon = icon === true || icon === null || icon ===
undefined || icon === '' ? true : icon;
dom = this.get_node(obj,
true).children(".jstree-anchor").children(".jstree-themeicon");
if(icon === false) {
this.hide_icon(obj);
}
- else if(icon === true) {
+ else if(icon === true || icon === null || icon ===
undefined || icon === '') {
dom.removeClass('jstree-themeicon-custom ' +
old).css("background","").removeAttr("rel");
if(old === false) { this.show_icon(obj); }
}
@@ -4250,7 +4533,7 @@
*/
get_icon : function (obj) {
obj = this.get_node(obj);
- return (!obj || obj.id === '#') ? false : obj.icon;
+ return (!obj || obj.id === $.jstree.root) ? false :
obj.icon;
},
/**
* hide the icon on an individual node
@@ -4267,7 +4550,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj === '#') { return false; }
+ if(!obj || obj === $.jstree.root) { return false; }
obj.icon = false;
this.get_node(obj,
true).children(".jstree-anchor").children(".jstree-themeicon").addClass('jstree-themeicon-hidden');
return true;
@@ -4287,7 +4570,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj === '#') { return false; }
+ if(!obj || obj === $.jstree.root) { return false; }
dom = this.get_node(obj, true);
obj.icon = dom.length ?
dom.children(".jstree-anchor").children(".jstree-themeicon").attr('rel') : true;
if(!obj.icon) { obj.icon = true; }
@@ -4314,14 +4597,12 @@
return attr;
};
$.vakata.array_unique = function(array) {
- var a = [], i, j, l;
+ var a = [], i, j, l, o = {};
for(i = 0, l = array.length; i < l; i++) {
- for(j = 0; j <= i; j++) {
- if(array[i] === array[j]) {
- break;
- }
+ if(o[array[i]] === undefined) {
+ a.push(array[i]);
+ o[array[i]] = true;
}
- if(j === i) { a.push(array[i]); }
}
return a;
};
@@ -4338,10 +4619,64 @@
return tmp !== -1 ? $.vakata.array_remove(array, tmp) : array;
};
+
/**
+ * ### Changed plugin
+ *
+ * This plugin adds more information to the `changed.jstree` event. The new
data is contained in the `changed` event data property, and contains a lists of
`selected` and `deselected` nodes.
+ */
+
+ $.jstree.plugins.changed = function (options, parent) {
+ var last = [];
+ this.trigger = function (ev, data) {
+ var i, j;
+ if(!data) {
+ data = {};
+ }
+ if(ev.replace('.jstree','') === 'changed') {
+ data.changed = { selected : [], deselected : []
};
+ var tmp = {};
+ for(i = 0, j = last.length; i < j; i++) {
+ tmp[last[i]] = 1;
+ }
+ for(i = 0, j = data.selected.length; i < j;
i++) {
+ if(!tmp[data.selected[i]]) {
+
data.changed.selected.push(data.selected[i]);
+ }
+ else {
+ tmp[data.selected[i]] = 2;
+ }
+ }
+ for(i = 0, j = last.length; i < j; i++) {
+ if(tmp[last[i]] === 1) {
+
data.changed.deselected.push(last[i]);
+ }
+ }
+ last = data.selected.slice();
+ }
+ /**
+ * triggered when selection changes (the "changed"
plugin enhances the original event with more data)
+ * @event
+ * @name changed.jstree
+ * @param {Object} node
+ * @param {Object} action the action that caused the
selection to change
+ * @param {Array} selected the current selection
+ * @param {Object} changed an object containing two
properties `selected` and `deselected` - both arrays of node IDs, which were
selected or deselected since the last changed event
+ * @param {Object} event the event (if any) that
triggered this changed event
+ * @plugin changed
+ */
+ parent.trigger.call(this, ev, data);
+ };
+ this.refresh = function (skip_loading, forget_state) {
+ last = [];
+ return parent.refresh.apply(this, arguments);
+ };
+ };
+
+/**
* ### Checkbox plugin
*
- * This plugin renders checkbox icons in front of each node, making multiple
selection much easier.
+ * This plugin renders checkbox icons in front of each node, making multiple
selection much easier.
* It also supports tri-state behavior, meaning that if a node has a few of
its children checked it will be rendered as undetermined, and state will be
propagated up.
*/
@@ -4379,15 +4714,15 @@
*/
keep_selected_style : true,
/**
- * This setting controls how cascading and undetermined nodes
are applied.
- * If 'up' is in the string - cascading up is enabled, if
'down' is in the string - cascading down is enabled, if 'undetermined' is in
the string - undetermined nodes will be used.
+ * This setting controls how cascading and undetermined nodes
are applied.
+ * If 'up' is in the string - cascading up is enabled, if
'down' is in the string - cascading down is enabled, if 'undetermined' is in
the string - undetermined nodes will be used.
* If `three_state` is set to `true` this setting is
automatically set to 'up+down+undetermined'. Defaults to ''.
* @name $.jstree.defaults.checkbox.cascade
* @plugin checkbox
*/
cascade : '',
/**
- * This setting controls if checkbox are bound to the general
tree selection or to an internal array maintained by the checkbox plugin.
Defaults to `true`, only set to `false` if you know exactly what you are doing.
+ * This setting controls if checkbox are bound to the general
tree selection or to an internal array maintained by the checkbox plugin.
Defaults to `true`, only set to `false` if you know exactly what you are doing.
* @name $.jstree.defaults.checkbox.tie_selection
* @plugin checkbox
*/
@@ -4430,7 +4765,7 @@
dpc = data.nodes,
i, j;
for(i = 0, j = dpc.length; i <
j; i++) {
- m[dpc[i]].state.checked
= (m[dpc[i]].original && m[dpc[i]].original.state &&
m[dpc[i]].original.state.checked);
+ m[dpc[i]].state.checked
= m[dpc[i]].state.checked || (m[dpc[i]].original && m[dpc[i]].original.state &&
m[dpc[i]].original.state.checked);
if(m[dpc[i]].state.checked) {
this._data.checkbox.selected.push(dpc[i]);
}
@@ -4476,7 +4811,7 @@
chd =
$.vakata.array_unique(chd);
for(k = 0, l =
chd.length; k < l; k++) {
p =
m[chd[k]];
- while(p
&& p.id !== '#') {
+ while(p
&& p.id !== $.jstree.root) {
c = 0;
for(i = 0, j = p.children.length; i < j; i++) {
c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
@@ -4520,7 +4855,7 @@
// apply up
if(s.indexOf('up') !==
-1) {
- while(par &&
par.id !== '#') {
+ while(par &&
par.id !== $.jstree.root) {
c = 0;
for(i =
0, j = par.children.length; i < j; i++) {
c += m[par.children[i]].state[ t ? 'selected' : 'checked' ];
@@ -4546,7 +4881,7 @@
}
}, this))
.on(this.settings.checkbox.tie_selection ? 'deselect_all.jstree' :
'uncheck_all.jstree', $.proxy(function (e, data) {
- var obj =
this.get_node('#'),
+ var obj =
this.get_node($.jstree.root),
m =
this._model.data,
i, j, tmp;
for(i = 0, j =
obj.children_d.length; i < j; i++) {
@@ -4614,12 +4949,12 @@
var p =
this.get_node(data.parent),
m =
this._model.data,
i, j, c, tmp, t
= this.settings.checkbox.tie_selection;
- while(p && p.id !==
'#') {
+ while(p && p.id !==
$.jstree.root && !p.state[ t ? 'selected' : 'checked' ]) {
c = 0;
for(i = 0, j =
p.children.length; i < j; i++) {
c +=
m[p.children[i]].state[ t ? 'selected' : 'checked' ];
}
- if(c === j) {
+ if(j > 0 && c
=== j) {
p.state[ t ? 'selected' : 'checked' ] = true;
this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
tmp =
this.get_node(p, true);
@@ -4642,12 +4977,12 @@
p, c, i, j,
tmp, t = this.settings.checkbox.tie_selection;
if(!is_multi) {
p =
this.get_node(old_par);
- while(p && p.id
!== '#') {
+ while(p && p.id
!== $.jstree.root && !p.state[ t ? 'selected' : 'checked' ]) {
c = 0;
for(i =
0, j = p.children.length; i < j; i++) {
c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
}
- if(c
=== j) {
+ if(j >
0 && c === j) {
p.state[ t ? 'selected' : 'checked' ] = true;
this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
tmp = this.get_node(p, true);
@@ -4662,7 +4997,7 @@
}
}
p = new_par;
- while(p && p.id !==
'#') {
+ while(p && p.id !==
$.jstree.root) {
c = 0;
for(i = 0, j =
p.children.length; i < j; i++) {
c +=
m[p.children[i]].state[ t ? 'selected' : 'checked' ];
@@ -4702,10 +5037,16 @@
* @plugin checkbox
*/
this._undetermined = function () {
- var i, j, m = this._model.data, t =
this.settings.checkbox.tie_selection, s = this._data[ t ? 'core' : 'checkbox'
].selected, p = [], tt = this;
+ if(this.element === null) { return; }
+ var i, j, k, l, o = {}, m = this._model.data, t =
this.settings.checkbox.tie_selection, s = this._data[ t ? 'core' : 'checkbox'
].selected, p = [], tt = this;
for(i = 0, j = s.length; i < j; i++) {
if(m[s[i]] && m[s[i]].parents) {
- p = p.concat(m[s[i]].parents);
+ for(k = 0, l = m[s[i]].parents.length;
k < l; k++) {
+ if(o[m[s[i]].parents[k]] ===
undefined && m[s[i]].parents[k] !== $.jstree.root) {
+ o[m[s[i]].parents[k]] =
true;
+
p.push(m[s[i]].parents[k]);
+ }
+ }
}
}
// attempt for server side undetermined state
@@ -4714,22 +5055,36 @@
var tmp = tt.get_node(this), tmp2;
if(!tmp.state.loaded) {
if(tmp.original &&
tmp.original.state && tmp.original.state.undetermined &&
tmp.original.state.undetermined === true) {
- p.push(tmp.id);
- p =
p.concat(tmp.parents);
+ if(o[tmp.id] ===
undefined && tmp.id !== $.jstree.root) {
+ o[tmp.id] =
true;
+ p.push(tmp.id);
+ }
+ for(k = 0, l =
tmp.parents.length; k < l; k++) {
+
if(o[tmp.parents[k]] === undefined && tmp.parents[k] !== $.jstree.root) {
+
o[tmp.parents[k]] = true;
+
p.push(tmp.parents[k]);
+ }
+ }
}
}
else {
for(i = 0, j =
tmp.children_d.length; i < j; i++) {
tmp2 =
m[tmp.children_d[i]];
if(!tmp2.state.loaded
&& tmp2.original && tmp2.original.state && tmp2.original.state.undetermined &&
tmp2.original.state.undetermined === true) {
- p.push(tmp2.id);
- p =
p.concat(tmp2.parents);
+ if(o[tmp2.id]
=== undefined && tmp2.id !== $.jstree.root) {
+
o[tmp2.id] = true;
+
p.push(tmp2.id);
+ }
+ for(k = 0, l =
tmp2.parents.length; k < l; k++) {
+
if(o[tmp2.parents[k]] === undefined && tmp2.parents[k] !== $.jstree.root) {
+
o[tmp2.parents[k]] = true;
+
p.push(tmp2.parents[k]);
+ }
+ }
}
}
}
});
- p = $.vakata.array_unique(p);
- p = $.vakata.array_remove_item(p,'#');
this.element.find('.jstree-undetermined').removeClass('jstree-undetermined');
for(i = 0, j = p.length; i < j; i++) {
@@ -4744,7 +5099,7 @@
this.redraw_node = function(obj, deep, is_callback,
force_render) {
obj = parent.redraw_node.apply(this, arguments);
if(obj) {
- var i, j, tmp = null;
+ var i, j, tmp = null, icon = null;
for(i = 0, j = obj.childNodes.length; i < j;
i++) {
if(obj.childNodes[i] &&
obj.childNodes[i].className &&
obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) {
tmp = obj.childNodes[i];
@@ -4753,7 +5108,9 @@
}
if(tmp) {
if(!this.settings.checkbox.tie_selection &&
this._model.data[obj.id].state.checked) { tmp.className += ' jstree-checked'; }
- tmp.insertBefore(_i.cloneNode(false),
tmp.childNodes[0]);
+ icon = _i.cloneNode(false);
+
if(this._model.data[obj.id].state.checkbox_disabled) { icon.className += '
jstree-checkbox-disabled'; }
+ tmp.insertBefore(icon,
tmp.childNodes[0]);
}
}
if(!is_callback &&
this.settings.checkbox.cascade.indexOf('undetermined') !== -1) {
@@ -4802,14 +5159,92 @@
}
return false;
};
+ /**
+ * disable a node's checkbox
+ * @name disable_checkbox(obj)
+ * @param {mixed} obj an array can be used too
+ * @trigger disable_checkbox.jstree
+ * @plugin checkbox
+ */
+ this.disable_checkbox = function (obj) {
+ var t1, t2, dom;
+ if($.isArray(obj)) {
+ obj = obj.slice();
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
+ this.disable_checkbox(obj[t1]);
+ }
+ return true;
+ }
+ obj = this.get_node(obj);
+ if(!obj || obj.id === $.jstree.root) {
+ return false;
+ }
+ dom = this.get_node(obj, true);
+ if(!obj.state.checkbox_disabled) {
+ obj.state.checkbox_disabled = true;
+ if(dom && dom.length) {
+
dom.children('.jstree-anchor').children('.jstree-checkbox').addClass('jstree-checkbox-disabled');
+ }
+ /**
+ * triggered when an node's checkbox is disabled
+ * @event
+ * @name disable_checkbox.jstree
+ * @param {Object} node
+ * @plugin checkbox
+ */
+ this.trigger('disable_checkbox', { 'node' : obj
});
+ }
+ };
+ /**
+ * enable a node's checkbox
+ * @name disable_checkbox(obj)
+ * @param {mixed} obj an array can be used too
+ * @trigger enable_checkbox.jstree
+ * @plugin checkbox
+ */
+ this.enable_checkbox = function (obj) {
+ var t1, t2, dom;
+ if($.isArray(obj)) {
+ obj = obj.slice();
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
+ this.enable_checkbox(obj[t1]);
+ }
+ return true;
+ }
+ obj = this.get_node(obj);
+ if(!obj || obj.id === $.jstree.root) {
+ return false;
+ }
+ dom = this.get_node(obj, true);
+ if(obj.state.checkbox_disabled) {
+ obj.state.checkbox_disabled = false;
+ if(dom && dom.length) {
+
dom.children('.jstree-anchor').children('.jstree-checkbox').removeClass('jstree-checkbox-disabled');
+ }
+ /**
+ * triggered when an node's checkbox is enabled
+ * @event
+ * @name enable_checkbox.jstree
+ * @param {Object} node
+ * @plugin checkbox
+ */
+ this.trigger('enable_checkbox', { 'node' : obj
});
+ }
+ };
this.activate_node = function (obj, e) {
+ if($(e.target).hasClass('jstree-checkbox-disabled')) {
+ return false;
+ }
if(this.settings.checkbox.tie_selection &&
(this.settings.checkbox.whole_node || $(e.target).hasClass('jstree-checkbox')))
{
e.ctrlKey = true;
}
if(this.settings.checkbox.tie_selection ||
(!this.settings.checkbox.whole_node &&
!$(e.target).hasClass('jstree-checkbox'))) {
return parent.activate_node.call(this, obj, e);
}
+ if(this.is_disabled(obj)) {
+ return false;
+ }
if(this.is_checked(obj)) {
this.uncheck_node(obj, e);
}
@@ -4837,7 +5272,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
dom = this.get_node(obj, true);
@@ -4861,8 +5296,8 @@
};
/**
* uncheck a node (only if tie_selection in checkbox settings
is false, otherwise deselect_node will be called internally)
- * @name deselect_node(obj)
- * @param {mixed} obj an array can be used to deselect multiple
nodes
+ * @name uncheck_node(obj)
+ * @param {mixed} obj an array can be used to uncheck multiple
nodes
* @trigger uncheck_node.jstree
* @plugin checkbox
*/
@@ -4877,7 +5312,7 @@
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
dom = this.get_node(obj, true);
@@ -4908,7 +5343,7 @@
this.check_all = function () {
if(this.settings.checkbox.tie_selection) { return
this.select_all(); }
var tmp = this._data.checkbox.selected.concat([]), i, j;
- this._data.checkbox.selected =
this._model.data['#'].children_d.concat();
+ this._data.checkbox.selected =
this._model.data[$.jstree.root].children_d.concat();
for(i = 0, j = this._data.checkbox.selected.length; i <
j; i++) {
if(this._model.data[this._data.checkbox.selected[i]]) {
this._model.data[this._data.checkbox.selected[i]].state.checked = true;
@@ -4960,7 +5395,7 @@
this.is_checked = function (obj) {
if(this.settings.checkbox.tie_selection) { return
this.is_selected(obj); }
obj = this.get_node(obj);
- if(!obj || obj.id === '#') { return false; }
+ if(!obj || obj.id === $.jstree.root) { return false; }
return obj.state.checked;
};
/**
@@ -5021,12 +5456,77 @@
}
return full ? $.map(obj, $.proxy(function (i) { return
this.get_node(i); }, this)) : obj;
};
+ this.load_node = function (obj, callback) {
+ var k, l, i, j, c, tmp;
+ if(!$.isArray(obj) &&
!this.settings.checkbox.tie_selection) {
+ tmp = this.get_node(obj);
+ if(tmp && tmp.state.loaded) {
+ for(k = 0, l = tmp.children_d.length; k
< l; k++) {
+
if(this._model.data[tmp.children_d[k]].state.checked) {
+ c = true;
+
this._data.checkbox.selected =
$.vakata.array_remove_item(this._data.checkbox.selected, tmp.children_d[k]);
+ }
+ }
+ }
+ }
+ return parent.load_node.apply(this, arguments);
+ };
+ this.get_state = function () {
+ var state = parent.get_state.apply(this, arguments);
+ if(this.settings.checkbox.tie_selection) { return
state; }
+ state.checkbox = this._data.checkbox.selected.slice();
+ return state;
+ };
+ this.set_state = function (state, callback) {
+ var res = parent.set_state.apply(this, arguments);
+ if(res && state.checkbox) {
+ if(!this.settings.checkbox.tie_selection) {
+ this.uncheck_all();
+ var _this = this;
+ $.each(state.checkbox, function (i, v) {
+ _this.check_node(v);
+ });
+ }
+ delete state.checkbox;
+ this.set_state(state, callback);
+ return false;
+ }
+ return res;
+ };
+ this.refresh = function (skip_loading, forget_state) {
+ if(!this.settings.checkbox.tie_selection) {
+ this._data.checkbox.selected = [];
+ }
+ return parent.refresh.apply(this, arguments);
+ };
};
// include the checkbox plugin by default
// $.jstree.defaults.plugins.push("checkbox");
/**
+ * ### Conditionalselect plugin
+ *
+ * This plugin allows defining a callback to allow or deny node selection by
user input (activate node method).
+ */
+
+ /**
+ * a callback (function) which is invoked in the instance's scope and
receives two arguments - the node and the event that triggered the
`activate_node` call. Returning false prevents working with the node, returning
true allows invoking activate_node. Defaults to returning `true`.
+ * @name $.jstree.defaults.checkbox.visible
+ * @plugin checkbox
+ */
+ $.jstree.defaults.conditionalselect = function () { return true; };
+ $.jstree.plugins.conditionalselect = function (options, parent) {
+ // own function
+ this.activate_node = function (obj, e) {
+ if(this.settings.conditionalselect.call(this,
this.get_node(obj), e)) {
+ parent.activate_node.call(this, obj, e);
+ }
+ };
+ };
+
+
+/**
* ### Contextmenu plugin
*
* Shows a context menu when a node is right-clicked.
@@ -5052,9 +5552,9 @@
show_at_node : true,
/**
* an object of actions, or a function that accepts a node and
a callback function and calls the callback function with an object of actions
available for that node (you can also return the items too).
- *
+ *
* Each action consists of a key (a unique name) and a value
which is an object with the following properties (only label and action are
required):
- *
+ *
* * `separator_before` - a boolean indicating if there should
be a separator before this item
* * `separator_after` - a boolean indicating if there should
be a separator after this item
* * `_disabled` - a boolean indicating if this action should
be disabled
@@ -5063,7 +5563,7 @@
* * `icon` - a string, can be a path to an icon or a
className, if using an image that is in the current directory use a `./`
prefix, otherwise it will be detected as a class
* * `shortcut` - keyCode which will trigger the action if the
menu is open (for example `113` for rename, which equals F2)
* * `shortcut_label` - shortcut label (like for example `F2`
for rename)
- *
+ *
* @name $.jstree.defaults.contextmenu.items
* @plugin contextmenu
*/
@@ -5087,7 +5587,7 @@
"separator_after" : false,
"_disabled" :
false, //(this.check("rename_node", data.reference,
this.get_parent(data.reference), "")),
"label" :
"Rename",
- /*
+ /*!
"shortcut" : 113,
"shortcut_label" : 'F2',
"icon" :
"glyphicon glyphicon-leaf",
@@ -5130,7 +5630,7 @@
var inst =
$.jstree.reference(data.reference),
obj =
inst.get_node(data.reference);
if(inst.is_selected(obj)) {
-
inst.cut(inst.get_selected());
+
inst.cut(inst.get_top_selected());
}
else {
inst.cut(obj);
@@ -5146,7 +5646,7 @@
var inst =
$.jstree.reference(data.reference),
obj =
inst.get_node(data.reference);
if(inst.is_selected(obj)) {
-
inst.copy(inst.get_selected());
+
inst.copy(inst.get_top_selected());
}
else {
inst.copy(obj);
@@ -5177,21 +5677,49 @@
this.bind = function () {
parent.bind.call(this);
- var last_ts = 0;
+ var last_ts = 0, cto = null, ex, ey;
this.element
- .on("contextmenu.jstree", ".jstree-anchor",
$.proxy(function (e) {
+ .on("contextmenu.jstree", ".jstree-anchor",
$.proxy(function (e, data) {
e.preventDefault();
- last_ts = e.ctrlKey ?
e.timeStamp : 0;
+ last_ts = e.ctrlKey ? +new
Date() : 0;
+ if(data || cto) {
+ last_ts = (+new Date())
+ 10000;
+ }
+ if(cto) {
+ clearTimeout(cto);
+ }
if(!this.is_loading(e.currentTarget)) {
this.show_contextmenu(e.currentTarget, e.pageX, e.pageY, e);
}
}, this))
.on("click.jstree", ".jstree-anchor",
$.proxy(function (e) {
-
if(this._data.contextmenu.visible && (!last_ts || e.timeStamp - last_ts > 250))
{ // work around safari & macOS ctrl+click
+
if(this._data.contextmenu.visible && (!last_ts || (+new Date()) - last_ts >
250)) { // work around safari & macOS ctrl+click
$.vakata.context.hide();
}
- }, this));
- /*
+ last_ts = 0;
+ }, this))
+ .on("touchstart.jstree", ".jstree-anchor",
function (e) {
+ if(!e.originalEvent ||
!e.originalEvent.changedTouches || !e.originalEvent.changedTouches[0]) {
+ return;
+ }
+ ex = e.pageX;
+ ey = e.pageY;
+ cto = setTimeout(function () {
+
$(e.currentTarget).trigger('contextmenu', true);
+ }, 750);
+ })
+ .on('touchmove.vakata.jstree', function (e) {
+ if(cto && e.originalEvent &&
e.originalEvent.changedTouches && e.originalEvent.changedTouches[0] &&
(Math.abs(ex - e.pageX) > 50 || Math.abs(ey - e.pageY) > 50)) {
+ clearTimeout(cto);
+ }
+ })
+ .on('touchend.vakata.jstree', function (e) {
+ if(cto) {
+ clearTimeout(cto);
+ }
+ });
+
+ /*!
if(!('oncontextmenu' in document.body) &&
('ontouchstart' in document.body)) {
var el = null, tm = null;
this.element
@@ -5233,7 +5761,7 @@
*/
this.show_contextmenu = function (obj, x, y, e) {
obj = this.get_node(obj);
- if(!obj || obj.id === '#') { return false; }
+ if(!obj || obj.id === $.jstree.root) { return false; }
var s = this.settings.contextmenu,
d = this.get_node(obj, true),
a = d.children(".jstree-anchor"),
@@ -5446,7 +5974,7 @@
dw = $(window).width() +
$(window).scrollLeft();
dh = $(window).height() +
$(window).scrollTop();
if(right_to_left) {
- x -= e.outerWidth();
+ x -= (e.outerWidth() -
$(reference).outerWidth());
if(x < $(window).scrollLeft() +
20) {
x =
$(window).scrollLeft() + 20;
}
@@ -5597,7 +6125,9 @@
$(document)
.on("mousedown.vakata.jstree", function (e) {
- if(vakata_context.is_visible &&
!$.contains(vakata_context.element[0], e.target)) { $.vakata.context.hide(); }
+ if(vakata_context.is_visible &&
!$.contains(vakata_context.element[0], e.target)) {
+ $.vakata.context.hide();
+ }
})
.on("context_show.vakata.jstree", function (e,
data) {
vakata_context.element.find("li:has(ul)").children("a").addClass("vakata-context-parent");
@@ -5636,7 +6166,7 @@
*/
open_timeout : 500,
/**
- * a function invoked each time a node is about to be dragged,
invoked in the tree's scope and receives the nodes about to be dragged as an
argument (array) - return `false` to prevent dragging
+ * a function invoked each time a node is about to be dragged,
invoked in the tree's scope and receives the nodes about to be dragged as an
argument (array) and the event that started the drag - return `false` to
prevent dragging
* @name $.jstree.defaults.dnd.is_draggable
* @plugin dnd
*/
@@ -5658,7 +6188,31 @@
* @name $.jstree.defaults.dnd.inside_pos
* @plugin dnd
*/
- inside_pos : 0
+ inside_pos : 0,
+ /**
+ * when starting the drag on a node that is selected this
setting controls if all selected nodes are dragged or only the single node,
default is `true`, which means all selected nodes are dragged when the drag is
started on a selected node
+ * @name $.jstree.defaults.dnd.drag_selection
+ * @plugin dnd
+ */
+ drag_selection : true,
+ /**
+ * controls whether dnd works on touch devices. If left as
boolean true dnd will work the same as in desktop browsers, which in some cases
may impair scrolling. If set to boolean false dnd will not work on touch
devices. There is a special third option - string "selected" which means only
selected nodes can be dragged on touch devices.
+ * @name $.jstree.defaults.dnd.touch
+ * @plugin dnd
+ */
+ touch : true,
+ /**
+ * controls whether items can be dropped anywhere on the node,
not just on the anchor, by default only the node anchor is a valid drop target.
Works best with the wholerow plugin. If enabled on mobile depending on the
interface it might be hard for the user to cancel the drop, since the whole
tree container will be a valid drop target.
+ * @name $.jstree.defaults.dnd.large_drop_target
+ * @plugin dnd
+ */
+ large_drop_target : false,
+ /**
+ * controls whether a drag can be initiated from any part of
the node and not just the text/icon part, works best with the wholerow plugin.
Keep in mind it can cause problems with tree scrolling on mobile depending on
the interface - in that case set the touch option to "selected".
+ * @name $.jstree.defaults.dnd.large_drag_target
+ * @plugin dnd
+ */
+ large_drag_target : false
};
// TODO: now check works by checking for each node individually, how
about max_children, unique, etc?
$.jstree.plugins.dnd = function (options, parent) {
@@ -5666,14 +6220,24 @@
parent.bind.call(this);
this.element
- .on('mousedown.jstree touchstart.jstree',
'.jstree-anchor', $.proxy(function (e) {
+ .on('mousedown.jstree touchstart.jstree',
this.settings.dnd.large_drag_target ? '.jstree-node' : '.jstree-anchor',
$.proxy(function (e) {
+ if(this.settings.dnd.large_drag_target
&& $(e.target).closest('.jstree-node')[0] !== e.currentTarget) {
+ return true;
+ }
+ if(e.type === "touchstart" &&
(!this.settings.dnd.touch || (this.settings.dnd.touch === 'selected' &&
!$(e.currentTarget).closest('.jstree-node').children('.jstree-anchor').hasClass('jstree-clicked'))))
{
+ return true;
+ }
var obj = this.get_node(e.target),
- mlt = this.is_selected(obj) ?
this.get_selected().length : 1;
- if(obj && obj.id && obj.id !== "#" &&
(e.which === 1 || e.type === "touchstart") &&
- (this.settings.dnd.is_draggable
=== true || ($.isFunction(this.settings.dnd.is_draggable) &&
this.settings.dnd.is_draggable.call(this, (mlt > 1 ? this.get_selected(true) :
[obj]))))
+ mlt = this.is_selected(obj) &&
this.settings.dnd.drag_selection ? this.get_top_selected().length : 1,
+ txt = (mlt > 1 ? mlt + ' ' +
this.get_string('nodes') : this.get_text(e.currentTarget));
+ if(this.settings.core.force_text) {
+ txt = $.vakata.html.escape(txt);
+ }
+ if(obj && obj.id && obj.id !==
$.jstree.root && (e.which === 1 || e.type === "touchstart") &&
+ (this.settings.dnd.is_draggable
=== true || ($.isFunction(this.settings.dnd.is_draggable) &&
this.settings.dnd.is_draggable.call(this, (mlt > 1 ?
this.get_top_selected(true) : [obj]), e)))
) {
this.element.trigger('mousedown.jstree');
- return $.vakata.dnd.start(e, {
'jstree' : true, 'origin' : this, 'obj' : this.get_node(obj,true), 'nodes' :
mlt > 1 ? this.get_selected() : [obj.id] }, '<div id="jstree-dnd"
class="jstree-' + this.get_theme() + ' jstree-' + this.get_theme() + '-' +
this.get_theme_variant() + ' ' + ( this.settings.core.themes.responsive ? '
jstree-dnd-responsive' : '' ) + '"><i class="jstree-icon jstree-er"></i>' +
(mlt > 1 ? mlt + ' ' + this.get_string('nodes') :
this.get_text(e.currentTarget, true)) + '<ins class="jstree-copy"
style="display:none;">+</ins></div>');
+ return $.vakata.dnd.start(e, {
'jstree' : true, 'origin' : this, 'obj' : this.get_node(obj,true), 'nodes' :
mlt > 1 ? this.get_top_selected() : [obj.id] }, '<div id="jstree-dnd"
class="jstree-' + this.get_theme() + ' jstree-' + this.get_theme() + '-' +
this.get_theme_variant() + ' ' + ( this.settings.core.themes.responsive ? '
jstree-dnd-responsive' : '' ) + '"><i class="jstree-icon jstree-er"></i>' + txt
+ '<ins class="jstree-copy" style="display:none;">+</ins></div>');
}
}, this));
};
@@ -5683,12 +6247,14 @@
// bind only once for all instances
var lastmv = false,
laster = false,
+ lastev = false,
opento = false,
marker = $('<div
id="jstree-marker"> </div>').hide(); //.appendTo('body');
$(document)
.on('dnd_start.vakata.jstree', function (e, data) {
lastmv = false;
+ lastev = false;
if(!data || !data.data || !data.data.jstree) {
return; }
marker.appendTo('body'); //.show();
})
@@ -5700,12 +6266,13 @@
if(data.event.target.id && data.event.target.id
=== 'jstree-marker') {
return;
}
+ lastev = data.event;
var ins = $.jstree.reference(data.event.target),
ref = false,
off = false,
rel = false,
- l, t, h, p, i, o, ok, t1, t2, op, ps,
pr, ip, tm;
+ tmp, l, t, h, p, i, o, ok, t1, t2, op,
ps, pr, ip, tm;
// if we are over an instance
if(ins && ins._data && ins._data.dnd) {
marker.attr('class', 'jstree-' +
ins.get_theme() + ( ins.settings.core.themes.responsive ? '
jstree-dnd-responsive' : '' ));
@@ -5718,11 +6285,11 @@
if( (data.event.target ===
ins.element[0] || data.event.target === ins.get_container_ul()[0]) &&
ins.get_container_ul().children().length === 0) {
ok = true;
for(t1 = 0, t2 =
data.data.nodes.length; t1 < t2; t1++) {
- ok = ok && ins.check(
(data.data.origin && (data.data.origin.settings.dnd.always_copy ||
(data.data.origin.settings.dnd.copy && (data.event.metaKey ||
data.event.ctrlKey)) ) ? "copy_node" : "move_node"), (data.data.origin &&
data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) :
data.data.nodes[t1]), '#', 'last', { 'dnd' : true, 'ref' : ins.get_node('#'),
'pos' : 'i', 'is_multi' : (data.data.origin && data.data.origin !== ins),
'is_foreign' : (!data.data.origin) });
+ ok = ok && ins.check(
(data.data.origin && (data.data.origin.settings.dnd.always_copy ||
(data.data.origin.settings.dnd.copy && (data.event.metaKey ||
data.event.ctrlKey)) ) ? "copy_node" : "move_node"), (data.data.origin &&
data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) :
data.data.nodes[t1]), $.jstree.root, 'last', { 'dnd' : true, 'ref' :
ins.get_node($.jstree.root), 'pos' : 'i', 'origin' : data.data.origin,
'is_multi' : (data.data.origin && data.data.origin !== ins), 'is_foreign' :
(!data.data.origin) });
if(!ok) { break; }
}
if(ok) {
- lastmv = { 'ins' : ins,
'par' : '#', 'pos' : 'last' };
+ lastmv = { 'ins' : ins,
'par' : $.jstree.root, 'pos' : 'last' };
marker.hide();
data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok');
return;
@@ -5730,11 +6297,11 @@
}
else {
// if we are hovering a tree
node
- ref =
$(data.event.target).closest('.jstree-anchor');
+ ref =
ins.settings.dnd.large_drop_target ?
$(data.event.target).closest('.jstree-node').children('.jstree-anchor') :
$(data.event.target).closest('.jstree-anchor');
if(ref && ref.length &&
ref.parent().is('.jstree-closed, .jstree-open, .jstree-leaf')) {
off = ref.offset();
rel = data.event.pageY
- off.top;
- h = ref.height();
+ h = ref.outerHeight();
if(rel < h / 3) {
o = ['b', 'i',
'a'];
}
@@ -5777,7 +6344,7 @@
ps -= 1;
}
}
- ok = ok
&& ( (ins && ins.settings && ins.settings.dnd &&
ins.settings.dnd.check_while_dragging === false) || ins.check(op,
(data.data.origin && data.data.origin !== ins ?
data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), p, ps, {
'dnd' : true, 'ref' : ins.get_node(ref.parent()), 'pos' : v, 'is_multi' :
(data.data.origin && data.data.origin !== ins), 'is_foreign' :
(!data.data.origin) }) );
+ ok = ok
&& ( (ins && ins.settings && ins.settings.dnd &&
ins.settings.dnd.check_while_dragging === false) || ins.check(op,
(data.data.origin && data.data.origin !== ins ?
data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), p, ps, {
'dnd' : true, 'ref' : ins.get_node(ref.parent()), 'pos' : v, 'origin' :
data.data.origin, 'is_multi' : (data.data.origin && data.data.origin !== ins),
'is_foreign' : (!data.data.origin) }) );
if(!ok)
{
if(ins && ins.last_error) { laster = ins.last_error(); }
break;
@@ -5807,6 +6374,7 @@
if(!data || !data.data || !data.data.jstree) {
return; }
marker.hide();
lastmv = false;
+ lastev = false;
data.helper.find('.jstree-icon').first().removeClass('jstree-ok').addClass('jstree-er');
})
.on('dnd_stop.vakata.jstree', function (e, data) {
@@ -5817,16 +6385,8 @@
if(lastmv) {
for(i = 0, j = data.data.nodes.length;
i < j; i++) {
nodes[i] = data.data.origin ?
data.data.origin.get_node(data.data.nodes[i]) : data.data.nodes[i];
- if(data.data.origin) {
- nodes[i].instance =
data.data.origin;
- }
}
- lastmv.ins[ data.data.origin &&
(data.data.origin.settings.dnd.always_copy ||
(data.data.origin.settings.dnd.copy && (data.event.metaKey ||
data.event.ctrlKey))) ? 'copy_node' : 'move_node' ](nodes, lastmv.par,
lastmv.pos);
- for(i = 0, j = nodes.length; i < j;
i++) {
- if(nodes[i].instance) {
- nodes[i].instance =
null;
- }
- }
+ lastmv.ins[ data.data.origin &&
(data.data.origin.settings.dnd.always_copy ||
(data.data.origin.settings.dnd.copy && (data.event.metaKey ||
data.event.ctrlKey))) ? 'copy_node' : 'move_node' ](nodes, lastmv.par,
lastmv.pos, false, false, false, data.data.origin);
}
else {
i =
$(data.event.target).closest('.jstree');
@@ -5837,17 +6397,33 @@
}
}
}
+ lastev = false;
+ lastmv = false;
})
.on('keyup.jstree keydown.jstree', function (e, data) {
data = $.vakata.dnd._get();
if(data && data.data && data.data.jstree) {
data.helper.find('.jstree-copy').first()[ data.data.origin &&
(data.data.origin.settings.dnd.always_copy ||
(data.data.origin.settings.dnd.copy && (e.metaKey || e.ctrlKey))) ? 'show' :
'hide' ]();
+ if(lastev) {
+ lastev.metaKey = e.metaKey;
+ lastev.ctrlKey = e.ctrlKey;
+ $.vakata.dnd._trigger('move',
lastev);
+ }
}
});
});
// helpers
(function ($) {
+ $.vakata.html = {
+ div : $('<div />'),
+ escape : function (str) {
+ return $.vakata.html.div.text(str).html();
+ },
+ strip : function (str) {
+ return
$.vakata.html.div.empty().append($.parseHTML(str)).text();
+ }
+ };
// private variable
var vakata_dnd = {
element : false,
@@ -6107,6 +6683,90 @@
/**
+ * ### Massload plugin
+ *
+ * Adds massload functionality to jsTree, so that multiple nodes can be loaded
in a single request (only useful with lazy loading).
+ */
+
+ /**
+ * massload configuration
+ *
+ * It is possible to set this to a standard jQuery-like AJAX config.
+ * In addition to the standard jQuery ajax options here you can supply
functions for `data` and `url`, the functions will be run in the current
instance's scope and a param will be passed indicating which node IDs need to
be loaded, the return value of those functions will be used.
+ *
+ * You can also set this to a function, that function will receive the
node IDs being loaded as argument and a second param which is a function
(callback) which should be called with the result.
+ *
+ * Both the AJAX and the function approach rely on the same return
value - an object where the keys are the node IDs, and the value is the
children of that node as an array.
+ *
+ * {
+ * "id1" : [{ "text" : "Child of ID1", "id" : "c1" }, {
"text" : "Another child of ID1", "id" : "c2" }],
+ * "id2" : [{ "text" : "Child of ID2", "id" : "c3" }]
+ * }
+ *
+ * @name $.jstree.defaults.massload
+ * @plugin massload
+ */
+ $.jstree.defaults.massload = null;
+ $.jstree.plugins.massload = function (options, parent) {
+ this.init = function (el, options) {
+ parent.init.call(this, el, options);
+ this._data.massload = {};
+ };
+ this._load_nodes = function (nodes, callback, is_callback) {
+ var s = this.settings.massload;
+ if(is_callback &&
!$.isEmptyObject(this._data.massload)) {
+ return parent._load_nodes.call(this, nodes,
callback, is_callback);
+ }
+ if($.isFunction(s)) {
+ return s.call(this, nodes, $.proxy(function
(data) {
+ if(data) {
+ for(var i in data) {
+
if(data.hasOwnProperty(i)) {
+
this._data.massload[i] = data[i];
+ }
+ }
+ }
+ parent._load_nodes.call(this, nodes,
callback, is_callback);
+ }, this));
+ }
+ if(typeof s === 'object' && s && s.url) {
+ s = $.extend(true, {}, s);
+ if($.isFunction(s.url)) {
+ s.url = s.url.call(this, nodes);
+ }
+ if($.isFunction(s.data)) {
+ s.data = s.data.call(this, nodes);
+ }
+ return $.ajax(s)
+ .done($.proxy(function (data,t,x) {
+ if(data) {
+ for(var i in
data) {
+
if(data.hasOwnProperty(i)) {
+
this._data.massload[i] = data[i];
+ }
+ }
+ }
+
parent._load_nodes.call(this, nodes, callback, is_callback);
+ }, this))
+ .fail($.proxy(function (f) {
+
parent._load_nodes.call(this, nodes, callback, is_callback);
+ }, this));
+ }
+ return parent._load_nodes.call(this, nodes, callback,
is_callback);
+ };
+ this._load_node = function (obj, callback) {
+ var d = this._data.massload[obj.id];
+ if(d) {
+ return this[typeof d === 'string' ?
'_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ?
$($.parseHTML(d)).filter(function () { return this.nodeType !== 3; }) : d,
function (status) {
+ callback.call(this, status);
+ delete this._data.massload[obj.id];
+ });
+ }
+ return parent._load_node.call(this, obj, callback);
+ };
+ };
+
+/**
* ### Search plugin
*
* Adds search functionality to jsTree.
@@ -6121,8 +6781,8 @@
/**
* a jQuery-like AJAX config, which jstree uses if a server
should be queried for results.
*
- * A `str` (which is the search string) parameter will be added
with the request. The expected result is a JSON array with nodes that need to
be opened so that matching nodes will be revealed.
- * Leave this setting as `false` to not query the server. You
can also set this to a function, which will be invoked in the instance's scope
and receive 2 parameters - the search string and the callback to call with the
array of nodes to load.
+ * A `str` (which is the search string) parameter will be added
with the request, an optional `inside` parameter will be added if the search is
limited to a node id. The expected result is a JSON array with nodes that need
to be opened so that matching nodes will be revealed.
+ * Leave this setting as `false` to not query the server. You
can also set this to a function, which will be invoked in the instance's scope
and receive 3 parameters - the search string, the callback to call with the
array of nodes to load, and the optional node ID to limit the search to
* @name $.jstree.defaults.search.ajax
* @plugin search
*/
@@ -6147,6 +6807,13 @@
*/
show_only_matches : false,
/**
+ * Indicates if the children of matched element are shown (when
show_only_matches is true)
+ * This setting can be changed at runtime when calling the
search method. Default is `false`.
+ * @name $.jstree.defaults.search.show_only_matches_children
+ * @plugin search
+ */
+ show_only_matches_children : false,
+ /**
* Indicates if all nodes opened to reveal the search result,
should be closed when the search is cleared or a new search is performed.
Default is `true`.
* @name $.jstree.defaults.search.close_opened_onclear
* @plugin search
@@ -6176,39 +6843,30 @@
this._data.search.res = [];
this._data.search.opn = [];
this._data.search.som = false;
+ this._data.search.smc = false;
+ this._data.search.hdn = [];
this.element
- .on('before_open.jstree', $.proxy(function (e,
data) {
- var i, j, f, r =
this._data.search.res, s = [], o = $();
- if(r && r.length) {
- this._data.search.dom =
$(this.element[0].querySelectorAll('#' + $.map(r, function (v) { return
"0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' +
v.substr(1).replace($.jstree.idregex,'\\$&') :
v.replace($.jstree.idregex,'\\$&'); }).join(', #')));
-
this._data.search.dom.children(".jstree-anchor").addClass('jstree-search');
-
if(this._data.search.som && this._data.search.res.length) {
- for(i = 0, j =
r.length; i < j; i++) {
- s =
s.concat(this.get_node(r[i]).parents);
+ .on("search.jstree", $.proxy(function (e, data)
{
+ if(this._data.search.som &&
data.res.length) {
+ var m =
this._model.data, i, j, p = [];
+ for(i = 0, j =
data.res.length; i < j; i++) {
+
if(m[data.res[i]] && !m[data.res[i]].state.hidden) {
+
p.push(data.res[i]);
+ p =
p.concat(m[data.res[i]].parents);
+
if(this._data.search.smc) {
+
p = p.concat(m[data.res[i]].children_d);
+ }
}
- s =
$.vakata.array_remove_item($.vakata.array_unique(s),'#');
- o = s.length ?
$(this.element[0].querySelectorAll('#' + $.map(s, function (v) { return
"0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' +
v.substr(1).replace($.jstree.idregex,'\\$&') :
v.replace($.jstree.idregex,'\\$&'); }).join(', #'))) : $();
-
-
this.element.find(".jstree-node").hide().filter('.jstree-last').filter(function()
{ return this.nextSibling; }).removeClass('jstree-last');
- o =
o.add(this._data.search.dom);
-
o.parentsUntil(".jstree").addBack().show()
-
.filter(".jstree-children").each(function () {
$(this).children(".jstree-node:visible").eq(-1).addClass("jstree-last"); });
}
+ p =
$.vakata.array_remove_item($.vakata.array_unique(p), $.jstree.root);
+ this._data.search.hdn =
this.hide_all(true);
+ this.show_node(p);
}
}, this))
- .on("search.jstree", $.proxy(function (e, data)
{
- if(this._data.search.som) {
- if(data.nodes.length) {
-
this.element.find(".jstree-node").hide().filter('.jstree-last').filter(function()
{ return this.nextSibling; }).removeClass('jstree-last');
-
data.nodes.parentsUntil(".jstree").addBack().show()
-
.filter(".jstree-children").each(function () {
$(this).children(".jstree-node:visible").eq(-1).addClass("jstree-last"); });
- }
- }
- }, this))
.on("clear_search.jstree", $.proxy(function (e,
data) {
- if(this._data.search.som &&
data.nodes.length) {
-
this.element.find(".jstree-node").css("display","").filter('.jstree-last').filter(function()
{ return this.nextSibling; }).removeClass('jstree-last');
+ if(this._data.search.som &&
data.res.length) {
+
this.show_node(this._data.search.hdn);
}
}, this));
};
@@ -6218,38 +6876,49 @@
* @param {String} str the search string
* @param {Boolean} skip_async if set to true server will not
be queried even if configured
* @param {Boolean} show_only_matches if set to true only
matching nodes will be shown (keep in mind this can be very slow on large trees
or old browsers)
+ * @param {mixed} inside an optional node to whose children to
limit the search
+ * @param {Boolean} append if set to true the results of this
search are appended to the previous search
* @plugin search
* @trigger search.jstree
*/
- this.search = function (str, skip_async, show_only_matches) {
+ this.search = function (str, skip_async, show_only_matches,
inside, append, show_only_matches_children) {
if(str === false || $.trim(str.toString()) === "") {
return this.clear_search();
}
+ inside = this.get_node(inside);
+ inside = inside && inside.id ? inside.id : null;
str = str.toString();
var s = this.settings.search,
a = s.ajax ? s.ajax : false,
+ m = this._model.data,
f = null,
r = [],
p = [], i, j;
- if(this._data.search.res.length) {
+ if(this._data.search.res.length && !append) {
this.clear_search();
}
if(show_only_matches === undefined) {
show_only_matches = s.show_only_matches;
}
+ if(show_only_matches_children === undefined) {
+ show_only_matches_children =
s.show_only_matches_children;
+ }
if(!skip_async && a !== false) {
if($.isFunction(a)) {
return a.call(this, str,
$.proxy(function (d) {
if(d && d.d) { d = d.d;
}
this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () {
-
this.search(str, true, show_only_matches);
+
this.search(str, true, show_only_matches, inside, append);
}, true);
- }, this));
+ }, this), inside);
}
else {
a = $.extend({}, a);
if(!a.data) { a.data = {}; }
a.data.str = str;
+ if(inside) {
+ a.data.inside = inside;
+ }
return $.ajax(a)
.fail($.proxy(function () {
this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'search', 'id' :
'search_01', 'reason' : 'Could not load search parents', 'data' :
JSON.stringify(a) };
@@ -6258,30 +6927,43 @@
.done($.proxy(function (d) {
if(d && d.d) { d = d.d;
}
this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () {
-
this.search(str, true, show_only_matches);
+
this.search(str, true, show_only_matches, inside, append);
}, true);
}, this));
}
}
- this._data.search.str = str;
- this._data.search.dom = $();
- this._data.search.res = [];
- this._data.search.opn = [];
- this._data.search.som = show_only_matches;
+ if(!append) {
+ this._data.search.str = str;
+ this._data.search.dom = $();
+ this._data.search.res = [];
+ this._data.search.opn = [];
+ this._data.search.som = show_only_matches;
+ this._data.search.smc =
show_only_matches_children;
+ }
f = new $.vakata.search(str, true, { caseSensitive :
s.case_sensitive, fuzzy : s.fuzzy });
-
- $.each(this._model.data, function (i, v) {
- if(v.text && ( (s.search_callback &&
s.search_callback.call(this, str, v)) || (!s.search_callback &&
f.search(v.text).isMatch) ) && (!s.search_leaves_only || (v.state.loaded &&
v.children.length === 0)) ) {
+ $.each(m[inside ? inside : $.jstree.root].children_d,
function (ii, i) {
+ var v = m[i];
+ if(v.text && (!s.search_leaves_only ||
(v.state.loaded && v.children.length === 0)) && ( (s.search_callback &&
s.search_callback.call(this, str, v)) || (!s.search_callback &&
f.search(v.text).isMatch) ) ) {
r.push(i);
p = p.concat(v.parents);
}
});
if(r.length) {
p = $.vakata.array_unique(p);
- this._search_open(p);
- this._data.search.dom =
$(this.element[0].querySelectorAll('#' + $.map(r, function (v) { return
"0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' +
v.substr(1).replace($.jstree.idregex,'\\$&') :
v.replace($.jstree.idregex,'\\$&'); }).join(', #')));
- this._data.search.res = r;
+ for(i = 0, j = p.length; i < j; i++) {
+ if(p[i] !== $.jstree.root && m[p[i]] &&
this.open_node(p[i], null, 0) === true) {
+
this._data.search.opn.push(p[i]);
+ }
+ }
+ if(!append) {
+ this._data.search.dom =
$(this.element[0].querySelectorAll('#' + $.map(r, function (v) { return
"0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' +
v.substr(1).replace($.jstree.idregex,'\\$&') :
v.replace($.jstree.idregex,'\\$&'); }).join(', #')));
+ this._data.search.res = r;
+ }
+ else {
+ this._data.search.dom =
this._data.search.dom.add($(this.element[0].querySelectorAll('#' + $.map(r,
function (v) { return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' +
v.substr(1).replace($.jstree.idregex,'\\$&') :
v.replace($.jstree.idregex,'\\$&'); }).join(', #'))));
+ this._data.search.res =
$.vakata.array_unique(this._data.search.res.concat(r));
+ }
this._data.search.dom.children(".jstree-anchor").addClass('jstree-search');
}
/**
@@ -6302,7 +6984,6 @@
* @trigger clear_search.jstree
*/
this.clear_search = function () {
-
this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search");
if(this.settings.search.close_opened_onclear) {
this.close_node(this._data.search.opn, 0);
}
@@ -6316,30 +6997,35 @@
* @plugin search
*/
this.trigger('clear_search', { 'nodes' :
this._data.search.dom, str : this._data.search.str, res : this._data.search.res
});
+ if(this._data.search.res.length) {
+ this._data.search.dom =
$(this.element[0].querySelectorAll('#' + $.map(this._data.search.res, function
(v) {
+ return "0123456789".indexOf(v[0]) !==
-1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') :
v.replace($.jstree.idregex,'\\$&');
+ }).join(', #')));
+
this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search");
+ }
this._data.search.str = "";
this._data.search.res = [];
this._data.search.opn = [];
this._data.search.dom = $();
};
- /**
- * opens nodes that need to be opened to reveal the search
results. Used only internally.
- * @private
- * @name _search_open(d)
- * @param {Array} d an array of node IDs
- * @plugin search
- */
- this._search_open = function (d) {
- var t = this;
- $.each(d.concat([]), function (i, v) {
- if(v === "#") { return true; }
- try { v = $('#' +
v.replace($.jstree.idregex,'\\$&'), t.element); } catch(ignore) { }
- if(v && v.length) {
- if(t.is_closed(v)) {
-
t._data.search.opn.push(v[0].id);
- t.open_node(v, function () {
t._search_open(d); }, 0);
+
+ this.redraw_node = function(obj, deep, callback, force_render) {
+ obj = parent.redraw_node.apply(this, arguments);
+ if(obj) {
+ if($.inArray(obj.id, this._data.search.res) !==
-1) {
+ var i, j, tmp = null;
+ for(i = 0, j = obj.childNodes.length; i
< j; i++) {
+ if(obj.childNodes[i] &&
obj.childNodes[i].className &&
obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) {
+ tmp = obj.childNodes[i];
+ break;
+ }
}
+ if(tmp) {
+ tmp.className += '
jstree-search';
+ }
}
- });
+ }
+ return obj;
};
};
@@ -6348,13 +7034,14 @@
// from http://kiro.me/projects/fuse.html
$.vakata.search = function(pattern, txt, options) {
options = options || {};
+ options = $.extend({}, $.vakata.search.defaults,
options);
if(options.fuzzy !== false) {
options.fuzzy = true;
}
pattern = options.caseSensitive ? pattern :
pattern.toLowerCase();
- var MATCH_LOCATION = options.location || 0,
- MATCH_DISTANCE = options.distance || 100,
- MATCH_THRESHOLD = options.threshold || 0.6,
+ var MATCH_LOCATION = options.location,
+ MATCH_DISTANCE = options.distance,
+ MATCH_THRESHOLD = options.threshold,
patternLen = pattern.length,
matchmask, pattern_alphabet, match_bitapScore,
search;
if(patternLen > 32) {
@@ -6462,11 +7149,19 @@
};
return txt === true ? { 'search' : search } :
search(txt);
};
+ $.vakata.search.defaults = {
+ location : 0,
+ distance : 100,
+ threshold : 0.6,
+ fuzzy : false,
+ caseSensitive : false
+ };
}($));
// include the search plugin by default
// $.jstree.defaults.plugins.push("search");
+
/**
* ### Sort plugin
*
@@ -6549,7 +7244,7 @@
* @name $.jstree.defaults.state.events
* @plugin state
*/
- events : 'changed.jstree open_node.jstree close_node.jstree',
+ events : 'changed.jstree open_node.jstree close_node.jstree
check_node.jstree uncheck_node.jstree',
/**
* Time in milliseconds after which the state will expire.
Defaults to 'false' meaning - no expire.
* @name $.jstree.defaults.state.ttl
@@ -6571,6 +7266,13 @@
if(to) { clearTimeout(to); }
to = setTimeout($.proxy(function () {
this.save_state(); }, this), 100);
}, this));
+ /**
+ * triggered when the state plugin is finished
restoring the state (and immediately after ready if there is no state to
restore).
+ * @event
+ * @name state_ready.jstree
+ * @plugin state
+ */
+ this.trigger('state_ready');
}, this);
this.element
.on("ready.jstree", $.proxy(function (e, data) {
@@ -6635,31 +7337,31 @@
/**
* An object storing all types as key value pairs, where the key is the
type name and the value is an object that could contain following keys (all
optional).
- *
+ *
* * `max_children` the maximum number of immediate children this node
type can have. Do not specify or set to `-1` for unlimited.
* * `max_depth` the maximum number of nesting this node type can have.
A value of `1` would mean that the node can have children, but no
grandchildren. Do not specify or set to `-1` for unlimited.
* * `valid_children` an array of node type strings, that nodes of this
type can have as children. Do not specify or set to `-1` for no limits.
* * `icon` a string - can be a path to an icon or a className, if
using an image that is in the current directory use a `./` prefix, otherwise it
will be detected as a class. Omit to use the default icon from your theme.
*
* There are two predefined types:
- *
+ *
* * `#` represents the root of the tree, for example `max_children`
would control the maximum number of root nodes.
* * `default` represents the default node - any settings here will be
applied to all nodes that do not have a type specified.
- *
+ *
* @name $.jstree.defaults.types
* @plugin types
*/
$.jstree.defaults.types = {
- '#' : {},
'default' : {}
};
+ $.jstree.defaults.types[$.jstree.root] = {};
$.jstree.plugins.types = function (options, parent) {
this.init = function (el, options) {
var i, j;
if(options && options.types &&
options.types['default']) {
for(i in options.types) {
- if(i !== "default" && i !== "#" &&
options.types.hasOwnProperty(i)) {
+ if(i !== "default" && i !==
$.jstree.root && options.types.hasOwnProperty(i)) {
for(j in
options.types['default']) {
if(options.types['default'].hasOwnProperty(j) && options.types[i][j] ===
undefined) {
options.types[i][j] = options.types['default'][j];
@@ -6669,11 +7371,11 @@
}
}
parent.init.call(this, el, options);
- this._model.data['#'].type = '#';
+ this._model.data[$.jstree.root].type = $.jstree.root;
};
this.refresh = function (skip_loading, forget_state) {
parent.refresh.call(this, skip_loading, forget_state);
- this._model.data['#'].type = '#';
+ this._model.data[$.jstree.root].type = $.jstree.root;
};
this.bind = function () {
this.element
@@ -6695,7 +7397,7 @@
m[dpc[i]].icon
= t[c].icon;
}
}
- m['#'].type = '#';
+ m[$.jstree.root].type =
$.jstree.root;
}, this));
parent.bind.call(this);
};
@@ -6750,7 +7452,7 @@
if(parent.check.call(this, chk, obj, par, pos, more)
=== false) { return false; }
obj = obj && obj.id ? obj : this.get_node(obj);
par = par && par.id ? par : this.get_node(par);
- var m = obj && obj.id ? $.jstree.reference(obj.id) :
null, tmp, d, i, j;
+ var m = obj && obj.id ? (more && more.origin ?
more.origin : $.jstree.reference(obj.id)) : null, tmp, d, i, j;
m = m && m._model && m._model.data ? m._model.data :
null;
switch(chk) {
case "create_node":
@@ -6911,7 +7613,7 @@
}
return i;
case "move_node":
- i = (obj.parent === par.id ||
$.inArray(n, c) === -1);
+ i = ( (obj.parent === par.id && (!more
|| !more.is_multi)) || $.inArray(n, c) === -1);
if(!i) {
this._data.core.last_error = {
'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_03', 'reason' : 'Child
with name ' + n + ' already exists. Preventing: ' + chk, 'data' :
JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id :
false, 'par' : par && par.id ? par.id : false }) };
}
@@ -6922,7 +7624,7 @@
this.create_node = function (par, node, pos, callback,
is_loaded) {
if(!node || node.text === undefined) {
if(par === null) {
- par = "#";
+ par = $.jstree.root;
}
par = this.get_node(par);
if(!par) {
@@ -7001,6 +7703,15 @@
var tmp =
$.Event('contextmenu', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey :
e.altKey, shiftKey : e.shiftKey, pageX : e.pageX, pageY : e.pageY });
$(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp);
}, this))
+ /*!
+ .on("mousedown.jstree touchstart.jstree",
".jstree-wholerow", function (e) {
+ if(e.target ===
e.currentTarget) {
+ var a =
$(e.currentTarget).closest(".jstree-node").children(".jstree-anchor");
+ e.target = a[0];
+ a.trigger(e);
+ }
+ })
+ */
.on("click.jstree", ".jstree-wholerow",
function (e) {
e.stopImmediatePropagation();
var tmp = $.Event('click', {
metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey :
e.shiftKey });
@@ -7042,9 +7753,6 @@
};
// include the wholerow plugin by default
// $.jstree.defaults.plugins.push("wholerow");
-
-
-(function ($) {
if(document.registerElement && Object && Object.create) {
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function () {
@@ -7062,12 +7770,12 @@
c.core[i] =
JSON.parse(this.getAttribute(i)) || this.getAttribute(i);
}
}
- jQuery(this).jstree(c);
+ $(this).jstree(c);
};
// proto.attributeChangedCallback = function (name, previous,
value) { };
try {
document.registerElement("vakata-jstree", { prototype:
proto });
} catch(ignore) { }
}
-}(jQuery));
+
}));
\ No newline at end of file
Modified: branches/dev-syncromind/phpgwapi/js/jquery/treeview/jstree.min.js
===================================================================
--- branches/dev-syncromind/phpgwapi/js/jquery/treeview/jstree.min.js
2015-11-20 15:01:27 UTC (rev 14435)
+++ branches/dev-syncromind/phpgwapi/js/jquery/treeview/jstree.min.js
2015-11-20 15:05:42 UTC (rev 14436)
@@ -1,5 +1,5 @@
-/*! jsTree - v3.0.8 - 2014-10-23 - (MIT) */
@@ Diff output truncated at 153600 characters. @@
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Fmsystem-commits] [14436] update treeview from upstream,
Sigurd Nes <=