jstree-rails-4 3.1.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 637c3e2030c64578c72668ab8339dec3e696ac7d
4
- data.tar.gz: 2b738a880fa41dbfd500dce03593238d72a5ac60
3
+ metadata.gz: 10c8869f306a834bdbbd828f0fcb7bb7d1812f6e
4
+ data.tar.gz: f0cf31ae828d584665f444ff7de9b746e6a74e4d
5
5
  SHA512:
6
- metadata.gz: 665ee89eeca36314c2a004a9607a943ce852114b08ae8207028a141c1cb0d8fb0e58a2d89d4545f56d3986e5ec101aeff7b91e0a7c9cd8b9f6a5f539e8d8538e
7
- data.tar.gz: d63e91d381c838e53672f7a508350a670df3bcd522026abaf32315a1d815f161a689bb5dbc4c1053551ffa83a259f8e4cb1dfc1cd0690a5ad1626e603d458f84
6
+ metadata.gz: 295125af3463ddbbdc35d455f266cbfc5e2b4d54e26a232dc0f4ee359ac9b3915319a6ebe0aac35ded73994989526c761f9ec191a46f4d329c16e4b7badbd9d1
7
+ data.tar.gz: 7ed4f4caa2d2ea716ca982d62a8f52ff9dd23867b6e86be1dc5638c6ac97d95b0f4347af18a2ce89f92bdcae49d26ea741ed924547e726e24b18e10bef4b271b
data/Gemfile.lock CHANGED
@@ -1,76 +1,76 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jstree-rails-4 (3.1.0)
4
+ jstree-rails-4 (3.1.1)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
- actionmailer (4.2.1)
10
- actionpack (= 4.2.1)
11
- actionview (= 4.2.1)
12
- activejob (= 4.2.1)
9
+ actionmailer (4.2.3)
10
+ actionpack (= 4.2.3)
11
+ actionview (= 4.2.3)
12
+ activejob (= 4.2.3)
13
13
  mail (~> 2.5, >= 2.5.4)
14
14
  rails-dom-testing (~> 1.0, >= 1.0.5)
15
- actionpack (4.2.1)
16
- actionview (= 4.2.1)
17
- activesupport (= 4.2.1)
15
+ actionpack (4.2.3)
16
+ actionview (= 4.2.3)
17
+ activesupport (= 4.2.3)
18
18
  rack (~> 1.6)
19
19
  rack-test (~> 0.6.2)
20
20
  rails-dom-testing (~> 1.0, >= 1.0.5)
21
- rails-html-sanitizer (~> 1.0, >= 1.0.1)
22
- actionview (4.2.1)
23
- activesupport (= 4.2.1)
21
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
22
+ actionview (4.2.3)
23
+ activesupport (= 4.2.3)
24
24
  builder (~> 3.1)
25
25
  erubis (~> 2.7.0)
26
26
  rails-dom-testing (~> 1.0, >= 1.0.5)
27
- rails-html-sanitizer (~> 1.0, >= 1.0.1)
28
- activejob (4.2.1)
29
- activesupport (= 4.2.1)
27
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
28
+ activejob (4.2.3)
29
+ activesupport (= 4.2.3)
30
30
  globalid (>= 0.3.0)
31
- activemodel (4.2.1)
32
- activesupport (= 4.2.1)
31
+ activemodel (4.2.3)
32
+ activesupport (= 4.2.3)
33
33
  builder (~> 3.1)
34
- activerecord (4.2.1)
35
- activemodel (= 4.2.1)
36
- activesupport (= 4.2.1)
34
+ activerecord (4.2.3)
35
+ activemodel (= 4.2.3)
36
+ activesupport (= 4.2.3)
37
37
  arel (~> 6.0)
38
- activesupport (4.2.1)
38
+ activesupport (4.2.3)
39
39
  i18n (~> 0.7)
40
40
  json (~> 1.7, >= 1.7.7)
41
41
  minitest (~> 5.1)
42
42
  thread_safe (~> 0.3, >= 0.3.4)
43
43
  tzinfo (~> 1.1)
44
- arel (6.0.0)
44
+ arel (6.0.3)
45
45
  builder (3.2.2)
46
46
  erubis (2.7.0)
47
- globalid (0.3.5)
47
+ globalid (0.3.6)
48
48
  activesupport (>= 4.1.0)
49
49
  httpclient (2.6.0.1)
50
50
  i18n (0.7.0)
51
- json (1.8.2)
51
+ json (1.8.3)
52
52
  loofah (2.0.2)
53
53
  nokogiri (>= 1.5.9)
54
54
  mail (2.6.3)
55
55
  mime-types (>= 1.16, < 3)
56
- mime-types (2.5)
56
+ mime-types (2.6.1)
57
57
  mini_portile (0.6.2)
58
- minitest (5.6.1)
58
+ minitest (5.8.0)
59
59
  nokogiri (1.6.6.2)
60
60
  mini_portile (~> 0.6.0)
61
- rack (1.6.0)
61
+ rack (1.6.4)
62
62
  rack-test (0.6.3)
63
63
  rack (>= 1.0)
64
- rails (4.2.1)
65
- actionmailer (= 4.2.1)
66
- actionpack (= 4.2.1)
67
- actionview (= 4.2.1)
68
- activejob (= 4.2.1)
69
- activemodel (= 4.2.1)
70
- activerecord (= 4.2.1)
71
- activesupport (= 4.2.1)
64
+ rails (4.2.3)
65
+ actionmailer (= 4.2.3)
66
+ actionpack (= 4.2.3)
67
+ actionview (= 4.2.3)
68
+ activejob (= 4.2.3)
69
+ activemodel (= 4.2.3)
70
+ activerecord (= 4.2.3)
71
+ activesupport (= 4.2.3)
72
72
  bundler (>= 1.3.0, < 2.0)
73
- railties (= 4.2.1)
73
+ railties (= 4.2.3)
74
74
  sprockets-rails
75
75
  rails-deprecated_sanitizer (1.0.3)
76
76
  activesupport (>= 4.2.0.alpha)
@@ -80,15 +80,15 @@ GEM
80
80
  rails-deprecated_sanitizer (>= 1.0.1)
81
81
  rails-html-sanitizer (1.0.2)
82
82
  loofah (~> 2.0)
83
- railties (4.2.1)
84
- actionpack (= 4.2.1)
85
- activesupport (= 4.2.1)
83
+ railties (4.2.3)
84
+ actionpack (= 4.2.3)
85
+ activesupport (= 4.2.3)
86
86
  rake (>= 0.8.7)
87
87
  thor (>= 0.18.1, < 2.0)
88
88
  rake (10.4.2)
89
- sprockets (3.0.3)
89
+ sprockets (3.2.0)
90
90
  rack (~> 1.0)
91
- sprockets-rails (2.2.4)
91
+ sprockets-rails (2.3.2)
92
92
  actionpack (>= 3.0)
93
93
  activesupport (>= 3.0)
94
94
  sprockets (>= 2.8, < 4.0)
@@ -106,3 +106,6 @@ DEPENDENCIES
106
106
  jstree-rails-4!
107
107
  rails (>= 3.0)
108
108
  thor (~> 0.14)
109
+
110
+ BUNDLED WITH
111
+ 1.10.6
data/README.md CHANGED
@@ -38,6 +38,15 @@ If you want to contribute, please:
38
38
  * Make your feature addition or bug fix.
39
39
  * Send me a pull request on Github.
40
40
 
41
+ ## How to pull new version of jsTree yourself
42
+
43
+ Use command line:
44
+
45
+ * bundle install
46
+ * ruby -r './lib/jstree-rails-4/source_file.rb' -e 'SourceFile.new.fetch'
47
+ * Choose version and enter 'Y' on each request
48
+
41
49
  ## License
42
50
 
43
51
  jsTree-Rails-4 is released under the [MIT License](http://www.opensource.org/licenses/MIT).
52
+
@@ -1,33 +1,33 @@
1
- require "thor"
2
- require "json"
3
- require "httpclient"
1
+ require 'thor'
2
+ require 'json'
3
+ require 'httpclient'
4
4
 
5
5
  class SourceFile < Thor
6
6
  include Thor::Actions
7
7
 
8
- desc "fetch source files", "fetch source files from GitHub"
8
+ desc 'fetch source files', 'fetch source files from GitHub'
9
9
  def fetch
10
10
  filtered_tags = fetch_tags
11
- tag = select("Which tag do you want to fetch?", filtered_tags)
12
- self.destination_root = "vendor/assets"
13
- remote = "https://github.com/vakata/jstree"
11
+ tag = select('Which tag do you want to fetch?', filtered_tags)
12
+ self.destination_root = 'vendor/assets'
13
+ remote = 'https://github.com/vakata/jstree'
14
14
  # IMAGES
15
- get "#{remote}/raw/#{tag}/dist/themes/default/32px.png", "images/default/32px.png"
16
- get "#{remote}/raw/#{tag}/dist/themes/default/40px.png", "images/default/40px.png"
17
- get "#{remote}/raw/#{tag}/dist/themes/default/throbber.gif", "images/default/throbber.gif"
18
- get "#{remote}/raw/#{tag}/dist/themes/default-dark/32px.png", "images/default-dark/32px.png"
19
- get "#{remote}/raw/#{tag}/dist/themes/default-dark/40px.png", "images/default-dark/40px.png"
20
- get "#{remote}/raw/#{tag}/dist/themes/default-dark/throbber.gif", "images/default-dark/throbber.gif"
15
+ get "#{remote}/raw/#{tag}/dist/themes/default/32px.png", 'images/default/32px.png'
16
+ get "#{remote}/raw/#{tag}/dist/themes/default/40px.png", 'images/default/40px.png'
17
+ get "#{remote}/raw/#{tag}/dist/themes/default/throbber.gif", 'images/default/throbber.gif'
18
+ get "#{remote}/raw/#{tag}/dist/themes/default-dark/32px.png", 'images/default-dark/32px.png'
19
+ get "#{remote}/raw/#{tag}/dist/themes/default-dark/40px.png", 'images/default-dark/40px.png'
20
+ get "#{remote}/raw/#{tag}/dist/themes/default-dark/throbber.gif", 'images/default-dark/throbber.gif'
21
21
  # CSS
22
- get "#{remote}/raw/#{tag}/dist/themes/default/style.css", "stylesheets/jstree-default.scss"
23
- get "#{remote}/raw/#{tag}/dist/themes/default-dark/style.css", "stylesheets/jstree-default-dark.scss"
22
+ get "#{remote}/raw/#{tag}/dist/themes/default/style.css", 'stylesheets/jstree-default.scss'
23
+ get "#{remote}/raw/#{tag}/dist/themes/default-dark/style.css", 'stylesheets/jstree-default-dark.scss'
24
24
  # JS
25
- get "#{remote}/raw/#{tag}/dist/jstree.js", "javascripts/jstree.js"
25
+ get "#{remote}/raw/#{tag}/dist/jstree.js", 'javascripts/jstree.js'
26
26
  end
27
27
 
28
- desc "convert css to use rails paths", "make css use rails paths"
28
+ desc 'convert css to use rails paths', 'make css use rails paths'
29
29
  def convert
30
- self.destination_root = "vendor/assets"
30
+ self.destination_root = 'vendor/assets'
31
31
  inside destination_root do
32
32
  gsub_file 'stylesheets/jstree-default.scss', %r/url\((?:\"|\')([^\)]+\.(?:gif|png))(?:\"|\')\)/, 'image-url("default/\1")'
33
33
  gsub_file 'stylesheets/jstree-default-dark.scss', %r/url\((?:\"|\')([^\)]+\.(?:gif|png))(?:\"|\')\)/, 'image-url("default-dark/\1")'
@@ -39,8 +39,8 @@ class SourceFile < Thor
39
39
  def fetch_tags
40
40
  http = HTTPClient.new
41
41
  #http.ssl_config.ssl_version = :SSLv23
42
- response = JSON.parse(http.get("https://api.github.com/repos/vakata/jstree/tags").body)
43
- response.map{|tag| tag["name"]}.sort
42
+ response = JSON.parse(http.get('https://api.github.com/repos/vakata/jstree/tags').body)
43
+ response.map{|tag| tag['name']}.sort
44
44
  end
45
45
 
46
46
  def select msg, elements
@@ -1,5 +1,5 @@
1
1
  module JSTree
2
2
  module Rails
3
- VERSION = "3.1.1"
3
+ VERSION = '3.2.0'
4
4
  end
5
5
  end
@@ -1,11 +1,11 @@
1
- /*globals jQuery, define, exports, require, window, document, postMessage */
1
+ /*globals jQuery, define, module, exports, require, window, document, postMessage */
2
2
  (function (factory) {
3
3
  "use strict";
4
4
  if (typeof define === 'function' && define.amd) {
5
5
  define(['jquery'], factory);
6
6
  }
7
- else if(typeof exports === 'object') {
8
- factory(require('jquery'));
7
+ else if(typeof module !== 'undefined' && module.exports) {
8
+ module.exports = factory(require('jquery'));
9
9
  }
10
10
  else {
11
11
  factory(jQuery);
@@ -13,7 +13,7 @@
13
13
  }(function ($, undefined) {
14
14
  "use strict";
15
15
  /*!
16
- * jsTree 3.1.1
16
+ * jsTree 3.2.0
17
17
  * http://jstree.com/
18
18
  *
19
19
  * Copyright (c) 2014 Ivan Bozhanov (http://vakata.com)
@@ -28,7 +28,6 @@
28
28
 
29
29
  // prevent another load? maybe there is a better way?
30
30
  if($.jstree) {
31
- return;
32
31
  }
33
32
 
34
33
  /**
@@ -71,7 +70,7 @@
71
70
  * specifies the jstree version in use
72
71
  * @name $.jstree.version
73
72
  */
74
- version : '3.1.1',
73
+ version : '3.2.0',
75
74
  /**
76
75
  * holds all the default options used when creating new instances
77
76
  * @name $.jstree.defaults
@@ -89,7 +88,8 @@
89
88
  */
90
89
  plugins : {},
91
90
  path : src && src.indexOf('/') !== -1 ? src.replace(/\/[^\/]+$/,'') : '',
92
- idregex : /[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g
91
+ idregex : /[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g,
92
+ root : '#'
93
93
  };
94
94
  /**
95
95
  * creates a jstree instance
@@ -471,16 +471,7 @@
471
471
  */
472
472
  init : function (el, options) {
473
473
  this._model = {
474
- data : {
475
- '#' : {
476
- id : '#',
477
- parent : null,
478
- parents : [],
479
- children : [],
480
- children_d : [],
481
- state : { loaded : false }
482
- }
483
- },
474
+ data : {},
484
475
  changed : [],
485
476
  force_full_redraw : false,
486
477
  redraw_timeout : false,
@@ -491,6 +482,14 @@
491
482
  disabled : false
492
483
  }
493
484
  };
485
+ this._model.data[$.jstree.root] = {
486
+ id : $.jstree.root,
487
+ parent : null,
488
+ parents : [],
489
+ children : [],
490
+ children_d : [],
491
+ state : { loaded : false }
492
+ };
494
493
 
495
494
  this.element = $(el).addClass('jstree jstree-' + this._id);
496
495
  this.settings = options;
@@ -531,7 +530,7 @@
531
530
  * @name loading.jstree
532
531
  */
533
532
  this.trigger("loading");
534
- this.load_node('#');
533
+ this.load_node($.jstree.root);
535
534
  },
536
535
  /**
537
536
  * destroy an instance
@@ -574,7 +573,8 @@
574
573
  tout = null,
575
574
  was_click = 0;
576
575
  this.element
577
- .on("dblclick.jstree", function () {
576
+ .on("dblclick.jstree", function (e) {
577
+ if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
578
578
  if(document.selection && document.selection.empty) {
579
579
  document.selection.empty();
580
580
  }
@@ -601,6 +601,7 @@
601
601
  this.toggle_node(e.target);
602
602
  }, this))
603
603
  .on("dblclick.jstree", ".jstree-anchor", $.proxy(function (e) {
604
+ if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
604
605
  if(this.settings.core.dblclick_toggle) {
605
606
  this.toggle_node(e.target);
606
607
  }
@@ -611,7 +612,7 @@
611
612
  this.activate_node(e.currentTarget, e);
612
613
  }, this))
613
614
  .on('keydown.jstree', '.jstree-anchor', $.proxy(function (e) {
614
- if(e.target.tagName === "INPUT") { return true; }
615
+ if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
615
616
  if(e.which !== 32 && e.which !== 13 && (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey)) { return true; }
616
617
  var o = null;
617
618
  if(this._data.core.rtl) {
@@ -636,7 +637,7 @@
636
637
  }
637
638
  else {
638
639
  o = this.get_parent(e.currentTarget);
639
- if(o && o.id !== '#') { this.get_node(o, true).children('.jstree-anchor').focus(); }
640
+ if(o && o.id !== $.jstree.root) { this.get_node(o, true).children('.jstree-anchor').focus(); }
640
641
  }
641
642
  break;
642
643
  case 38: // up
@@ -676,7 +677,7 @@
676
677
  case 46:
677
678
  e.preventDefault();
678
679
  o = this.get_node(e.currentTarget);
679
- if(o && o.id && o.id !== '#') {
680
+ if(o && o.id && o.id !== $.jstree.root) {
680
681
  o = this.is_selected(o) ? this.get_selected() : o;
681
682
  this.delete_node(o);
682
683
  }
@@ -685,7 +686,7 @@
685
686
  case 113:
686
687
  e.preventDefault();
687
688
  o = this.get_node(e.currentTarget);
688
- if(o && o.id && o.id !== '#') {
689
+ if(o && o.id && o.id !== $.jstree.root) {
689
690
  // this.edit(o);
690
691
  }
691
692
  break;
@@ -697,7 +698,7 @@
697
698
  }, this))
698
699
  .on("load_node.jstree", $.proxy(function (e, data) {
699
700
  if(data.status) {
700
- if(data.node.id === '#' && !this._data.core.loaded) {
701
+ if(data.node.id === $.jstree.root && !this._data.core.loaded) {
701
702
  this._data.core.loaded = true;
702
703
  if(this._firstChild(this.get_container_ul()[0])) {
703
704
  this.element.attr('aria-activedescendant',this._firstChild(this.get_container_ul()[0]).id);
@@ -739,7 +740,7 @@
739
740
  }, this))
740
741
  // quick searching when the tree is focused
741
742
  .on('keypress.jstree', $.proxy(function (e) {
742
- if(e.target.tagName === "INPUT") { return true; }
743
+ if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
743
744
  if(tout) { clearTimeout(tout); }
744
745
  tout = setTimeout(function () {
745
746
  word = '';
@@ -773,7 +774,7 @@
773
774
  if(end) { return; }
774
775
  }
775
776
  // list nodes that start with that letter (only if word consists of a single char)
776
- if(new RegExp('^' + chr + '+$').test(word)) {
777
+ if(new RegExp('^' + chr.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '+$').test(word)) {
777
778
  // search for the next node starting with that letter
778
779
  col.slice(ind + 1).each($.proxy(function (i, v) {
779
780
  if($(v).text().toLowerCase().charAt(0) === chr) {
@@ -960,14 +961,14 @@
960
961
  obj = this._model.data[dom.closest('.jstree-node').attr('id')];
961
962
  }
962
963
  else if((dom = $(obj, this.element)).length && dom.hasClass('jstree')) {
963
- obj = this._model.data['#'];
964
+ obj = this._model.data[$.jstree.root];
964
965
  }
965
966
  else {
966
967
  return false;
967
968
  }
968
969
 
969
970
  if(as_dom) {
970
- obj = obj.id === '#' ? this.element : $('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element);
971
+ obj = obj.id === $.jstree.root ? this.element : $('#' + obj.id.replace($.jstree.idregex,'\\$&'), this.element);
971
972
  }
972
973
  return obj;
973
974
  } catch (ex) { return false; }
@@ -982,7 +983,7 @@
982
983
  */
983
984
  get_path : function (obj, glue, ids) {
984
985
  obj = obj.parents ? obj : this.get_node(obj);
985
- if(!obj || obj.id === '#' || !obj.parents) {
986
+ if(!obj || obj.id === $.jstree.root || !obj.parents) {
986
987
  return false;
987
988
  }
988
989
  var i, j, p = [];
@@ -1087,7 +1088,7 @@
1087
1088
  */
1088
1089
  get_parent : function (obj) {
1089
1090
  obj = this.get_node(obj);
1090
- if(!obj || obj.id === '#') {
1091
+ if(!obj || obj.id === $.jstree.root) {
1091
1092
  return false;
1092
1093
  }
1093
1094
  return obj.parent;
@@ -1213,8 +1214,14 @@
1213
1214
  obj.state.loading = false;
1214
1215
  obj.state.loaded = status;
1215
1216
  obj.state.failed = !obj.state.loaded;
1216
- var dom = this.get_node(obj, true);
1217
- if(obj.state.loaded && !obj.children.length && dom && dom.length && !dom.hasClass('jstree-leaf')) {
1217
+ var dom = this.get_node(obj, true), i = 0, j = 0, m = this._model.data, has_children = false;
1218
+ for(i = 0, j = obj.children.length; i < j; i++) {
1219
+ if(m[obj.children[i]] && !m[obj.children[i]].state.hidden) {
1220
+ has_children = true;
1221
+ break;
1222
+ }
1223
+ }
1224
+ if(obj.state.loaded && !has_children && dom && dom.length && !dom.hasClass('jstree-leaf')) {
1218
1225
  dom.removeClass('jstree-closed jstree-open').addClass('jstree-leaf');
1219
1226
  }
1220
1227
  dom.removeClass("jstree-loading").attr('aria-busy',false);
@@ -1271,7 +1278,7 @@
1271
1278
  * @trigger load_all.jstree
1272
1279
  */
1273
1280
  load_all : function (obj, callback) {
1274
- if(!obj) { obj = '#'; }
1281
+ if(!obj) { obj = $.jstree.root; }
1275
1282
  obj = this.get_node(obj);
1276
1283
  if(!obj) { return false; }
1277
1284
  var to_load = [],
@@ -1314,7 +1321,7 @@
1314
1321
  var s = this.settings.core.data, t;
1315
1322
  // use original HTML
1316
1323
  if(!s) {
1317
- if(obj.id === '#') {
1324
+ if(obj.id === $.jstree.root) {
1318
1325
  return this._append_html_data(obj, this._data.core.original_container_html.clone(true), function (status) {
1319
1326
  callback.call(this, status);
1320
1327
  });
@@ -1322,7 +1329,7 @@
1322
1329
  else {
1323
1330
  return callback.call(this, false);
1324
1331
  }
1325
- // return callback.call(this, obj.id === '#' ? this._append_html_data(obj, this._data.core.original_container_html.clone(true)) : false);
1332
+ // return callback.call(this, obj.id === $.jstree.root ? this._append_html_data(obj, this._data.core.original_container_html.clone(true)) : false);
1326
1333
  }
1327
1334
  if($.isFunction(s)) {
1328
1335
  return s.call(this, obj, $.proxy(function (d) {
@@ -1366,7 +1373,7 @@
1366
1373
  }, this));
1367
1374
  }
1368
1375
  t = ($.isArray(s) || $.isPlainObject(s)) ? JSON.parse(JSON.stringify(s)) : s;
1369
- if(obj.id === '#') {
1376
+ if(obj.id === $.jstree.root) {
1370
1377
  return this._append_json_data(obj, t, function (status) {
1371
1378
  callback.call(this, status);
1372
1379
  });
@@ -1376,10 +1383,10 @@
1376
1383
  this.settings.core.error.call(this, this._data.core.last_error);
1377
1384
  return callback.call(this, false);
1378
1385
  }
1379
- //return callback.call(this, (obj.id === "#" ? this._append_json_data(obj, t) : false) );
1386
+ //return callback.call(this, (obj.id === $.jstree.root ? this._append_json_data(obj, t) : false) );
1380
1387
  }
1381
1388
  if(typeof s === 'string') {
1382
- if(obj.id === '#') {
1389
+ if(obj.id === $.jstree.root) {
1383
1390
  return this._append_html_data(obj, $($.parseHTML(s)).filter(function () { return this.nodeType !== 3; }), function (status) {
1384
1391
  callback.call(this, status);
1385
1392
  });
@@ -1389,7 +1396,7 @@
1389
1396
  this.settings.core.error.call(this, this._data.core.last_error);
1390
1397
  return callback.call(this, false);
1391
1398
  }
1392
- //return callback.call(this, (obj.id === "#" ? this._append_html_data(obj, $(s)) : false) );
1399
+ //return callback.call(this, (obj.id === $.jstree.root ? this._append_html_data(obj, $(s)) : false) );
1393
1400
  }
1394
1401
  return callback.call(this, false);
1395
1402
  },
@@ -1448,7 +1455,7 @@
1448
1455
  * @param {String} parent the parent ID of the nodes
1449
1456
  */
1450
1457
  this.trigger('model', { "nodes" : dpc, 'parent' : par });
1451
- if(par !== '#') {
1458
+ if(par !== $.jstree.root) {
1452
1459
  this._node_changed(par);
1453
1460
  this.redraw();
1454
1461
  }
@@ -1793,7 +1800,7 @@
1793
1800
 
1794
1801
  this.trigger('model', { "nodes" : rslt.dpc, 'parent' : rslt.par });
1795
1802
 
1796
- if(rslt.par !== '#') {
1803
+ if(rslt.par !== $.jstree.root) {
1797
1804
  this._node_changed(rslt.par);
1798
1805
  this.redraw();
1799
1806
  }
@@ -2186,7 +2193,7 @@
2186
2193
  * @trigger redraw.jstree
2187
2194
  */
2188
2195
  _redraw : function () {
2189
- var nodes = this._model.force_full_redraw ? this._model.data['#'].children.concat([]) : this._model.changed.concat([]),
2196
+ var nodes = this._model.force_full_redraw ? this._model.data[$.jstree.root].children.concat([]) : this._model.changed.concat([]),
2190
2197
  f = document.createElement('UL'), tmp, i, j, fe = this._data.core.focused;
2191
2198
  for(i = 0, j = nodes.length; i < j; i++) {
2192
2199
  tmp = this.redraw_node(nodes[i], true, this._model.force_full_redraw);
@@ -2247,7 +2254,7 @@
2247
2254
  k = false,
2248
2255
  d = document;
2249
2256
  if(!obj) { return false; }
2250
- if(obj.id === '#') { return this.redraw(true); }
2257
+ if(obj.id === $.jstree.root) { return this.redraw(true); }
2251
2258
  node = this.get_node(node, true);
2252
2259
  if(!node || !node.length) { return false; } // TODO: quick toggle
2253
2260
 
@@ -2287,20 +2294,22 @@
2287
2294
  s = false,
2288
2295
  tmp = null,
2289
2296
  t = 0,
2290
- l = 0;
2297
+ l = 0,
2298
+ has_children = false,
2299
+ last_sibling = false;
2291
2300
  if(!obj) { return false; }
2292
- if(obj.id === '#') { return this.redraw(true); }
2301
+ if(obj.id === $.jstree.root) { return this.redraw(true); }
2293
2302
  deep = deep || obj.children.length === 0;
2294
2303
  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);
2295
2304
  if(!node) {
2296
2305
  deep = true;
2297
2306
  //node = d.createElement('LI');
2298
2307
  if(!is_callback) {
2299
- par = obj.parent !== '#' ? $('#' + obj.parent.replace($.jstree.idregex,'\\$&'), this.element)[0] : null;
2308
+ par = obj.parent !== $.jstree.root ? $('#' + obj.parent.replace($.jstree.idregex,'\\$&'), this.element)[0] : null;
2300
2309
  if(par !== null && (!par || !m[obj.parent].state.opened)) {
2301
2310
  return false;
2302
2311
  }
2303
- ind = $.inArray(obj.id, par === null ? m['#'].children : m[obj.parent].children);
2312
+ ind = $.inArray(obj.id, par === null ? m[$.jstree.root].children : m[obj.parent].children);
2304
2313
  }
2305
2314
  }
2306
2315
  else {
@@ -2349,14 +2358,39 @@
2349
2358
  node.setAttribute('aria-disabled', true);
2350
2359
  }
2351
2360
 
2352
- if(obj.state.loaded && !obj.children.length) {
2361
+ for(i = 0, j = obj.children.length; i < j; i++) {
2362
+ if(!m[obj.children[i]].state.hidden) {
2363
+ has_children = true;
2364
+ break;
2365
+ }
2366
+ }
2367
+ if(obj.parent !== null && m[obj.parent] && !obj.state.hidden) {
2368
+ i = $.inArray(obj.id, m[obj.parent].children);
2369
+ last_sibling = obj.id;
2370
+ if(i !== -1) {
2371
+ i++;
2372
+ for(j = m[obj.parent].children.length; i < j; i++) {
2373
+ if(!m[m[obj.parent].children[i]].state.hidden) {
2374
+ last_sibling = m[obj.parent].children[i];
2375
+ }
2376
+ if(last_sibling !== obj.id) {
2377
+ break;
2378
+ }
2379
+ }
2380
+ }
2381
+ }
2382
+
2383
+ if(obj.state.hidden) {
2384
+ c += ' jstree-hidden';
2385
+ }
2386
+ if(obj.state.loaded && !has_children) {
2353
2387
  c += ' jstree-leaf';
2354
2388
  }
2355
2389
  else {
2356
2390
  c += obj.state.opened && obj.state.loaded ? ' jstree-open' : ' jstree-closed';
2357
2391
  node.setAttribute('aria-expanded', (obj.state.opened && obj.state.loaded) );
2358
2392
  }
2359
- if(obj.parent !== null && m[obj.parent].children[m[obj.parent].children.length - 1] === obj.id) {
2393
+ if(last_sibling === obj.id) {
2360
2394
  c += ' jstree-last';
2361
2395
  }
2362
2396
  node.id = obj.id;
@@ -2470,7 +2504,7 @@
2470
2504
  return true;
2471
2505
  }
2472
2506
  obj = this.get_node(obj);
2473
- if(!obj || obj.id === '#') {
2507
+ if(!obj || obj.id === $.jstree.root) {
2474
2508
  return false;
2475
2509
  }
2476
2510
  animation = animation === undefined ? this.settings.core.animation : animation;
@@ -2557,12 +2591,12 @@
2557
2591
  */
2558
2592
  _open_to : function (obj) {
2559
2593
  obj = this.get_node(obj);
2560
- if(!obj || obj.id === '#') {
2594
+ if(!obj || obj.id === $.jstree.root) {
2561
2595
  return false;
2562
2596
  }
2563
2597
  var i, j, p = obj.parents;
2564
2598
  for(i = 0, j = p.length; i < j; i+=1) {
2565
- if(i !== '#') {
2599
+ if(i !== $.jstree.root) {
2566
2600
  this.open_node(p[i], false, 0);
2567
2601
  }
2568
2602
  }
@@ -2585,7 +2619,7 @@
2585
2619
  return true;
2586
2620
  }
2587
2621
  obj = this.get_node(obj);
2588
- if(!obj || obj.id === '#') {
2622
+ if(!obj || obj.id === $.jstree.root) {
2589
2623
  return false;
2590
2624
  }
2591
2625
  if(this.is_closed(obj)) {
@@ -2658,10 +2692,10 @@
2658
2692
  * @trigger open_all.jstree
2659
2693
  */
2660
2694
  open_all : function (obj, animation, original_obj) {
2661
- if(!obj) { obj = '#'; }
2695
+ if(!obj) { obj = $.jstree.root; }
2662
2696
  obj = this.get_node(obj);
2663
2697
  if(!obj) { return false; }
2664
- var dom = obj.id === '#' ? this.get_container_ul() : this.get_node(obj, true), i, j, _this;
2698
+ var dom = obj.id === $.jstree.root ? this.get_container_ul() : this.get_node(obj, true), i, j, _this;
2665
2699
  if(!dom.length) {
2666
2700
  for(i = 0, j = obj.children_d.length; i < j; i++) {
2667
2701
  if(this.is_closed(this._model.data[obj.children_d[i]])) {
@@ -2698,19 +2732,18 @@
2698
2732
  * @trigger close_all.jstree
2699
2733
  */
2700
2734
  close_all : function (obj, animation) {
2701
- if(!obj) { obj = '#'; }
2735
+ if(!obj) { obj = $.jstree.root; }
2702
2736
  obj = this.get_node(obj);
2703
2737
  if(!obj) { return false; }
2704
- var dom = obj.id === '#' ? this.get_container_ul() : this.get_node(obj, true),
2738
+ var dom = obj.id === $.jstree.root ? this.get_container_ul() : this.get_node(obj, true),
2705
2739
  _this = this, i, j;
2706
- if(!dom.length) {
2707
- for(i = 0, j = obj.children_d.length; i < j; i++) {
2708
- this._model.data[obj.children_d[i]].state.opened = false;
2709
- }
2710
- return this.trigger('close_all', { "node" : obj });
2740
+ if(dom.length) {
2741
+ dom = this.is_open(obj) ? dom.find('.jstree-open').addBack() : dom.find('.jstree-open');
2742
+ $(dom.get().reverse()).each(function () { _this.close_node(this, animation || 0); });
2743
+ }
2744
+ for(i = 0, j = obj.children_d.length; i < j; i++) {
2745
+ this._model.data[obj.children_d[i]].state.opened = false;
2711
2746
  }
2712
- dom = this.is_open(obj) ? dom.find('.jstree-open').addBack() : dom.find('.jstree-open');
2713
- $(dom.get().reverse()).each(function () { _this.close_node(this, animation || 0); });
2714
2747
  /**
2715
2748
  * triggered when an `close_all` call completes
2716
2749
  * @event
@@ -2745,7 +2778,7 @@
2745
2778
  return true;
2746
2779
  }
2747
2780
  obj = this.get_node(obj);
2748
- if(!obj || obj.id === '#') {
2781
+ if(!obj || obj.id === $.jstree.root) {
2749
2782
  return false;
2750
2783
  }
2751
2784
  obj.state.disabled = false;
@@ -2774,7 +2807,7 @@
2774
2807
  return true;
2775
2808
  }
2776
2809
  obj = this.get_node(obj);
2777
- if(!obj || obj.id === '#') {
2810
+ if(!obj || obj.id === $.jstree.root) {
2778
2811
  return false;
2779
2812
  }
2780
2813
  obj.state.disabled = true;
@@ -2787,6 +2820,126 @@
2787
2820
  */
2788
2821
  this.trigger('disable_node', { 'node' : obj });
2789
2822
  },
2823
+ /**
2824
+ * hides a node - it is still in the structure but will not be visible
2825
+ * @name hide_node(obj)
2826
+ * @param {mixed} obj the node to hide
2827
+ * @param {Boolean} redraw internal parameter controlling if redraw is called
2828
+ * @trigger hide_node.jstree
2829
+ */
2830
+ hide_node : function (obj, skip_redraw) {
2831
+ var t1, t2;
2832
+ if($.isArray(obj)) {
2833
+ obj = obj.slice();
2834
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
2835
+ this.hide_node(obj[t1], true);
2836
+ }
2837
+ this.redraw();
2838
+ return true;
2839
+ }
2840
+ obj = this.get_node(obj);
2841
+ if(!obj || obj.id === $.jstree.root) {
2842
+ return false;
2843
+ }
2844
+ if(!obj.state.hidden) {
2845
+ obj.state.hidden = true;
2846
+ this._node_changed(obj.parent);
2847
+ if(!skip_redraw) {
2848
+ this.redraw();
2849
+ }
2850
+ /**
2851
+ * triggered when an node is hidden
2852
+ * @event
2853
+ * @name hide_node.jstree
2854
+ * @param {Object} node the hidden node
2855
+ */
2856
+ this.trigger('hide_node', { 'node' : obj });
2857
+ }
2858
+ },
2859
+ /**
2860
+ * shows a node
2861
+ * @name show_node(obj)
2862
+ * @param {mixed} obj the node to show
2863
+ * @param {Boolean} skip_redraw internal parameter controlling if redraw is called
2864
+ * @trigger show_node.jstree
2865
+ */
2866
+ show_node : function (obj, skip_redraw) {
2867
+ var t1, t2;
2868
+ if($.isArray(obj)) {
2869
+ obj = obj.slice();
2870
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
2871
+ this.show_node(obj[t1], true);
2872
+ }
2873
+ this.redraw();
2874
+ return true;
2875
+ }
2876
+ obj = this.get_node(obj);
2877
+ if(!obj || obj.id === $.jstree.root) {
2878
+ return false;
2879
+ }
2880
+ if(obj.state.hidden) {
2881
+ obj.state.hidden = false;
2882
+ this._node_changed(obj.parent);
2883
+ if(!skip_redraw) {
2884
+ this.redraw();
2885
+ }
2886
+ /**
2887
+ * triggered when an node is shown
2888
+ * @event
2889
+ * @name show_node.jstree
2890
+ * @param {Object} node the shown node
2891
+ */
2892
+ this.trigger('show_node', { 'node' : obj });
2893
+ }
2894
+ },
2895
+ /**
2896
+ * hides all nodes
2897
+ * @name hide_all()
2898
+ * @trigger hide_all.jstree
2899
+ */
2900
+ hide_all : function (obj) {
2901
+ var i, m = this._model.data, ids = [];
2902
+ for(i in m) {
2903
+ if(m.hasOwnProperty(i) && i !== $.jstree.root && !m[i].state.hidden) {
2904
+ m[i].state.hidden = true;
2905
+ ids.push(i);
2906
+ }
2907
+ }
2908
+ this._model.force_full_redraw = true;
2909
+ this.redraw();
2910
+ /**
2911
+ * triggered when all nodes are hidden
2912
+ * @event
2913
+ * @name hide_all.jstree
2914
+ * @param {Array} nodes the IDs of all hidden nodes
2915
+ */
2916
+ this.trigger('hide_all', { 'nodes' : ids });
2917
+ return ids;
2918
+ },
2919
+ /**
2920
+ * shows all nodes
2921
+ * @name show_all()
2922
+ * @trigger show_all.jstree
2923
+ */
2924
+ show_all : function (obj) {
2925
+ var i, m = this._model.data, ids = [];
2926
+ for(i in m) {
2927
+ if(m.hasOwnProperty(i) && i !== $.jstree.root && m[i].state.hidden) {
2928
+ m[i].state.hidden = false;
2929
+ ids.push(i);
2930
+ }
2931
+ }
2932
+ this._model.force_full_redraw = true;
2933
+ this.redraw();
2934
+ /**
2935
+ * triggered when all nodes are shown
2936
+ * @event
2937
+ * @name show_all.jstree
2938
+ * @param {Array} nodes the IDs of all shown nodes
2939
+ */
2940
+ this.trigger('show_all', { 'nodes' : ids });
2941
+ return ids;
2942
+ },
2790
2943
  /**
2791
2944
  * called when a node is selected by the user. Used internally.
2792
2945
  * @private
@@ -2799,6 +2952,9 @@
2799
2952
  if(this.is_disabled(obj)) {
2800
2953
  return false;
2801
2954
  }
2955
+ if(!e || typeof e !== 'object') {
2956
+ e = {};
2957
+ }
2802
2958
 
2803
2959
  // 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
2804
2960
  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;
@@ -2853,8 +3009,9 @@
2853
3009
  * @event
2854
3010
  * @name activate_node.jstree
2855
3011
  * @param {Object} node
3012
+ * @param {Object} event the ooriginal event (if any) which triggered the call (may be an empty object)
2856
3013
  */
2857
- this.trigger('activate_node', { 'node' : this.get_node(obj) });
3014
+ this.trigger('activate_node', { 'node' : this.get_node(obj), 'event' : e });
2858
3015
  },
2859
3016
  /**
2860
3017
  * applies the hover state on a node, called when a node is hovered by the user. Used internally.
@@ -2920,7 +3077,7 @@
2920
3077
  return true;
2921
3078
  }
2922
3079
  obj = this.get_node(obj);
2923
- if(!obj || obj.id === '#') {
3080
+ if(!obj || obj.id === $.jstree.root) {
2924
3081
  return false;
2925
3082
  }
2926
3083
  dom = this.get_node(obj, true);
@@ -2973,7 +3130,7 @@
2973
3130
  return true;
2974
3131
  }
2975
3132
  obj = this.get_node(obj);
2976
- if(!obj || obj.id === '#') {
3133
+ if(!obj || obj.id === $.jstree.root) {
2977
3134
  return false;
2978
3135
  }
2979
3136
  dom = this.get_node(obj, true);
@@ -3005,7 +3162,7 @@
3005
3162
  */
3006
3163
  select_all : function (supress_event) {
3007
3164
  var tmp = this._data.core.selected.concat([]), i, j;
3008
- this._data.core.selected = this._model.data['#'].children_d.concat();
3165
+ this._data.core.selected = this._model.data[$.jstree.root].children_d.concat();
3009
3166
  for(i = 0, j = this._data.core.selected.length; i < j; i++) {
3010
3167
  if(this._model.data[this._data.core.selected[i]]) {
3011
3168
  this._model.data[this._data.core.selected[i]].state.selected = true;
@@ -3058,7 +3215,7 @@
3058
3215
  */
3059
3216
  is_selected : function (obj) {
3060
3217
  obj = this.get_node(obj);
3061
- if(!obj || obj.id === '#') {
3218
+ if(!obj || obj.id === $.jstree.root) {
3062
3219
  return false;
3063
3220
  }
3064
3221
  return obj.state.selected;
@@ -3141,7 +3298,7 @@
3141
3298
  }, i;
3142
3299
  for(i in this._model.data) {
3143
3300
  if(this._model.data.hasOwnProperty(i)) {
3144
- if(i !== '#') {
3301
+ if(i !== $.jstree.root) {
3145
3302
  if(this._model.data[i].state.opened) {
3146
3303
  state.core.open.push(i);
3147
3304
  }
@@ -3157,7 +3314,7 @@
3157
3314
  * sets the state of the tree. Used internally.
3158
3315
  * @name set_state(state [, callback])
3159
3316
  * @private
3160
- * @param {Object} state the state to restore
3317
+ * @param {Object} state the state to restore. Keep in mind this object is passed by reference and jstree will modify it.
3161
3318
  * @param {Function} callback an optional function to execute once the state is restored.
3162
3319
  * @trigger set_state.jstree
3163
3320
  */
@@ -3237,22 +3394,25 @@
3237
3394
  this._data.core.state = forget_state === true ? {} : this.get_state();
3238
3395
  if(forget_state && $.isFunction(forget_state)) { this._data.core.state = forget_state.call(this, this._data.core.state); }
3239
3396
  this._cnt = 0;
3240
- this._model.data = {
3241
- '#' : {
3242
- id : '#',
3243
- parent : null,
3244
- parents : [],
3245
- children : [],
3246
- children_d : [],
3247
- state : { loaded : false }
3248
- }
3397
+ this._model.data = {};
3398
+ this._model.data[$.jstree.root] = {
3399
+ id : $.jstree.root,
3400
+ parent : null,
3401
+ parents : [],
3402
+ children : [],
3403
+ children_d : [],
3404
+ state : { loaded : false }
3249
3405
  };
3406
+ this._data.core.selected = [];
3407
+ this._data.core.last_clicked = null;
3408
+ this._data.core.focused = null;
3409
+
3250
3410
  var c = this.get_container_ul()[0].className;
3251
3411
  if(!skip_loading) {
3252
3412
  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>");
3253
3413
  this.element.attr('aria-activedescendant','j'+this._id+'_loading');
3254
3414
  }
3255
- this.load_node('#', function (o, s) {
3415
+ this.load_node($.jstree.root, function (o, s) {
3256
3416
  if(s) {
3257
3417
  this.get_container_ul()[0].className = c;
3258
3418
  if(this._firstChild(this.get_container_ul()[0])) {
@@ -3278,7 +3438,7 @@
3278
3438
  */
3279
3439
  refresh_node : function (obj) {
3280
3440
  obj = this.get_node(obj);
3281
- if(!obj || obj.id === '#') { return false; }
3441
+ if(!obj || obj.id === $.jstree.root) { return false; }
3282
3442
  var opened = [], to_load = [], s = this._data.core.selected.concat([]);
3283
3443
  to_load.push(obj.id);
3284
3444
  if(obj.state.opened === true) { opened.push(obj.id); }
@@ -3305,7 +3465,7 @@
3305
3465
  */
3306
3466
  set_id : function (obj, id) {
3307
3467
  obj = this.get_node(obj);
3308
- if(!obj || obj.id === '#') { return false; }
3468
+ if(!obj || obj.id === $.jstree.root) { return false; }
3309
3469
  var i, j, m = this._model.data;
3310
3470
  id = id.toString();
3311
3471
  // update parents (replace current ID with new one in children and children_d)
@@ -3344,7 +3504,7 @@
3344
3504
  */
3345
3505
  get_text : function (obj) {
3346
3506
  obj = this.get_node(obj);
3347
- return (!obj || obj.id === '#') ? false : obj.text;
3507
+ return (!obj || obj.id === $.jstree.root) ? false : obj.text;
3348
3508
  },
3349
3509
  /**
3350
3510
  * set the text value of a node. Used internally, please use `rename_node(obj, val)`.
@@ -3365,7 +3525,7 @@
3365
3525
  return true;
3366
3526
  }
3367
3527
  obj = this.get_node(obj);
3368
- if(!obj || obj.id === '#') { return false; }
3528
+ if(!obj || obj.id === $.jstree.root) { return false; }
3369
3529
  obj.text = val;
3370
3530
  if(this.get_node(obj, true).length) {
3371
3531
  this.redraw_node(obj.id);
@@ -3393,7 +3553,7 @@
3393
3553
  * @return {Object}
3394
3554
  */
3395
3555
  get_json : function (obj, options, flat) {
3396
- obj = this.get_node(obj || '#');
3556
+ obj = this.get_node(obj || $.jstree.root);
3397
3557
  if(!obj) { return false; }
3398
3558
  if(options && options.flat && !flat) { flat = []; }
3399
3559
  var tmp = {
@@ -3428,7 +3588,7 @@
3428
3588
  delete tmp.a_attr.id;
3429
3589
  }
3430
3590
  }
3431
- if(options && options.flat && obj.id !== '#') {
3591
+ if(options && options.flat && obj.id !== $.jstree.root) {
3432
3592
  flat.push(tmp);
3433
3593
  }
3434
3594
  if(!options || !options.no_children) {
@@ -3441,7 +3601,7 @@
3441
3601
  }
3442
3602
  }
3443
3603
  }
3444
- return options && options.flat ? flat : (obj.id === '#' ? tmp.children : tmp);
3604
+ return options && options.flat ? flat : (obj.id === $.jstree.root ? tmp.children : tmp);
3445
3605
  },
3446
3606
  /**
3447
3607
  * create a new node (do not confuse with load_node)
@@ -3455,7 +3615,7 @@
3455
3615
  * @trigger model.jstree, create_node.jstree
3456
3616
  */
3457
3617
  create_node : function (par, node, pos, callback, is_loaded) {
3458
- if(par === null) { par = "#"; }
3618
+ if(par === null) { par = $.jstree.root; }
3459
3619
  par = this.get_node(par);
3460
3620
  if(!par) { return false; }
3461
3621
  pos = pos === undefined ? "last" : pos;
@@ -3467,7 +3627,7 @@
3467
3627
  if(node.text === undefined) { node.text = this.get_string('New node'); }
3468
3628
  var tmp, dpc, i, j;
3469
3629
 
3470
- if(par.id === '#') {
3630
+ if(par.id === $.jstree.root) {
3471
3631
  if(pos === "before") { pos = "first"; }
3472
3632
  if(pos === "after") { pos = "last"; }
3473
3633
  }
@@ -3551,7 +3711,7 @@
3551
3711
  return true;
3552
3712
  }
3553
3713
  obj = this.get_node(obj);
3554
- if(!obj || obj.id === '#') { return false; }
3714
+ if(!obj || obj.id === $.jstree.root) { return false; }
3555
3715
  old = obj.text;
3556
3716
  if(!this.check("rename_node", obj, this.get_parent(obj), val)) {
3557
3717
  this.settings.core.error.call(this, this._data.core.last_error);
@@ -3577,7 +3737,7 @@
3577
3737
  * @trigger delete_node.jstree, changed.jstree
3578
3738
  */
3579
3739
  delete_node : function (obj) {
3580
- var t1, t2, par, pos, tmp, i, j, k, l, c;
3740
+ var t1, t2, par, pos, tmp, i, j, k, l, c, top, lft;
3581
3741
  if($.isArray(obj)) {
3582
3742
  obj = obj.slice();
3583
3743
  for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
@@ -3586,7 +3746,7 @@
3586
3746
  return true;
3587
3747
  }
3588
3748
  obj = this.get_node(obj);
3589
- if(!obj || obj.id === '#') { return false; }
3749
+ if(!obj || obj.id === $.jstree.root) { return false; }
3590
3750
  par = this.get_node(obj.parent);
3591
3751
  pos = $.inArray(obj.id, par.children);
3592
3752
  c = false;
@@ -3628,6 +3788,19 @@
3628
3788
  for(k = 0, l = tmp.length; k < l; k++) {
3629
3789
  delete this._model.data[tmp[k]];
3630
3790
  }
3791
+ if($.inArray(this._data.core.focused, tmp) !== -1) {
3792
+ this._data.core.focused = null;
3793
+ top = this.element[0].scrollTop;
3794
+ lft = this.element[0].scrollLeft;
3795
+ if(par.id === $.jstree.root) {
3796
+ this.get_node(this._model.data[$.jstree.root].children[0], true).children('.jstree-anchor').focus();
3797
+ }
3798
+ else {
3799
+ this.get_node(par, true).children('.jstree-anchor').focus();
3800
+ }
3801
+ this.element[0].scrollTop = top;
3802
+ this.element[0].scrollLeft = lft;
3803
+ }
3631
3804
  this.redraw_node(par, true);
3632
3805
  return true;
3633
3806
  },
@@ -3714,10 +3887,10 @@
3714
3887
  }
3715
3888
  obj = obj && obj.id ? obj : this.get_node(obj);
3716
3889
 
3717
- if(!obj || obj.id === '#') { return false; }
3890
+ if(!obj || obj.id === $.jstree.root) { return false; }
3718
3891
 
3719
- old_par = (obj.parent || '#').toString();
3720
- new_par = (!pos.toString().match(/^(before|after)$/) || par.id === '#') ? par : this.get_node(par.parent);
3892
+ old_par = (obj.parent || $.jstree.root).toString();
3893
+ new_par = (!pos.toString().match(/^(before|after)$/) || par.id === $.jstree.root) ? par : this.get_node(par.parent);
3721
3894
  old_ins = origin ? origin : (this._model.data[obj.id] ? this : $.jstree.reference(obj.id));
3722
3895
  is_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id);
3723
3896
  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;
@@ -3733,7 +3906,7 @@
3733
3906
  return false;
3734
3907
  }
3735
3908
  //var m = this._model.data;
3736
- if(par.id === '#') {
3909
+ if(par.id === $.jstree.root) {
3737
3910
  if(pos === "before") { pos = "first"; }
3738
3911
  if(pos === "after") { pos = "last"; }
3739
3912
  }
@@ -3774,7 +3947,7 @@
3774
3947
  tmp[pos] = obj.id;
3775
3948
  new_par.children = tmp;
3776
3949
  this._node_changed(new_par.id);
3777
- this.redraw(new_par.id === '#');
3950
+ this.redraw(new_par.id === $.jstree.root);
3778
3951
  }
3779
3952
  else {
3780
3953
  // clean old parent and up
@@ -3819,7 +3992,7 @@
3819
3992
  Array.prototype.push.apply(this._model.data[obj.children_d[i]].parents, tmp);
3820
3993
  }
3821
3994
 
3822
- if(old_par === '#' || new_par.id === '#') {
3995
+ if(old_par === $.jstree.root || new_par.id === $.jstree.root) {
3823
3996
  this._model.force_full_redraw = true;
3824
3997
  }
3825
3998
  if(!this._model.force_full_redraw) {
@@ -3886,10 +4059,10 @@
3886
4059
  }
3887
4060
  }
3888
4061
  obj = obj && obj.id ? obj : this.get_node(obj);
3889
- if(!obj || obj.id === '#') { return false; }
4062
+ if(!obj || obj.id === $.jstree.root) { return false; }
3890
4063
 
3891
- old_par = (obj.parent || '#').toString();
3892
- new_par = (!pos.toString().match(/^(before|after)$/) || par.id === '#') ? par : this.get_node(par.parent);
4064
+ old_par = (obj.parent || $.jstree.root).toString();
4065
+ new_par = (!pos.toString().match(/^(before|after)$/) || par.id === $.jstree.root) ? par : this.get_node(par.parent);
3893
4066
  old_ins = origin ? origin : (this._model.data[obj.id] ? this : $.jstree.reference(obj.id));
3894
4067
  is_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id);
3895
4068
 
@@ -3897,7 +4070,7 @@
3897
4070
  obj = old_ins._model.data[obj.id];
3898
4071
  }
3899
4072
 
3900
- if(par.id === '#') {
4073
+ if(par.id === $.jstree.root) {
3901
4074
  if(pos === "before") { pos = "first"; }
3902
4075
  if(pos === "after") { pos = "last"; }
3903
4076
  }
@@ -3949,14 +4122,14 @@
3949
4122
  new_par.children_d.push(tmp.id);
3950
4123
  new_par.children_d = new_par.children_d.concat(tmp.children_d);
3951
4124
 
3952
- if(new_par.id === '#') {
4125
+ if(new_par.id === $.jstree.root) {
3953
4126
  this._model.force_full_redraw = true;
3954
4127
  }
3955
4128
  if(!this._model.force_full_redraw) {
3956
4129
  this._node_changed(new_par.id);
3957
4130
  }
3958
4131
  if(!skip_redraw) {
3959
- this.redraw(new_par.id === '#');
4132
+ this.redraw(new_par.id === $.jstree.root);
3960
4133
  }
3961
4134
  if(callback) { callback.call(this, tmp, new_par, pos); }
3962
4135
  /**
@@ -3989,7 +4162,7 @@
3989
4162
  var tmp = [], o, t1, t2;
3990
4163
  for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
3991
4164
  o = this.get_node(obj[t1]);
3992
- if(o && o.id && o.id !== '#') { tmp.push(o); }
4165
+ if(o && o.id && o.id !== $.jstree.root) { tmp.push(o); }
3993
4166
  }
3994
4167
  if(!tmp.length) { return false; }
3995
4168
  ccp_node = tmp;
@@ -4016,7 +4189,7 @@
4016
4189
  var tmp = [], o, t1, t2;
4017
4190
  for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
4018
4191
  o = this.get_node(obj[t1]);
4019
- if(o && o.id && o.id !== '#') { tmp.push(o); }
4192
+ if(o && o.id && o.id !== $.jstree.root) { tmp.push(o); }
4020
4193
  }
4021
4194
  if(!tmp.length) { return false; }
4022
4195
  ccp_node = tmp;
@@ -4092,10 +4265,10 @@
4092
4265
  * @name edit(obj [, default_text, callback])
4093
4266
  * @param {mixed} obj
4094
4267
  * @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)
4095
- * @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
4268
+ * @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
4096
4269
  */
4097
4270
  edit : function (obj, default_text, callback) {
4098
- var rtl, w, a, s, t, h1, h2, fn, tmp;
4271
+ var rtl, w, a, s, t, h1, h2, fn, tmp, cancel = false;
4099
4272
  obj = this.get_node(obj);
4100
4273
  if(!obj) { return false; }
4101
4274
  if(this.settings.core.check_callback === false) {
@@ -4111,7 +4284,8 @@
4111
4284
 
4112
4285
  rtl = this._data.core.rtl;
4113
4286
  w = this.element.width();
4114
- a = obj.children('.jstree-anchor');
4287
+ this._data.core.focused = tmp.id;
4288
+ a = obj.children('.jstree-anchor').focus();
4115
4289
  s = $('<span>');
4116
4290
  /*!
4117
4291
  oi = obj.children("i:visible"),
@@ -4134,7 +4308,9 @@
4134
4308
  "lineHeight" : (this._data.core.li_height) + "px",
4135
4309
  "width" : "150px" // will be set a bit further down
4136
4310
  },
4137
- "blur" : $.proxy(function () {
4311
+ "blur" : $.proxy(function (e) {
4312
+ e.stopImmediatePropagation();
4313
+ e.preventDefault();
4138
4314
  var i = s.children(".jstree-rename-input"),
4139
4315
  v = i.val(),
4140
4316
  f = this.settings.core.force_text,
@@ -4149,30 +4325,39 @@
4149
4325
  if(!nv) {
4150
4326
  this.set_text(obj, t); // move this up? and fix #483
4151
4327
  }
4328
+ this._data.core.focused = tmp.id;
4329
+ setTimeout($.proxy(function () {
4330
+ var node = this.get_node(tmp.id, true);
4331
+ if(node.length) {
4332
+ this._data.core.focused = tmp.id;
4333
+ node.children('.jstree-anchor').focus();
4334
+ }
4335
+ }, this), 0);
4152
4336
  if(callback) {
4153
- callback.call(this, tmp, nv);
4337
+ callback.call(this, tmp, nv, cancel);
4154
4338
  }
4155
4339
  }, this),
4156
- "keydown" : function (event) {
4157
- var key = event.which;
4340
+ "keydown" : function (e) {
4341
+ var key = e.which;
4158
4342
  if(key === 27) {
4343
+ cancel = true;
4159
4344
  this.value = t;
4160
4345
  }
4161
4346
  if(key === 27 || key === 13 || key === 37 || key === 38 || key === 39 || key === 40 || key === 32) {
4162
- event.stopImmediatePropagation();
4347
+ e.stopImmediatePropagation();
4163
4348
  }
4164
4349
  if(key === 27 || key === 13) {
4165
- event.preventDefault();
4350
+ e.preventDefault();
4166
4351
  this.blur();
4167
4352
  }
4168
4353
  },
4169
4354
  "click" : function (e) { e.stopImmediatePropagation(); },
4170
4355
  "mousedown" : function (e) { e.stopImmediatePropagation(); },
4171
- "keyup" : function (event) {
4356
+ "keyup" : function (e) {
4172
4357
  h2.width(Math.min(h1.text("pW" + this.value).width(),w));
4173
4358
  },
4174
- "keypress" : function(event) {
4175
- if(event.which === 13) { return false; }
4359
+ "keypress" : function(e) {
4360
+ if(e.which === 13) { return false; }
4176
4361
  }
4177
4362
  });
4178
4363
  fn = {
@@ -4311,7 +4496,7 @@
4311
4496
  return true;
4312
4497
  }
4313
4498
  obj = this.get_node(obj);
4314
- if(!obj || obj.id === '#') { return false; }
4499
+ if(!obj || obj.id === $.jstree.root) { return false; }
4315
4500
  old = obj.icon;
4316
4501
  obj.icon = icon === true || icon === null || icon === undefined || icon === '' ? true : icon;
4317
4502
  dom = this.get_node(obj, true).children(".jstree-anchor").children(".jstree-themeicon");
@@ -4342,7 +4527,7 @@
4342
4527
  */
4343
4528
  get_icon : function (obj) {
4344
4529
  obj = this.get_node(obj);
4345
- return (!obj || obj.id === '#') ? false : obj.icon;
4530
+ return (!obj || obj.id === $.jstree.root) ? false : obj.icon;
4346
4531
  },
4347
4532
  /**
4348
4533
  * hide the icon on an individual node
@@ -4359,7 +4544,7 @@
4359
4544
  return true;
4360
4545
  }
4361
4546
  obj = this.get_node(obj);
4362
- if(!obj || obj === '#') { return false; }
4547
+ if(!obj || obj === $.jstree.root) { return false; }
4363
4548
  obj.icon = false;
4364
4549
  this.get_node(obj, true).children(".jstree-anchor").children(".jstree-themeicon").addClass('jstree-themeicon-hidden');
4365
4550
  return true;
@@ -4379,7 +4564,7 @@
4379
4564
  return true;
4380
4565
  }
4381
4566
  obj = this.get_node(obj);
4382
- if(!obj || obj === '#') { return false; }
4567
+ if(!obj || obj === $.jstree.root) { return false; }
4383
4568
  dom = this.get_node(obj, true);
4384
4569
  obj.icon = dom.length ? dom.children(".jstree-anchor").children(".jstree-themeicon").attr('rel') : true;
4385
4570
  if(!obj.icon) { obj.icon = true; }
@@ -4429,6 +4614,59 @@
4429
4614
  };
4430
4615
 
4431
4616
 
4617
+ /**
4618
+ * ### Changed plugin
4619
+ *
4620
+ * 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.
4621
+ */
4622
+
4623
+ $.jstree.plugins.changed = function (options, parent) {
4624
+ var last = [];
4625
+ this.trigger = function (ev, data) {
4626
+ var i, j;
4627
+ if(!data) {
4628
+ data = {};
4629
+ }
4630
+ if(ev.replace('.jstree','') === 'changed') {
4631
+ data.changed = { selected : [], deselected : [] };
4632
+ var tmp = {};
4633
+ for(i = 0, j = last.length; i < j; i++) {
4634
+ tmp[last[i]] = 1;
4635
+ }
4636
+ for(i = 0, j = data.selected.length; i < j; i++) {
4637
+ if(!tmp[data.selected[i]]) {
4638
+ data.changed.selected.push(data.selected[i]);
4639
+ }
4640
+ else {
4641
+ tmp[data.selected[i]] = 2;
4642
+ }
4643
+ }
4644
+ for(i = 0, j = last.length; i < j; i++) {
4645
+ if(tmp[last[i]] === 1) {
4646
+ data.changed.deselected.push(last[i]);
4647
+ }
4648
+ }
4649
+ last = data.selected.slice();
4650
+ }
4651
+ /**
4652
+ * triggered when selection changes (the "changed" plugin enhances the original event with more data)
4653
+ * @event
4654
+ * @name changed.jstree
4655
+ * @param {Object} node
4656
+ * @param {Object} action the action that caused the selection to change
4657
+ * @param {Array} selected the current selection
4658
+ * @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
4659
+ * @param {Object} event the event (if any) that triggered this changed event
4660
+ * @plugin changed
4661
+ */
4662
+ parent.trigger.call(this, ev, data);
4663
+ };
4664
+ this.refresh = function (skip_loading, forget_state) {
4665
+ last = [];
4666
+ return parent.refresh.apply(this, arguments);
4667
+ };
4668
+ };
4669
+
4432
4670
  /**
4433
4671
  * ### Checkbox plugin
4434
4672
  *
@@ -4521,7 +4759,7 @@
4521
4759
  dpc = data.nodes,
4522
4760
  i, j;
4523
4761
  for(i = 0, j = dpc.length; i < j; i++) {
4524
- m[dpc[i]].state.checked = (m[dpc[i]].original && m[dpc[i]].original.state && m[dpc[i]].original.state.checked);
4762
+ 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);
4525
4763
  if(m[dpc[i]].state.checked) {
4526
4764
  this._data.checkbox.selected.push(dpc[i]);
4527
4765
  }
@@ -4567,7 +4805,7 @@
4567
4805
  chd = $.vakata.array_unique(chd);
4568
4806
  for(k = 0, l = chd.length; k < l; k++) {
4569
4807
  p = m[chd[k]];
4570
- while(p && p.id !== '#') {
4808
+ while(p && p.id !== $.jstree.root) {
4571
4809
  c = 0;
4572
4810
  for(i = 0, j = p.children.length; i < j; i++) {
4573
4811
  c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
@@ -4611,7 +4849,7 @@
4611
4849
 
4612
4850
  // apply up
4613
4851
  if(s.indexOf('up') !== -1) {
4614
- while(par && par.id !== '#') {
4852
+ while(par && par.id !== $.jstree.root) {
4615
4853
  c = 0;
4616
4854
  for(i = 0, j = par.children.length; i < j; i++) {
4617
4855
  c += m[par.children[i]].state[ t ? 'selected' : 'checked' ];
@@ -4637,7 +4875,7 @@
4637
4875
  }
4638
4876
  }, this))
4639
4877
  .on(this.settings.checkbox.tie_selection ? 'deselect_all.jstree' : 'uncheck_all.jstree', $.proxy(function (e, data) {
4640
- var obj = this.get_node('#'),
4878
+ var obj = this.get_node($.jstree.root),
4641
4879
  m = this._model.data,
4642
4880
  i, j, tmp;
4643
4881
  for(i = 0, j = obj.children_d.length; i < j; i++) {
@@ -4705,7 +4943,7 @@
4705
4943
  var p = this.get_node(data.parent),
4706
4944
  m = this._model.data,
4707
4945
  i, j, c, tmp, t = this.settings.checkbox.tie_selection;
4708
- while(p && p.id !== '#') {
4946
+ while(p && p.id !== $.jstree.root) {
4709
4947
  c = 0;
4710
4948
  for(i = 0, j = p.children.length; i < j; i++) {
4711
4949
  c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
@@ -4733,7 +4971,7 @@
4733
4971
  p, c, i, j, tmp, t = this.settings.checkbox.tie_selection;
4734
4972
  if(!is_multi) {
4735
4973
  p = this.get_node(old_par);
4736
- while(p && p.id !== '#') {
4974
+ while(p && p.id !== $.jstree.root) {
4737
4975
  c = 0;
4738
4976
  for(i = 0, j = p.children.length; i < j; i++) {
4739
4977
  c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
@@ -4753,7 +4991,7 @@
4753
4991
  }
4754
4992
  }
4755
4993
  p = new_par;
4756
- while(p && p.id !== '#') {
4994
+ while(p && p.id !== $.jstree.root) {
4757
4995
  c = 0;
4758
4996
  for(i = 0, j = p.children.length; i < j; i++) {
4759
4997
  c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
@@ -4798,7 +5036,7 @@
4798
5036
  for(i = 0, j = s.length; i < j; i++) {
4799
5037
  if(m[s[i]] && m[s[i]].parents) {
4800
5038
  for(k = 0, l = m[s[i]].parents.length; k < l; k++) {
4801
- if(o[m[s[i]].parents[k]] === undefined && m[s[i]].parents[k] !== '#') {
5039
+ if(o[m[s[i]].parents[k]] === undefined && m[s[i]].parents[k] !== $.jstree.root) {
4802
5040
  o[m[s[i]].parents[k]] = true;
4803
5041
  p.push(m[s[i]].parents[k]);
4804
5042
  }
@@ -4811,12 +5049,12 @@
4811
5049
  var tmp = tt.get_node(this), tmp2;
4812
5050
  if(!tmp.state.loaded) {
4813
5051
  if(tmp.original && tmp.original.state && tmp.original.state.undetermined && tmp.original.state.undetermined === true) {
4814
- if(o[tmp.id] === undefined && tmp.id !== '#') {
5052
+ if(o[tmp.id] === undefined && tmp.id !== $.jstree.root) {
4815
5053
  o[tmp.id] = true;
4816
5054
  p.push(tmp.id);
4817
5055
  }
4818
5056
  for(k = 0, l = tmp.parents.length; k < l; k++) {
4819
- if(o[tmp.parents[k]] === undefined && tmp.parents[k] !== '#') {
5057
+ if(o[tmp.parents[k]] === undefined && tmp.parents[k] !== $.jstree.root) {
4820
5058
  o[tmp.parents[k]] = true;
4821
5059
  p.push(tmp.parents[k]);
4822
5060
  }
@@ -4827,12 +5065,12 @@
4827
5065
  for(i = 0, j = tmp.children_d.length; i < j; i++) {
4828
5066
  tmp2 = m[tmp.children_d[i]];
4829
5067
  if(!tmp2.state.loaded && tmp2.original && tmp2.original.state && tmp2.original.state.undetermined && tmp2.original.state.undetermined === true) {
4830
- if(o[tmp2.id] === undefined && tmp2.id !== '#') {
5068
+ if(o[tmp2.id] === undefined && tmp2.id !== $.jstree.root) {
4831
5069
  o[tmp2.id] = true;
4832
5070
  p.push(tmp2.id);
4833
5071
  }
4834
5072
  for(k = 0, l = tmp2.parents.length; k < l; k++) {
4835
- if(o[tmp2.parents[k]] === undefined && tmp2.parents[k] !== '#') {
5073
+ if(o[tmp2.parents[k]] === undefined && tmp2.parents[k] !== $.jstree.root) {
4836
5074
  o[tmp2.parents[k]] = true;
4837
5075
  p.push(tmp2.parents[k]);
4838
5076
  }
@@ -4855,7 +5093,7 @@
4855
5093
  this.redraw_node = function(obj, deep, is_callback, force_render) {
4856
5094
  obj = parent.redraw_node.apply(this, arguments);
4857
5095
  if(obj) {
4858
- var i, j, tmp = null;
5096
+ var i, j, tmp = null, icon = null;
4859
5097
  for(i = 0, j = obj.childNodes.length; i < j; i++) {
4860
5098
  if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) {
4861
5099
  tmp = obj.childNodes[i];
@@ -4864,7 +5102,9 @@
4864
5102
  }
4865
5103
  if(tmp) {
4866
5104
  if(!this.settings.checkbox.tie_selection && this._model.data[obj.id].state.checked) { tmp.className += ' jstree-checked'; }
4867
- tmp.insertBefore(_i.cloneNode(false), tmp.childNodes[0]);
5105
+ icon = _i.cloneNode(false);
5106
+ if(this._model.data[obj.id].state.checkbox_disabled) { icon.className += ' jstree-checkbox-disabled'; }
5107
+ tmp.insertBefore(icon, tmp.childNodes[0]);
4868
5108
  }
4869
5109
  }
4870
5110
  if(!is_callback && this.settings.checkbox.cascade.indexOf('undetermined') !== -1) {
@@ -4913,8 +5153,83 @@
4913
5153
  }
4914
5154
  return false;
4915
5155
  };
5156
+ /**
5157
+ * disable a node's checkbox
5158
+ * @name disable_checkbox(obj)
5159
+ * @param {mixed} obj an array can be used too
5160
+ * @trigger disable_checkbox.jstree
5161
+ * @plugin checkbox
5162
+ */
5163
+ this.disable_checkbox = function (obj) {
5164
+ var t1, t2, dom;
5165
+ if($.isArray(obj)) {
5166
+ obj = obj.slice();
5167
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
5168
+ this.disable_checkbox(obj[t1]);
5169
+ }
5170
+ return true;
5171
+ }
5172
+ obj = this.get_node(obj);
5173
+ if(!obj || obj.id === $.jstree.root) {
5174
+ return false;
5175
+ }
5176
+ dom = this.get_node(obj, true);
5177
+ if(!obj.state.checkbox_disabled) {
5178
+ obj.state.checkbox_disabled = true;
5179
+ if(dom && dom.length) {
5180
+ dom.children('.jstree-anchor').children('.jstree-checkbox').addClass('jstree-checkbox-disabled');
5181
+ }
5182
+ /**
5183
+ * triggered when an node's checkbox is disabled
5184
+ * @event
5185
+ * @name disable_checkbox.jstree
5186
+ * @param {Object} node
5187
+ * @plugin checkbox
5188
+ */
5189
+ this.trigger('disable_checkbox', { 'node' : obj });
5190
+ }
5191
+ };
5192
+ /**
5193
+ * enable a node's checkbox
5194
+ * @name disable_checkbox(obj)
5195
+ * @param {mixed} obj an array can be used too
5196
+ * @trigger enable_checkbox.jstree
5197
+ * @plugin checkbox
5198
+ */
5199
+ this.enable_checkbox = function (obj) {
5200
+ var t1, t2, dom;
5201
+ if($.isArray(obj)) {
5202
+ obj = obj.slice();
5203
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
5204
+ this.enable_checkbox(obj[t1]);
5205
+ }
5206
+ return true;
5207
+ }
5208
+ obj = this.get_node(obj);
5209
+ if(!obj || obj.id === $.jstree.root) {
5210
+ return false;
5211
+ }
5212
+ dom = this.get_node(obj, true);
5213
+ if(obj.state.checkbox_disabled) {
5214
+ obj.state.checkbox_disabled = false;
5215
+ if(dom && dom.length) {
5216
+ dom.children('.jstree-anchor').children('.jstree-checkbox').removeClass('jstree-checkbox-disabled');
5217
+ }
5218
+ /**
5219
+ * triggered when an node's checkbox is enabled
5220
+ * @event
5221
+ * @name enable_checkbox.jstree
5222
+ * @param {Object} node
5223
+ * @plugin checkbox
5224
+ */
5225
+ this.trigger('enable_checkbox', { 'node' : obj });
5226
+ }
5227
+ };
4916
5228
 
4917
5229
  this.activate_node = function (obj, e) {
5230
+ if($(e.target).hasClass('jstree-checkbox-disabled')) {
5231
+ return false;
5232
+ }
4918
5233
  if(this.settings.checkbox.tie_selection && (this.settings.checkbox.whole_node || $(e.target).hasClass('jstree-checkbox'))) {
4919
5234
  e.ctrlKey = true;
4920
5235
  }
@@ -4951,7 +5266,7 @@
4951
5266
  return true;
4952
5267
  }
4953
5268
  obj = this.get_node(obj);
4954
- if(!obj || obj.id === '#') {
5269
+ if(!obj || obj.id === $.jstree.root) {
4955
5270
  return false;
4956
5271
  }
4957
5272
  dom = this.get_node(obj, true);
@@ -4991,7 +5306,7 @@
4991
5306
  return true;
4992
5307
  }
4993
5308
  obj = this.get_node(obj);
4994
- if(!obj || obj.id === '#') {
5309
+ if(!obj || obj.id === $.jstree.root) {
4995
5310
  return false;
4996
5311
  }
4997
5312
  dom = this.get_node(obj, true);
@@ -5022,7 +5337,7 @@
5022
5337
  this.check_all = function () {
5023
5338
  if(this.settings.checkbox.tie_selection) { return this.select_all(); }
5024
5339
  var tmp = this._data.checkbox.selected.concat([]), i, j;
5025
- this._data.checkbox.selected = this._model.data['#'].children_d.concat();
5340
+ this._data.checkbox.selected = this._model.data[$.jstree.root].children_d.concat();
5026
5341
  for(i = 0, j = this._data.checkbox.selected.length; i < j; i++) {
5027
5342
  if(this._model.data[this._data.checkbox.selected[i]]) {
5028
5343
  this._model.data[this._data.checkbox.selected[i]].state.checked = true;
@@ -5074,7 +5389,7 @@
5074
5389
  this.is_checked = function (obj) {
5075
5390
  if(this.settings.checkbox.tie_selection) { return this.is_selected(obj); }
5076
5391
  obj = this.get_node(obj);
5077
- if(!obj || obj.id === '#') { return false; }
5392
+ if(!obj || obj.id === $.jstree.root) { return false; }
5078
5393
  return obj.state.checked;
5079
5394
  };
5080
5395
  /**
@@ -5172,11 +5487,39 @@
5172
5487
  }
5173
5488
  return res;
5174
5489
  };
5490
+ this.refresh = function (skip_loading, forget_state) {
5491
+ if(!this.settings.checkbox.tie_selection) {
5492
+ this._data.checkbox.selected = [];
5493
+ }
5494
+ return parent.refresh.apply(this, arguments);
5495
+ };
5175
5496
  };
5176
5497
 
5177
5498
  // include the checkbox plugin by default
5178
5499
  // $.jstree.defaults.plugins.push("checkbox");
5179
5500
 
5501
+ /**
5502
+ * ### Conditionalselect plugin
5503
+ *
5504
+ * This plugin allows defining a callback to allow or deny node selection by user input (activate node method).
5505
+ */
5506
+
5507
+ /**
5508
+ * 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`.
5509
+ * @name $.jstree.defaults.checkbox.visible
5510
+ * @plugin checkbox
5511
+ */
5512
+ $.jstree.defaults.conditionalselect = function () { return true; };
5513
+ $.jstree.plugins.conditionalselect = function (options, parent) {
5514
+ // own function
5515
+ this.activate_node = function (obj, e) {
5516
+ if(this.settings.conditionalselect.call(this, this.get_node(obj), e)) {
5517
+ parent.activate_node.call(this, obj, e);
5518
+ }
5519
+ };
5520
+ };
5521
+
5522
+
5180
5523
  /**
5181
5524
  * ### Contextmenu plugin
5182
5525
  *
@@ -5412,7 +5755,7 @@
5412
5755
  */
5413
5756
  this.show_contextmenu = function (obj, x, y, e) {
5414
5757
  obj = this.get_node(obj);
5415
- if(!obj || obj.id === '#') { return false; }
5758
+ if(!obj || obj.id === $.jstree.root) { return false; }
5416
5759
  var s = this.settings.contextmenu,
5417
5760
  d = this.get_node(obj, true),
5418
5761
  a = d.children(".jstree-anchor"),
@@ -5817,7 +6160,7 @@
5817
6160
  */
5818
6161
  open_timeout : 500,
5819
6162
  /**
5820
- * 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
6163
+ * 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
5821
6164
  * @name $.jstree.defaults.dnd.is_draggable
5822
6165
  * @plugin dnd
5823
6166
  */
@@ -5884,8 +6227,8 @@
5884
6227
  if(this.settings.core.force_text) {
5885
6228
  txt = $.vakata.html.escape(txt);
5886
6229
  }
5887
- if(obj && obj.id && obj.id !== "#" && (e.which === 1 || e.type === "touchstart") &&
5888
- (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]))))
6230
+ if(obj && obj.id && obj.id !== $.jstree.root && (e.which === 1 || e.type === "touchstart") &&
6231
+ (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)))
5889
6232
  ) {
5890
6233
  this.element.trigger('mousedown.jstree');
5891
6234
  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>');
@@ -5898,12 +6241,14 @@
5898
6241
  // bind only once for all instances
5899
6242
  var lastmv = false,
5900
6243
  laster = false,
6244
+ lastev = false,
5901
6245
  opento = false,
5902
6246
  marker = $('<div id="jstree-marker">&#160;</div>').hide(); //.appendTo('body');
5903
6247
 
5904
6248
  $(document)
5905
6249
  .on('dnd_start.vakata.jstree', function (e, data) {
5906
6250
  lastmv = false;
6251
+ lastev = false;
5907
6252
  if(!data || !data.data || !data.data.jstree) { return; }
5908
6253
  marker.appendTo('body'); //.show();
5909
6254
  })
@@ -5915,6 +6260,7 @@
5915
6260
  if(data.event.target.id && data.event.target.id === 'jstree-marker') {
5916
6261
  return;
5917
6262
  }
6263
+ lastev = data.event;
5918
6264
 
5919
6265
  var ins = $.jstree.reference(data.event.target),
5920
6266
  ref = false,
@@ -5933,11 +6279,11 @@
5933
6279
  if( (data.event.target === ins.element[0] || data.event.target === ins.get_container_ul()[0]) && ins.get_container_ul().children().length === 0) {
5934
6280
  ok = true;
5935
6281
  for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) {
5936
- 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) });
6282
+ 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) });
5937
6283
  if(!ok) { break; }
5938
6284
  }
5939
6285
  if(ok) {
5940
- lastmv = { 'ins' : ins, 'par' : '#', 'pos' : 'last' };
6286
+ lastmv = { 'ins' : ins, 'par' : $.jstree.root, 'pos' : 'last' };
5941
6287
  marker.hide();
5942
6288
  data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok');
5943
6289
  return;
@@ -6022,6 +6368,7 @@
6022
6368
  if(!data || !data.data || !data.data.jstree) { return; }
6023
6369
  marker.hide();
6024
6370
  lastmv = false;
6371
+ lastev = false;
6025
6372
  data.helper.find('.jstree-icon').first().removeClass('jstree-ok').addClass('jstree-er');
6026
6373
  })
6027
6374
  .on('dnd_stop.vakata.jstree', function (e, data) {
@@ -6044,11 +6391,18 @@
6044
6391
  }
6045
6392
  }
6046
6393
  }
6394
+ lastev = false;
6395
+ lastmv = false;
6047
6396
  })
6048
6397
  .on('keyup.jstree keydown.jstree', function (e, data) {
6049
6398
  data = $.vakata.dnd._get();
6050
6399
  if(data && data.data && data.data.jstree) {
6051
6400
  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' ]();
6401
+ if(lastev) {
6402
+ lastev.metaKey = e.metaKey;
6403
+ lastev.ctrlKey = e.ctrlKey;
6404
+ $.vakata.dnd._trigger('move', lastev);
6405
+ }
6052
6406
  }
6053
6407
  });
6054
6408
  });
@@ -6484,45 +6838,29 @@
6484
6838
  this._data.search.opn = [];
6485
6839
  this._data.search.som = false;
6486
6840
  this._data.search.smc = false;
6841
+ this._data.search.hdn = [];
6487
6842
 
6488
6843
  this.element
6489
- .on('before_open.jstree', $.proxy(function (e, data) {
6490
- var i, j, f, r = this._data.search.res, s = [], o = $();
6491
- if(r && r.length) {
6492
- 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(', #')));
6493
- this._data.search.dom.children(".jstree-anchor").addClass('jstree-search');
6494
- if(this._data.search.som && this._data.search.res.length) {
6495
- for(i = 0, j = r.length; i < j; i++) {
6496
- s = s.concat(this.get_node(r[i]).parents);
6497
- }
6498
- s = $.vakata.array_remove_item($.vakata.array_unique(s),'#');
6499
- 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(', #'))) : $();
6500
-
6501
- this.element.find(".jstree-node").hide().filter('.jstree-last').filter(function() { return this.nextSibling; }).removeClass('jstree-last');
6502
- o = o.add(this._data.search.dom);
6503
- if(this._data.search.smc) {
6504
- this._data.search.dom.children(".jstree-children").find(".jstree-node").show();
6505
- }
6506
- o.parentsUntil(".jstree").addBack().show()
6507
- .filter(".jstree-children").each(function () { $(this).children(".jstree-node:visible").eq(-1).addClass("jstree-last"); });
6508
- }
6509
- }
6510
- }, this))
6511
6844
  .on("search.jstree", $.proxy(function (e, data) {
6512
- if(this._data.search.som) {
6513
- if(data.nodes.length) {
6514
- this.element.find(".jstree-node").hide().filter('.jstree-last').filter(function() { return this.nextSibling; }).removeClass('jstree-last');
6515
- if(this._data.search.smc) {
6516
- data.nodes.children(".jstree-children").find(".jstree-node").show();
6845
+ if(this._data.search.som && data.res.length) {
6846
+ var m = this._model.data, i, j, p = [];
6847
+ for(i = 0, j = data.res.length; i < j; i++) {
6848
+ if(m[data.res[i]] && !m[data.res[i]].state.hidden) {
6849
+ p.push(data.res[i]);
6850
+ p = p.concat(m[data.res[i]].parents);
6851
+ if(this._data.search.smc) {
6852
+ p = p.concat(m[data.res[i]].children_d);
6853
+ }
6517
6854
  }
6518
- data.nodes.parentsUntil(".jstree").addBack().show()
6519
- .filter(".jstree-children").each(function () { $(this).children(".jstree-node:visible").eq(-1).addClass("jstree-last"); });
6520
6855
  }
6856
+ p = $.vakata.array_remove_item($.vakata.array_unique(p), $.jstree.root);
6857
+ this._data.search.hdn = this.hide_all();
6858
+ this.show_node(p);
6521
6859
  }
6522
6860
  }, this))
6523
6861
  .on("clear_search.jstree", $.proxy(function (e, data) {
6524
- if(this._data.search.som && data.nodes.length) {
6525
- this.element.find(".jstree-node").css("display","").filter('.jstree-last').filter(function() { return this.nextSibling; }).removeClass('jstree-last');
6862
+ if(this._data.search.som && data.res.length) {
6863
+ this.show_node(this._data.search.hdn);
6526
6864
  }
6527
6865
  }, this));
6528
6866
  };
@@ -6598,9 +6936,9 @@
6598
6936
  }
6599
6937
 
6600
6938
  f = new $.vakata.search(str, true, { caseSensitive : s.case_sensitive, fuzzy : s.fuzzy });
6601
- $.each(m[inside ? inside : '#'].children_d, function (ii, i) {
6939
+ $.each(m[inside ? inside : $.jstree.root].children_d, function (ii, i) {
6602
6940
  var v = m[i];
6603
- 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)) ) {
6941
+ 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) ) ) {
6604
6942
  r.push(i);
6605
6943
  p = p.concat(v.parents);
6606
6944
  }
@@ -6636,7 +6974,6 @@
6636
6974
  * @trigger clear_search.jstree
6637
6975
  */
6638
6976
  this.clear_search = function () {
6639
- this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search");
6640
6977
  if(this.settings.search.close_opened_onclear) {
6641
6978
  this.close_node(this._data.search.opn, 0);
6642
6979
  }
@@ -6650,6 +6987,12 @@
6650
6987
  * @plugin search
6651
6988
  */
6652
6989
  this.trigger('clear_search', { 'nodes' : this._data.search.dom, str : this._data.search.str, res : this._data.search.res });
6990
+ if(this._data.search.res.length) {
6991
+ this._data.search.dom = $(this.element[0].querySelectorAll('#' + $.map(this._data.search.res, function (v) {
6992
+ return "0123456789".indexOf(v[0]) !== -1 ? '\\3' + v[0] + ' ' + v.substr(1).replace($.jstree.idregex,'\\$&') : v.replace($.jstree.idregex,'\\$&');
6993
+ }).join(', #')));
6994
+ this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search");
6995
+ }
6653
6996
  this._data.search.str = "";
6654
6997
  this._data.search.res = [];
6655
6998
  this._data.search.opn = [];
@@ -6665,7 +7008,7 @@
6665
7008
  this._search_open = function (d) {
6666
7009
  var t = this;
6667
7010
  $.each(d.concat([]), function (i, v) {
6668
- if(v === "#") { return true; }
7011
+ if(v === $.jstree.root) { return true; }
6669
7012
  try { v = $('#' + v.replace($.jstree.idregex,'\\$&'), t.element); } catch(ignore) { }
6670
7013
  if(v && v.length) {
6671
7014
  if(t.is_closed(v)) {
@@ -6675,6 +7018,25 @@
6675
7018
  }
6676
7019
  });
6677
7020
  };
7021
+
7022
+ this.redraw_node = function(obj, deep, callback, force_render) {
7023
+ obj = parent.redraw_node.apply(this, arguments);
7024
+ if(obj) {
7025
+ if($.inArray(obj.id, this._data.search.res) !== -1) {
7026
+ var i, j, tmp = null;
7027
+ for(i = 0, j = obj.childNodes.length; i < j; i++) {
7028
+ if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) {
7029
+ tmp = obj.childNodes[i];
7030
+ break;
7031
+ }
7032
+ }
7033
+ if(tmp) {
7034
+ tmp.className += ' jstree-search';
7035
+ }
7036
+ }
7037
+ }
7038
+ return obj;
7039
+ };
6678
7040
  };
6679
7041
 
6680
7042
  // helpers
@@ -6809,6 +7171,7 @@
6809
7171
  // include the search plugin by default
6810
7172
  // $.jstree.defaults.plugins.push("search");
6811
7173
 
7174
+
6812
7175
  /**
6813
7176
  * ### Sort plugin
6814
7177
  *
@@ -6999,16 +7362,16 @@
6999
7362
  * @plugin types
7000
7363
  */
7001
7364
  $.jstree.defaults.types = {
7002
- '#' : {},
7003
7365
  'default' : {}
7004
7366
  };
7367
+ $.jstree.defaults.types[$.jstree.root] = {};
7005
7368
 
7006
7369
  $.jstree.plugins.types = function (options, parent) {
7007
7370
  this.init = function (el, options) {
7008
7371
  var i, j;
7009
7372
  if(options && options.types && options.types['default']) {
7010
7373
  for(i in options.types) {
7011
- if(i !== "default" && i !== "#" && options.types.hasOwnProperty(i)) {
7374
+ if(i !== "default" && i !== $.jstree.root && options.types.hasOwnProperty(i)) {
7012
7375
  for(j in options.types['default']) {
7013
7376
  if(options.types['default'].hasOwnProperty(j) && options.types[i][j] === undefined) {
7014
7377
  options.types[i][j] = options.types['default'][j];
@@ -7018,11 +7381,11 @@
7018
7381
  }
7019
7382
  }
7020
7383
  parent.init.call(this, el, options);
7021
- this._model.data['#'].type = '#';
7384
+ this._model.data[$.jstree.root].type = $.jstree.root;
7022
7385
  };
7023
7386
  this.refresh = function (skip_loading, forget_state) {
7024
7387
  parent.refresh.call(this, skip_loading, forget_state);
7025
- this._model.data['#'].type = '#';
7388
+ this._model.data[$.jstree.root].type = $.jstree.root;
7026
7389
  };
7027
7390
  this.bind = function () {
7028
7391
  this.element
@@ -7044,7 +7407,7 @@
7044
7407
  m[dpc[i]].icon = t[c].icon;
7045
7408
  }
7046
7409
  }
7047
- m['#'].type = '#';
7410
+ m[$.jstree.root].type = $.jstree.root;
7048
7411
  }, this));
7049
7412
  parent.bind.call(this);
7050
7413
  };
@@ -7271,7 +7634,7 @@
7271
7634
  this.create_node = function (par, node, pos, callback, is_loaded) {
7272
7635
  if(!node || node.text === undefined) {
7273
7636
  if(par === null) {
7274
- par = "#";
7637
+ par = $.jstree.root;
7275
7638
  }
7276
7639
  par = this.get_node(par);
7277
7640
  if(!par) {
@@ -7425,4 +7788,5 @@
7425
7788
  } catch(ignore) { }
7426
7789
  }
7427
7790
 
7791
+ return $.fn.jstree;
7428
7792
  }));