vendor/assets/javascripts/jstree.js in jstree-rails-4-3.1.1 vs vendor/assets/javascripts/jstree.js in jstree-rails-4-3.2.0
- old
+ new
@@ -1,21 +1,21 @@
-/*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);
}
}(function ($, undefined) {
"use strict";
/*!
- * jsTree 3.1.1
+ * jsTree 3.2.0
* http://jstree.com/
*
* Copyright (c) 2014 Ivan Bozhanov (http://vakata.com)
*
* Licensed same as jquery - under the terms of the MIT License
@@ -26,11 +26,10 @@
* jslint: browser: true, ass: true, bitwise: true, continue: true, nomen: true, plusplus: true, regexp: true, unparam: true, todo: true, white: true
*/
// prevent another load? maybe there is a better way?
if($.jstree) {
- return;
}
/**
* ### jsTree core functionality
*/
@@ -69,11 +68,11 @@
$.jstree = {
/**
* specifies the jstree version in use
* @name $.jstree.version
*/
- version : '3.1.1',
+ version : '3.2.0',
/**
* holds all the default options used when creating new instances
* @name $.jstree.defaults
*/
defaults : {
@@ -87,11 +86,12 @@
* stores all loaded jstree plugins (used internally)
* @name $.jstree.plugins
*/
plugins : {},
path : src && src.indexOf('/') !== -1 ? src.replace(/\/[^\/]+$/,'') : '',
- idregex : /[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g
+ idregex : /[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g,
+ root : '#'
};
/**
* creates a jstree instance
* @name $.jstree.create(el [, options])
* @param {DOMElement|jQuery|String} el the element to create the instance on, can be jQuery extended or a selector
@@ -469,30 +469,29 @@
* @param {Object} options options for this instance
* @trigger init.jstree, loading.jstree, loaded.jstree, ready.jstree, changed.jstree
*/
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,
default_state : {
loaded : true,
opened : false,
selected : false,
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._data.core.ready = false;
@@ -529,11 +528,11 @@
* triggered after the loading text is shown and before loading starts
* @event
* @name loading.jstree
*/
this.trigger("loading");
- this.load_node('#');
+ this.load_node($.jstree.root);
},
/**
* destroy an instance
* @name destroy()
* @param {Boolean} keep_html if not set to `true` the container will be emptied, otherwise the current DOM elements will be kept intact
@@ -572,11 +571,12 @@
bind : function () {
var word = '',
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();
}
else {
if(window.getSelection) {
@@ -599,21 +599,22 @@
})
.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; }
else if(e.which === 39) { e.which = 37; }
@@ -634,11 +635,11 @@
if(this.is_open(e.currentTarget)) {
this.close_node(e.currentTarget);
}
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
e.preventDefault();
o = this.get_prev_dom(e.currentTarget);
@@ -674,20 +675,20 @@
/*
// 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);
}
break;
// f2
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;
default:
// console.log(e.which);
@@ -695,11 +696,11 @@
*/
}
}, 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);
}
/**
@@ -737,11 +738,11 @@
}
}
}, 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 = '';
}, 500);
@@ -771,11 +772,11 @@
}
}, this));
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) {
$(v).focus();
end = true;
@@ -958,18 +959,18 @@
}
else if((dom = $(obj, this.element)).length && this._model.data[dom.closest('.jstree-node').attr('id')]) {
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; }
},
/**
@@ -980,11 +981,11 @@
* @param {Boolean} ids if set to true build the path using ID, otherwise node text is used
* @return {mixed}
*/
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 = [];
p.push(ids ? obj.id : obj.text);
for(i = 0, j = obj.parents.length; i < j; i++) {
@@ -1085,11 +1086,11 @@
* @param {mixed} obj
* @return {String}
*/
get_parent : function (obj) {
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
return obj.parent;
},
/**
@@ -1211,12 +1212,18 @@
this._load_node(obj, $.proxy(function (status) {
obj = this._model.data[obj.id];
obj.state.loading = false;
obj.state.loaded = status;
obj.state.failed = !obj.state.loaded;
- var dom = this.get_node(obj, true);
- if(obj.state.loaded && !obj.children.length && dom && dom.length && !dom.hasClass('jstree-leaf')) {
+ 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);
/**
* triggered after a node is loaded
@@ -1269,11 +1276,11 @@
* @param {mixed} obj the node to load recursively, omit to load all nodes in the tree
* @param {function} callback a function to be executed once loading all the nodes is complete,
* @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 = [],
m = this._model.data,
c = m[obj.id].children_d,
@@ -1312,19 +1319,19 @@
*/
_load_node : function (obj, callback) {
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);
});
}
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);
@@ -1364,34 +1371,34 @@
this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : f }) };
this.settings.core.error.call(this, this._data.core.last_error);
}, 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);
});
}
else {
this._data.core.last_error = { 'error' : 'nodata', 'plugin' : 'core', 'id' : 'core_05', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id }) };
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 === '#') {
+ 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);
});
}
else {
this._data.core.last_error = { 'error' : 'nodata', 'plugin' : 'core', 'id' : 'core_06', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id }) };
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);
},
/**
* adds a node to the list of nodes to redraw. Used only internally.
@@ -1446,11 +1453,11 @@
* @name model.jstree
* @param {Array} nodes an array of node IDs
* @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();
}
else {
this.get_container_ul().children('.jstree-initial-node').remove();
@@ -1791,11 +1798,11 @@
this._data.core.selected = this._data.core.selected.concat(rslt.add);
}
this.trigger('model', { "nodes" : rslt.dpc, 'parent' : rslt.par });
- if(rslt.par !== '#') {
+ if(rslt.par !== $.jstree.root) {
this._node_changed(rslt.par);
this.redraw();
}
else {
// this.get_container_ul().children('.jstree-initial-node').remove();
@@ -2184,11 +2191,11 @@
* @private
* @name _redraw()
* @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);
if(tmp && this._model.force_full_redraw) {
f.appendChild(tmp);
@@ -2245,11 +2252,11 @@
i = false,
j = false,
k = false,
d = document;
if(!obj) { return false; }
- if(obj.id === '#') { return this.redraw(true); }
+ 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];
@@ -2285,24 +2292,26 @@
m = this._model.data,
f = false,
s = false,
tmp = null,
t = 0,
- l = 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 {
node = $(node);
if(!is_callback) {
@@ -2347,18 +2356,43 @@
node.setAttribute('aria-labelledby', obj.a_attr.id);
if(obj.state.disabled) {
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;
node.className = c;
c = ( obj.state.selected ? ' jstree-clicked' : '') + ( obj.state.disabled ? ' jstree-disabled' : '');
@@ -2468,11 +2502,11 @@
this.open_node(obj[t1], callback, animation);
}
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;
if(!this.is_closed(obj)) {
if(callback) {
@@ -2555,16 +2589,16 @@
* @param {mixed} obj the node to reveal
* @private
*/
_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);
}
}
return $('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element);
},
@@ -2583,11 +2617,11 @@
this.close_node(obj[t1], animation);
}
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
if(this.is_closed(obj)) {
return false;
}
@@ -2656,14 +2690,14 @@
* @param {Number} animation the animation duration in milliseconds when opening the nodes, the default is no animation
* @param {jQuery} reference to the node that started the process (internal use)
* @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]])) {
this._model.data[obj.children_d[i]].state.opened = true;
}
@@ -2696,23 +2730,22 @@
* @param {mixed} obj the node to close recursively, omit to close all nodes in the tree
* @param {Number} animation the animation duration in milliseconds when closing the nodes, the default is no animation
* @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
* @name close_all.jstree
* @param {Object} node the closed node
@@ -2743,11 +2776,11 @@
this.enable_node(obj[t1]);
}
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
obj.state.disabled = false;
this.get_node(obj,true).children('.jstree-anchor').removeClass('jstree-disabled').attr('aria-disabled', false);
/**
@@ -2772,11 +2805,11 @@
this.disable_node(obj[t1]);
}
return true;
}
obj = this.get_node(obj);
- if(!obj || obj.id === '#') {
+ if(!obj || obj.id === $.jstree.root) {
return false;
}
obj.state.disabled = true;
this.get_node(obj,true).children('.jstree-anchor').addClass('jstree-disabled').attr('aria-disabled', true);
/**
@@ -2786,10 +2819,130 @@
* @param {Object} node the disabled node
*/
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 (obj) {
+ 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;
+ 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 (obj) {
+ 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;
+ 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)
* @param {mixed} obj the node
* @param {Object} e the related event
@@ -2797,10 +2950,13 @@
*/
activate_node : function (obj, e) {
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;
if(this._data.core.last_clicked && !this._data.core.last_clicked.state.selected) { this._data.core.last_clicked = null; }
if(!this._data.core.last_clicked && this._data.core.selected.length) { this._data.core.last_clicked = this.get_node(this._data.core.selected[this._data.core.selected.length - 1]); }
@@ -2851,12 +3007,13 @@
/**
* triggered when an node is clicked or intercated with by the user
* @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.
* @private
* @name hover_node(obj)
@@ -2918,11 +3075,11 @@
this.select_node(obj[t1], supress_event, prevent_open, e);
}
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);
if(!obj.state.selected) {
obj.state.selected = true;
@@ -2971,11 +3128,11 @@
this.deselect_node(obj[t1], supress_event, e);
}
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);
if(obj.state.selected) {
obj.state.selected = false;
@@ -3003,11 +3160,11 @@
* @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered
* @trigger select_all.jstree, changed.jstree
*/
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;
}
}
@@ -3056,11 +3213,11 @@
* @param {mixed} obj
* @return {Boolean}
*/
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;
},
/**
@@ -3139,11 +3296,11 @@
'selected' : []
}
}, 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);
}
if(this._model.data[i].state.selected) {
state.core.selected.push(i);
@@ -3155,11 +3312,11 @@
},
/**
* 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) {
@@ -3235,26 +3392,29 @@
*/
refresh : function (skip_loading, forget_state) {
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])) {
this.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).id);
}
@@ -3276,11 +3436,11 @@
* @param {mixed} obj the node
* @trigger refresh_node.jstree
*/
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); }
this.get_node(obj, true).find('.jstree-open').each(function() { opened.push(this.id); });
this._load_nodes(to_load, $.proxy(function (nodes) {
@@ -3303,11 +3463,11 @@
* @param {String} id the new ID
* @return {Boolean}
*/
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)
m[obj.parent].children[$.inArray(obj.id, m[obj.parent].children)] = id;
for(i = 0, j = obj.parents.length; i < j; i++) {
@@ -3342,11 +3502,11 @@
* @param {mixed} obj the node
* @return {String}
*/
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)`.
* @private
* @name set_text(obj, val)
@@ -3363,11 +3523,11 @@
this.set_text(obj[t1], val);
}
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);
}
/**
@@ -3391,11 +3551,11 @@
* @param {Boolean} options.no_data do not include node data
* @param {Boolean} options.flat return flat JSON instead of nested
* @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 = {
'id' : obj.id,
'text' : obj.text,
@@ -3426,11 +3586,11 @@
}
if(tmp.a_attr && tmp.a_attr.id) {
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) {
for(i = 0, j = obj.children.length; i < j; i++) {
if(options && options.flat) {
@@ -3439,11 +3599,11 @@
else {
tmp.children.push(this.get_json(obj.children[i], options));
}
}
}
- 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)
* @name create_node([obj, node, pos, callback, is_loaded])
* @param {mixed} par the parent node (to create a root node use either "#" (string) or `null`)
@@ -3453,11 +3613,11 @@
* @param {Boolean} is_loaded internal argument indicating if the parent node was succesfully loaded
* @return {String} the ID of the newly create node
* @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;
if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) {
return this.load_node(par, function () { this.create_node(par, node, pos, callback, true); });
@@ -3465,11 +3625,11 @@
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"; }
}
switch(pos) {
case "before":
@@ -3549,11 +3709,11 @@
this.rename_node(obj[t1], val);
}
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);
return false;
}
@@ -3575,20 +3735,20 @@
* @param {mixed} obj the node, you can pass an array to delete multiple nodes
* @return {Boolean}
* @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++) {
this.delete_node(obj[t1]);
}
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;
if(!this.check("delete_node", obj, par, pos)) {
this.settings.core.error.call(this, this._data.core.last_error);
@@ -3626,10 +3786,23 @@
this.trigger('changed', { 'action' : 'delete_node', 'node' : obj, 'selected' : this._data.core.selected, 'parent' : par.id });
}
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;
},
/**
* check if an operation is premitted on the tree. Used internally.
@@ -3712,14 +3885,14 @@
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_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];
@@ -3731,11 +3904,11 @@
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"; }
}
switch(pos) {
case "before":
@@ -3772,11 +3945,11 @@
tmp[i >= pos ? i+1 : i] = dpc[i];
}
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
tmp = obj.children_d.concat();
tmp.push(obj.id);
@@ -3817,11 +3990,11 @@
for(i = 0, j = obj.children_d.length; i < j; i++) {
this._model.data[obj.children_d[i]].parents = this._model.data[obj.children_d[i]].parents.slice(0,p*-1);
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) {
this._node_changed(old_par);
this._node_changed(new_par.id);
@@ -3884,22 +4057,22 @@
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_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(old_ins && old_ins._id) {
obj = old_ins._model.data[obj.id];
}
- if(par.id === '#') {
+ if(par.id === $.jstree.root) {
if(pos === "before") { pos = "first"; }
if(pos === "after") { pos = "last"; }
}
switch(pos) {
case "before":
@@ -3947,18 +4120,18 @@
dpc[pos] = tmp.id;
new_par.children = dpc;
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); }
/**
* triggered when a node is copied
* @event
@@ -3987,11 +4160,11 @@
if(!$.isArray(obj)) { obj = [obj]; }
if(!obj.length) { return false; }
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;
ccp_inst = this;
ccp_mode = 'move_node';
@@ -4014,11 +4187,11 @@
if(!$.isArray(obj)) { obj = [obj]; }
if(!obj.length) { return false; }
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;
ccp_inst = this;
ccp_mode = 'copy_node';
@@ -4090,14 +4263,14 @@
/**
* put a node in edit mode (input field to rename the node)
* @name edit(obj [, default_text, callback])
* @param {mixed} obj
* @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 and a status parameter - true if the rename is successful, false otherwise. You can access the node's title using .text
+ * @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, callback) {
- var rtl, w, a, s, t, h1, h2, fn, tmp;
+ 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) {
this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_07', 'reason' : 'Could not edit node because of check_callback' };
this.settings.core.error.call(this, this._data.core.last_error);
@@ -4109,11 +4282,12 @@
obj = this._open_to(obj);
tmp.text = default_text;
rtl = this._data.core.rtl;
w = this.element.width();
- a = obj.children('.jstree-anchor');
+ 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,
@@ -4132,11 +4306,13 @@
"display" : "inline-block",
"height" : (this._data.core.li_height) + "px",
"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(),
f = this.settings.core.force_text,
nv;
if(v === "") { v = t; }
@@ -4147,34 +4323,43 @@
this.set_text(obj, t);
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);
+ 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') || '',
@@ -4309,11 +4494,11 @@
this.set_icon(obj[t1], icon);
}
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 === 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);
@@ -4340,11 +4525,11 @@
* @param {mixed} obj
* @return {String}
*/
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
* @name hide_icon(obj)
* @param {mixed} obj
@@ -4357,11 +4542,11 @@
this.hide_icon(obj[t1]);
}
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;
},
/**
@@ -4377,11 +4562,11 @@
this.show_icon(obj[t1]);
}
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; }
dom.children(".jstree-anchor").children(".jstree-themeicon").removeClass('jstree-themeicon-hidden');
return true;
@@ -4428,10 +4613,63 @@
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.
* 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.
*/
@@ -4519,11 +4757,11 @@
var m = this._model.data,
p = m[data.parent],
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]);
}
}
}, this));
@@ -4565,11 +4803,11 @@
}
}
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' ];
}
if(c === j) {
@@ -4609,11 +4847,11 @@
}
}
// 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' ];
}
if(c === j) {
@@ -4635,11 +4873,11 @@
if(s.indexOf('down') !== -1 && dom.length) {
dom.find('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked').parent().attr('aria-selected', true);
}
}, 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++) {
tmp = m[obj.children_d[i]];
if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) {
@@ -4703,11 +4941,11 @@
.on('delete_node.jstree', $.proxy(function (e, data) {
// apply up (whole handler)
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) {
c = 0;
for(i = 0, j = p.children.length; i < j; i++) {
c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
}
if(c === j) {
@@ -4731,11 +4969,11 @@
new_par = this.get_node(data.parent),
m = this._model.data,
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) {
c = 0;
for(i = 0, j = p.children.length; i < j; i++) {
c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
}
if(c === j) {
@@ -4751,11 +4989,11 @@
}
p = this.get_node(p.parent);
}
}
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' ];
}
if(c === j) {
@@ -4796,11 +5034,11 @@
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) {
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] !== '#') {
+ 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]);
}
}
}
@@ -4809,32 +5047,32 @@
this.element.find('.jstree-closed').not(':has(.jstree-children)')
.each(function () {
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) {
- if(o[tmp.id] === undefined && tmp.id !== '#') {
+ 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] !== '#') {
+ 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) {
- if(o[tmp2.id] === undefined && tmp2.id !== '#') {
+ 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] !== '#') {
+ if(o[tmp2.parents[k]] === undefined && tmp2.parents[k] !== $.jstree.root) {
o[tmp2.parents[k]] = true;
p.push(tmp2.parents[k]);
}
}
}
@@ -4853,20 +5091,22 @@
}
};
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];
break;
}
}
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) {
if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); }
this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50);
@@ -4911,12 +5151,87 @@
return true;
}
}
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);
@@ -4949,11 +5264,11 @@
this.check_node(obj[t1], e);
}
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);
if(!obj.state.checked) {
obj.state.checked = true;
@@ -4989,11 +5304,11 @@
this.uncheck_node(obj[t1], e);
}
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);
if(obj.state.checked) {
obj.state.checked = false;
@@ -5020,11 +5335,11 @@
* @plugin checkbox
*/
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;
}
}
@@ -5072,11 +5387,11 @@
* @plugin checkbox
*/
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;
};
/**
* get an array of all checked nodes (if tie_selection is on in the settings this function will return the same as get_selected)
* @name get_checked([full])
@@ -5170,16 +5485,44 @@
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.
*/
@@ -5410,11 +5753,11 @@
* @plugin contextmenu
* @trigger show_contextmenu.jstree
*/
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"),
o = false,
i = false;
@@ -5815,11 +6158,11 @@
* @name $.jstree.defaults.dnd.open_timeout
* @plugin dnd
*/
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
*/
is_draggable : true,
/**
@@ -5882,12 +6225,12 @@
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 !== "#" && (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]))))
+ 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_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));
@@ -5896,16 +6239,18 @@
$(function() {
// 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();
})
.on('dnd_move.vakata.jstree', function (e, data) {
if(opento) { clearTimeout(opento); }
@@ -5913,10 +6258,11 @@
// if we are hovering the marker image do nothing (can happen on "inside" drags)
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,
@@ -5931,15 +6277,15 @@
// if are hovering the container itself add a new root node
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', 'origin' : data.data.origin, '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;
}
}
@@ -6020,10 +6366,11 @@
})
.on('dnd_scroll.vakata.jstree', function (e, data) {
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) {
if(opento) { clearTimeout(opento); }
if(!data || !data.data || !data.data.jstree) { return; }
@@ -6042,15 +6389,22 @@
if(i) {
i.settings.core.error.call(this, laster);
}
}
}
+ 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
@@ -6482,49 +6836,33 @@
this._data.search.dom = $();
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);
- }
- 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);
- if(this._data.search.smc) {
- this._data.search.dom.children(".jstree-children").find(".jstree-node").show();
- }
- o.parentsUntil(".jstree").addBack().show()
- .filter(".jstree-children").each(function () { $(this).children(".jstree-node:visible").eq(-1).addClass("jstree-last"); });
- }
- }
- }, 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');
- if(this._data.search.smc) {
- data.nodes.children(".jstree-children").find(".jstree-node").show();
+ 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);
+ }
}
- data.nodes.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();
+ this.show_node(p);
}
}, 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));
};
/**
* used to search the tree nodes for a given string
@@ -6596,13 +6934,13 @@
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(m[inside ? inside : '#'].children_d, function (ii, i) {
+ $.each(m[inside ? inside : $.jstree.root].children_d, function (ii, i) {
var v = m[i];
- 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)) ) {
+ 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) {
@@ -6634,11 +6972,10 @@
* @name clear_search()
* @plugin search
* @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);
}
/**
* triggered after search is complete
@@ -6648,10 +6985,16 @@
* @param {String} str the search string (the last search string)
* @param {Array} res a collection of objects represeing the matching nodes (the result from the last search)
* @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 = $();
};
@@ -6663,20 +7006,39 @@
* @plugin search
*/
this._search_open = function (d) {
var t = this;
$.each(d.concat([]), function (i, v) {
- if(v === "#") { return true; }
+ if(v === $.jstree.root) { 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;
+ };
};
// helpers
(function ($) {
// from http://kiro.me/projects/fuse.html
@@ -6807,10 +7169,11 @@
}($));
// include the search plugin by default
// $.jstree.defaults.plugins.push("search");
+
/**
* ### Sort plugin
*
* Automatically sorts all siblings in the tree according to a sorting function.
*/
@@ -6997,34 +7360,34 @@
*
* @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];
}
}
}
}
}
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
.on('model.jstree', $.proxy(function (e, data) {
var m = this._model.data,
@@ -7042,11 +7405,11 @@
m[dpc[i]].type = c;
if(m[dpc[i]].icon === true && t[c].icon !== undefined) {
m[dpc[i]].icon = t[c].icon;
}
}
- m['#'].type = '#';
+ m[$.jstree.root].type = $.jstree.root;
}, this));
parent.bind.call(this);
};
this.get_json = function (obj, options, flat) {
var i, j,
@@ -7269,11 +7632,11 @@
return true;
};
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) {
return parent.create_node.call(this, par, node, pos, callback, is_loaded);
}
@@ -7423,6 +7786,7 @@
try {
document.registerElement("vakata-jstree", { prototype: proto });
} catch(ignore) { }
}
+ return $.fn.jstree;
}));
\ No newline at end of file