sequenceserver 2.0.0.rc8 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sequenceserver might be problematic. Click here for more details.

Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/bin/sequenceserver +22 -30
  3. data/lib/sequenceserver/api_errors.rb +5 -1
  4. data/lib/sequenceserver/blast/constants.rb +1 -1
  5. data/lib/sequenceserver/blast/hit.rb +5 -16
  6. data/lib/sequenceserver/blast/job.rb +9 -18
  7. data/lib/sequenceserver/blast/report.rb +5 -3
  8. data/lib/sequenceserver/config.rb +4 -1
  9. data/lib/sequenceserver/database.rb +69 -9
  10. data/lib/sequenceserver/job.rb +1 -1
  11. data/lib/sequenceserver/makeblastdb.rb +40 -45
  12. data/lib/sequenceserver/routes.rb +4 -0
  13. data/lib/sequenceserver/version.rb +1 -1
  14. data/lib/sequenceserver.rb +15 -11
  15. data/public/config.js +143 -142
  16. data/public/css/fonts.css +23 -22
  17. data/public/css/grapher.css +598 -594
  18. data/public/css/sequenceserver.css +86 -24
  19. data/public/css/sequenceserver.min.css +2 -2
  20. data/public/js/alignment_exporter.js +14 -14
  21. data/public/js/databases_tree.js +215 -0
  22. data/public/js/download_fasta.js +1 -1
  23. data/public/js/hit.js +6 -2
  24. data/public/js/hits_overview.js +1 -1
  25. data/public/js/length_distribution.js +5 -5
  26. data/public/js/query.js +4 -7
  27. data/public/js/report.js +12 -24
  28. data/public/js/search.js +21 -2
  29. data/public/js/sidebar.js +4 -4
  30. data/public/js/svgExporter.js +12 -12
  31. data/public/js/visualisation_helpers.js +4 -5
  32. data/public/sequenceserver-report.min.js +11 -11
  33. data/public/sequenceserver-search.min.js +15 -11
  34. data/public/vendor/github/vakata/jstree@3.3.8/LICENSE-MIT +22 -0
  35. data/public/vendor/github/vakata/jstree@3.3.8/README.md +663 -0
  36. data/public/vendor/github/vakata/jstree@3.3.8/bower.json +33 -0
  37. data/public/vendor/github/vakata/jstree@3.3.8/component.json +28 -0
  38. data/public/vendor/github/vakata/jstree@3.3.8/composer.json +46 -0
  39. data/public/vendor/github/vakata/jstree@3.3.8/demo/README.md +2 -0
  40. data/public/vendor/github/vakata/jstree@3.3.8/demo/basic/index.html +146 -0
  41. data/public/vendor/github/vakata/jstree@3.3.8/demo/basic/root.json +1 -0
  42. data/public/vendor/github/vakata/jstree@3.3.8/dist/jstree.js +8612 -0
  43. data/public/vendor/github/vakata/jstree@3.3.8/dist/jstree.min.js +6 -0
  44. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/32px.png +0 -0
  45. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/40px.png +0 -0
  46. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/style.css +1102 -0
  47. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/style.min.css +1 -0
  48. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default/throbber.gif +0 -0
  49. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/32px.png +0 -0
  50. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/40px.png +0 -0
  51. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/style.css +1146 -0
  52. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/style.min.css +1 -0
  53. data/public/vendor/github/vakata/jstree@3.3.8/dist/themes/default-dark/throbber.gif +0 -0
  54. data/public/vendor/github/vakata/jstree@3.3.8/gruntfile.js +242 -0
  55. data/public/vendor/github/vakata/jstree@3.3.8/jstree.jquery.json +28 -0
  56. data/public/vendor/github/vakata/jstree@3.3.8/package.json +58 -0
  57. data/public/vendor/github/vakata/jstree@3.3.8/src/intro.js +14 -0
  58. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.changed.js +69 -0
  59. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.checkbox.js +976 -0
  60. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.conditionalselect.js +38 -0
  61. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.contextmenu.js +661 -0
  62. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.dnd.js +669 -0
  63. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.js +4931 -0
  64. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.massload.js +137 -0
  65. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.search.js +421 -0
  66. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.sort.js +74 -0
  67. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.state.js +138 -0
  68. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.types.js +372 -0
  69. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.unique.js +164 -0
  70. data/public/vendor/github/vakata/jstree@3.3.8/src/jstree.wholerow.js +122 -0
  71. data/public/vendor/github/vakata/jstree@3.3.8/src/misc.js +656 -0
  72. data/public/vendor/github/vakata/jstree@3.3.8/src/outro.js +1 -0
  73. data/public/vendor/github/vakata/jstree@3.3.8/src/sample.js +93 -0
  74. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/base.less +93 -0
  75. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/32px.png +0 -0
  76. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/40px.png +0 -0
  77. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/style.css +1102 -0
  78. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/style.less +22 -0
  79. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default/throbber.gif +0 -0
  80. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/32px.png +0 -0
  81. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/40px.png +0 -0
  82. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/style.css +1146 -0
  83. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/style.less +50 -0
  84. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/default-dark/throbber.gif +0 -0
  85. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/main.less +77 -0
  86. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/mixins.less +104 -0
  87. data/public/vendor/github/vakata/jstree@3.3.8/src/themes/responsive.less +67 -0
  88. data/public/vendor/github/vakata/jstree@3.3.8/src/vakata-jstree.js +38 -0
  89. data/public/vendor/github/vakata/jstree@3.3.8/test/unit/index.html +16 -0
  90. data/public/vendor/github/vakata/jstree@3.3.8/test/unit/libs/qunit.css +244 -0
  91. data/public/vendor/github/vakata/jstree@3.3.8/test/unit/libs/qunit.js +2212 -0
  92. data/public/vendor/github/vakata/jstree@3.3.8/test/unit/test.js +11 -0
  93. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/desktop/index.html +44 -0
  94. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/mobile/index.html +42 -0
  95. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/desktop/desktop.png +0 -0
  96. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/desktop/home.png +0 -0
  97. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/mobile/home.png +0 -0
  98. data/public/vendor/github/vakata/jstree@3.3.8/test/visual/screenshots/mobile/mobile.png +0 -0
  99. data/public/vendor/github/vakata/jstree@3.3.8.js +3 -0
  100. data/public/vendor/system-csp-production.js +3 -3
  101. data/public/vendor/system-csp-production.js.map +1 -1
  102. data/public/vendor/system-csp-production.src.js +146 -140
  103. data/public/vendor/system-polyfills.js.map +1 -1
  104. data/public/vendor/system-polyfills.src.js +1 -0
  105. data/public/vendor/system.js +3 -3
  106. data/public/vendor/system.js.map +1 -1
  107. data/public/vendor/system.src.js +4771 -2383
  108. data/views/_options.erb +21 -0
  109. data/views/layout.erb +17 -18
  110. metadata +102 -43
  111. data/bin/chromedriver +0 -0
  112. data/bin/geckodriver +0 -0
  113. data/public/shims/form-core.js +0 -3
  114. data/public/shims/form-validation.js +0 -3
  115. data/public/shims/plugins/jquery.ui.position.js +0 -13
  116. data/public/shims/styles/shim.css +0 -1
@@ -0,0 +1,976 @@
1
+ /**
2
+ * ### Checkbox plugin
3
+ *
4
+ * This plugin renders checkbox icons in front of each node, making multiple selection much easier.
5
+ * 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.
6
+ */
7
+ /*globals jQuery, define, exports, require, document */
8
+ (function (factory) {
9
+ "use strict";
10
+ if (typeof define === 'function' && define.amd) {
11
+ define('jstree.checkbox', ['jquery','jstree'], factory);
12
+ }
13
+ else if(typeof exports === 'object') {
14
+ factory(require('jquery'), require('jstree'));
15
+ }
16
+ else {
17
+ factory(jQuery, jQuery.jstree);
18
+ }
19
+ }(function ($, jstree, undefined) {
20
+ "use strict";
21
+
22
+ if($.jstree.plugins.checkbox) { return; }
23
+
24
+ var _i = document.createElement('I');
25
+ _i.className = 'jstree-icon jstree-checkbox';
26
+ _i.setAttribute('role', 'presentation');
27
+ /**
28
+ * stores all defaults for the checkbox plugin
29
+ * @name $.jstree.defaults.checkbox
30
+ * @plugin checkbox
31
+ */
32
+ $.jstree.defaults.checkbox = {
33
+ /**
34
+ * a boolean indicating if checkboxes should be visible (can be changed at a later time using `show_checkboxes()` and `hide_checkboxes`). Defaults to `true`.
35
+ * @name $.jstree.defaults.checkbox.visible
36
+ * @plugin checkbox
37
+ */
38
+ visible : true,
39
+ /**
40
+ * a boolean indicating if checkboxes should cascade down and have an undetermined state. Defaults to `true`.
41
+ * @name $.jstree.defaults.checkbox.three_state
42
+ * @plugin checkbox
43
+ */
44
+ three_state : true,
45
+ /**
46
+ * a boolean indicating if clicking anywhere on the node should act as clicking on the checkbox. Defaults to `true`.
47
+ * @name $.jstree.defaults.checkbox.whole_node
48
+ * @plugin checkbox
49
+ */
50
+ whole_node : true,
51
+ /**
52
+ * a boolean indicating if the selected style of a node should be kept, or removed. Defaults to `true`.
53
+ * @name $.jstree.defaults.checkbox.keep_selected_style
54
+ * @plugin checkbox
55
+ */
56
+ keep_selected_style : true,
57
+ /**
58
+ * This setting controls how cascading and undetermined nodes are applied.
59
+ * If 'up' is in the string - cascading up is enabled, if 'down' is in the string - cascading down is enabled, if 'undetermined' is in the string - undetermined nodes will be used.
60
+ * If `three_state` is set to `true` this setting is automatically set to 'up+down+undetermined'. Defaults to ''.
61
+ * @name $.jstree.defaults.checkbox.cascade
62
+ * @plugin checkbox
63
+ */
64
+ cascade : '',
65
+ /**
66
+ * This setting controls if checkbox are bound to the general tree selection or to an internal array maintained by the checkbox plugin. Defaults to `true`, only set to `false` if you know exactly what you are doing.
67
+ * @name $.jstree.defaults.checkbox.tie_selection
68
+ * @plugin checkbox
69
+ */
70
+ tie_selection : true,
71
+
72
+ /**
73
+ * This setting controls if cascading down affects disabled checkboxes
74
+ * @name $.jstree.defaults.checkbox.cascade_to_disabled
75
+ * @plugin checkbox
76
+ */
77
+ cascade_to_disabled : true,
78
+
79
+ /**
80
+ * This setting controls if cascading down affects hidden checkboxes
81
+ * @name $.jstree.defaults.checkbox.cascade_to_hidden
82
+ * @plugin checkbox
83
+ */
84
+ cascade_to_hidden : true
85
+ };
86
+ $.jstree.plugins.checkbox = function (options, parent) {
87
+ this.bind = function () {
88
+ parent.bind.call(this);
89
+ this._data.checkbox.uto = false;
90
+ this._data.checkbox.selected = [];
91
+ if(this.settings.checkbox.three_state) {
92
+ this.settings.checkbox.cascade = 'up+down+undetermined';
93
+ }
94
+ this.element
95
+ .on("init.jstree", $.proxy(function () {
96
+ this._data.checkbox.visible = this.settings.checkbox.visible;
97
+ if(!this.settings.checkbox.keep_selected_style) {
98
+ this.element.addClass('jstree-checkbox-no-clicked');
99
+ }
100
+ if(this.settings.checkbox.tie_selection) {
101
+ this.element.addClass('jstree-checkbox-selection');
102
+ }
103
+ }, this))
104
+ .on("loading.jstree", $.proxy(function () {
105
+ this[ this._data.checkbox.visible ? 'show_checkboxes' : 'hide_checkboxes' ]();
106
+ }, this));
107
+ if(this.settings.checkbox.cascade.indexOf('undetermined') !== -1) {
108
+ this.element
109
+ .on('changed.jstree uncheck_node.jstree check_node.jstree uncheck_all.jstree check_all.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree', $.proxy(function () {
110
+ // only if undetermined is in setting
111
+ if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); }
112
+ this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50);
113
+ }, this));
114
+ }
115
+ if(!this.settings.checkbox.tie_selection) {
116
+ this.element
117
+ .on('model.jstree', $.proxy(function (e, data) {
118
+ var m = this._model.data,
119
+ p = m[data.parent],
120
+ dpc = data.nodes,
121
+ i, j;
122
+ for(i = 0, j = dpc.length; i < j; i++) {
123
+ 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);
124
+ if(m[dpc[i]].state.checked) {
125
+ this._data.checkbox.selected.push(dpc[i]);
126
+ }
127
+ }
128
+ }, this));
129
+ }
130
+ if(this.settings.checkbox.cascade.indexOf('up') !== -1 || this.settings.checkbox.cascade.indexOf('down') !== -1) {
131
+ this.element
132
+ .on('model.jstree', $.proxy(function (e, data) {
133
+ var m = this._model.data,
134
+ p = m[data.parent],
135
+ dpc = data.nodes,
136
+ chd = [],
137
+ c, i, j, k, l, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection;
138
+
139
+ if(s.indexOf('down') !== -1) {
140
+ // apply down
141
+ if(p.state[ t ? 'selected' : 'checked' ]) {
142
+ for(i = 0, j = dpc.length; i < j; i++) {
143
+ m[dpc[i]].state[ t ? 'selected' : 'checked' ] = true;
144
+ }
145
+
146
+ this._data[ t ? 'core' : 'checkbox' ].selected = this._data[ t ? 'core' : 'checkbox' ].selected.concat(dpc);
147
+ }
148
+ else {
149
+ for(i = 0, j = dpc.length; i < j; i++) {
150
+ if(m[dpc[i]].state[ t ? 'selected' : 'checked' ]) {
151
+ for(k = 0, l = m[dpc[i]].children_d.length; k < l; k++) {
152
+ m[m[dpc[i]].children_d[k]].state[ t ? 'selected' : 'checked' ] = true;
153
+ }
154
+ this._data[ t ? 'core' : 'checkbox' ].selected = this._data[ t ? 'core' : 'checkbox' ].selected.concat(m[dpc[i]].children_d);
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ if(s.indexOf('up') !== -1) {
161
+ // apply up
162
+ for(i = 0, j = p.children_d.length; i < j; i++) {
163
+ if(!m[p.children_d[i]].children.length) {
164
+ chd.push(m[p.children_d[i]].parent);
165
+ }
166
+ }
167
+ chd = $.vakata.array_unique(chd);
168
+ for(k = 0, l = chd.length; k < l; k++) {
169
+ p = m[chd[k]];
170
+ while(p && p.id !== $.jstree.root) {
171
+ c = 0;
172
+ for(i = 0, j = p.children.length; i < j; i++) {
173
+ c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
174
+ }
175
+ if(c === j) {
176
+ p.state[ t ? 'selected' : 'checked' ] = true;
177
+ this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
178
+ tmp = this.get_node(p, true);
179
+ if(tmp && tmp.length) {
180
+ tmp.attr('aria-selected', true).children('.jstree-anchor').addClass( t ? 'jstree-clicked' : 'jstree-checked');
181
+ }
182
+ }
183
+ else {
184
+ break;
185
+ }
186
+ p = this.get_node(p.parent);
187
+ }
188
+ }
189
+ }
190
+
191
+ this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected);
192
+ }, this))
193
+ .on(this.settings.checkbox.tie_selection ? 'select_node.jstree' : 'check_node.jstree', $.proxy(function (e, data) {
194
+ var self = this,
195
+ obj = data.node,
196
+ m = this._model.data,
197
+ par = this.get_node(obj.parent),
198
+ i, j, c, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection,
199
+ sel = {}, cur = this._data[ t ? 'core' : 'checkbox' ].selected;
200
+
201
+ for (i = 0, j = cur.length; i < j; i++) {
202
+ sel[cur[i]] = true;
203
+ }
204
+
205
+ // apply down
206
+ if(s.indexOf('down') !== -1) {
207
+ //this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected.concat(obj.children_d));
208
+ var selectedIds = this._cascade_new_checked_state(obj.id, true);
209
+ var temp = obj.children_d.concat(obj.id);
210
+ for (i = 0, j = temp.length; i < j; i++) {
211
+ if (selectedIds.indexOf(temp[i]) > -1) {
212
+ sel[temp[i]] = true;
213
+ }
214
+ else {
215
+ delete sel[temp[i]];
216
+ }
217
+ }
218
+ }
219
+
220
+ // apply up
221
+ if(s.indexOf('up') !== -1) {
222
+ while(par && par.id !== $.jstree.root) {
223
+ c = 0;
224
+ for(i = 0, j = par.children.length; i < j; i++) {
225
+ c += m[par.children[i]].state[ t ? 'selected' : 'checked' ];
226
+ }
227
+ if(c === j) {
228
+ par.state[ t ? 'selected' : 'checked' ] = true;
229
+ sel[par.id] = true;
230
+ //this._data[ t ? 'core' : 'checkbox' ].selected.push(par.id);
231
+ tmp = this.get_node(par, true);
232
+ if(tmp && tmp.length) {
233
+ tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
234
+ }
235
+ }
236
+ else {
237
+ break;
238
+ }
239
+ par = this.get_node(par.parent);
240
+ }
241
+ }
242
+
243
+ cur = [];
244
+ for (i in sel) {
245
+ if (sel.hasOwnProperty(i)) {
246
+ cur.push(i);
247
+ }
248
+ }
249
+ this._data[ t ? 'core' : 'checkbox' ].selected = cur;
250
+ }, this))
251
+ .on(this.settings.checkbox.tie_selection ? 'deselect_all.jstree' : 'uncheck_all.jstree', $.proxy(function (e, data) {
252
+ var obj = this.get_node($.jstree.root),
253
+ m = this._model.data,
254
+ i, j, tmp;
255
+ for(i = 0, j = obj.children_d.length; i < j; i++) {
256
+ tmp = m[obj.children_d[i]];
257
+ if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) {
258
+ tmp.original.state.undetermined = false;
259
+ }
260
+ }
261
+ }, this))
262
+ .on(this.settings.checkbox.tie_selection ? 'deselect_node.jstree' : 'uncheck_node.jstree', $.proxy(function (e, data) {
263
+ var self = this,
264
+ obj = data.node,
265
+ dom = this.get_node(obj, true),
266
+ i, j, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection,
267
+ cur = this._data[ t ? 'core' : 'checkbox' ].selected, sel = {},
268
+ stillSelectedIds = [],
269
+ allIds = obj.children_d.concat(obj.id);
270
+
271
+ // apply down
272
+ if(s.indexOf('down') !== -1) {
273
+ var selectedIds = this._cascade_new_checked_state(obj.id, false);
274
+
275
+ cur = $.vakata.array_filter(cur, function(id) {
276
+ return allIds.indexOf(id) === -1 || selectedIds.indexOf(id) > -1;
277
+ });
278
+ }
279
+
280
+ // only apply up if cascade up is enabled and if this node is not selected
281
+ // (if all child nodes are disabled and cascade_to_disabled === false then this node will till be selected).
282
+ if(s.indexOf('up') !== -1 && cur.indexOf(obj.id) === -1) {
283
+ for(i = 0, j = obj.parents.length; i < j; i++) {
284
+ tmp = this._model.data[obj.parents[i]];
285
+ tmp.state[ t ? 'selected' : 'checked' ] = false;
286
+ if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) {
287
+ tmp.original.state.undetermined = false;
288
+ }
289
+ tmp = this.get_node(obj.parents[i], true);
290
+ if(tmp && tmp.length) {
291
+ tmp.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
292
+ }
293
+ }
294
+
295
+ cur = $.vakata.array_filter(cur, function(id) {
296
+ return obj.parents.indexOf(id) === -1;
297
+ });
298
+ }
299
+
300
+ this._data[ t ? 'core' : 'checkbox' ].selected = cur;
301
+ }, this));
302
+ }
303
+ if(this.settings.checkbox.cascade.indexOf('up') !== -1) {
304
+ this.element
305
+ .on('delete_node.jstree', $.proxy(function (e, data) {
306
+ // apply up (whole handler)
307
+ var p = this.get_node(data.parent),
308
+ m = this._model.data,
309
+ i, j, c, tmp, t = this.settings.checkbox.tie_selection;
310
+ while(p && p.id !== $.jstree.root && !p.state[ t ? 'selected' : 'checked' ]) {
311
+ c = 0;
312
+ for(i = 0, j = p.children.length; i < j; i++) {
313
+ c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
314
+ }
315
+ if(j > 0 && c === j) {
316
+ p.state[ t ? 'selected' : 'checked' ] = true;
317
+ this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
318
+ tmp = this.get_node(p, true);
319
+ if(tmp && tmp.length) {
320
+ tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
321
+ }
322
+ }
323
+ else {
324
+ break;
325
+ }
326
+ p = this.get_node(p.parent);
327
+ }
328
+ }, this))
329
+ .on('move_node.jstree', $.proxy(function (e, data) {
330
+ // apply up (whole handler)
331
+ var is_multi = data.is_multi,
332
+ old_par = data.old_parent,
333
+ new_par = this.get_node(data.parent),
334
+ m = this._model.data,
335
+ p, c, i, j, tmp, t = this.settings.checkbox.tie_selection;
336
+ if(!is_multi) {
337
+ p = this.get_node(old_par);
338
+ while(p && p.id !== $.jstree.root && !p.state[ t ? 'selected' : 'checked' ]) {
339
+ c = 0;
340
+ for(i = 0, j = p.children.length; i < j; i++) {
341
+ c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
342
+ }
343
+ if(j > 0 && c === j) {
344
+ p.state[ t ? 'selected' : 'checked' ] = true;
345
+ this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
346
+ tmp = this.get_node(p, true);
347
+ if(tmp && tmp.length) {
348
+ tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
349
+ }
350
+ }
351
+ else {
352
+ break;
353
+ }
354
+ p = this.get_node(p.parent);
355
+ }
356
+ }
357
+ p = new_par;
358
+ while(p && p.id !== $.jstree.root) {
359
+ c = 0;
360
+ for(i = 0, j = p.children.length; i < j; i++) {
361
+ c += m[p.children[i]].state[ t ? 'selected' : 'checked' ];
362
+ }
363
+ if(c === j) {
364
+ if(!p.state[ t ? 'selected' : 'checked' ]) {
365
+ p.state[ t ? 'selected' : 'checked' ] = true;
366
+ this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
367
+ tmp = this.get_node(p, true);
368
+ if(tmp && tmp.length) {
369
+ tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
370
+ }
371
+ }
372
+ }
373
+ else {
374
+ if(p.state[ t ? 'selected' : 'checked' ]) {
375
+ p.state[ t ? 'selected' : 'checked' ] = false;
376
+ this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_remove_item(this._data[ t ? 'core' : 'checkbox' ].selected, p.id);
377
+ tmp = this.get_node(p, true);
378
+ if(tmp && tmp.length) {
379
+ tmp.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
380
+ }
381
+ }
382
+ else {
383
+ break;
384
+ }
385
+ }
386
+ p = this.get_node(p.parent);
387
+ }
388
+ }, this));
389
+ }
390
+ };
391
+ /**
392
+ * get an array of all nodes whose state is "undetermined"
393
+ * @name get_undetermined([full])
394
+ * @param {boolean} full: if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
395
+ * @return {Array}
396
+ * @plugin checkbox
397
+ */
398
+ this.get_undetermined = function (full) {
399
+ if (this.settings.checkbox.cascade.indexOf('undetermined') === -1) {
400
+ return [];
401
+ }
402
+ 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, r = [];
403
+ for(i = 0, j = s.length; i < j; i++) {
404
+ if(m[s[i]] && m[s[i]].parents) {
405
+ for(k = 0, l = m[s[i]].parents.length; k < l; k++) {
406
+ if(o[m[s[i]].parents[k]] !== undefined) {
407
+ break;
408
+ }
409
+ if(m[s[i]].parents[k] !== $.jstree.root) {
410
+ o[m[s[i]].parents[k]] = true;
411
+ p.push(m[s[i]].parents[k]);
412
+ }
413
+ }
414
+ }
415
+ }
416
+ // attempt for server side undetermined state
417
+ this.element.find('.jstree-closed').not(':has(.jstree-children)')
418
+ .each(function () {
419
+ var tmp = tt.get_node(this), tmp2;
420
+
421
+ if(!tmp) { return; }
422
+
423
+ if(!tmp.state.loaded) {
424
+ if(tmp.original && tmp.original.state && tmp.original.state.undetermined && tmp.original.state.undetermined === true) {
425
+ if(o[tmp.id] === undefined && tmp.id !== $.jstree.root) {
426
+ o[tmp.id] = true;
427
+ p.push(tmp.id);
428
+ }
429
+ for(k = 0, l = tmp.parents.length; k < l; k++) {
430
+ if(o[tmp.parents[k]] === undefined && tmp.parents[k] !== $.jstree.root) {
431
+ o[tmp.parents[k]] = true;
432
+ p.push(tmp.parents[k]);
433
+ }
434
+ }
435
+ }
436
+ }
437
+ else {
438
+ for(i = 0, j = tmp.children_d.length; i < j; i++) {
439
+ tmp2 = m[tmp.children_d[i]];
440
+ if(!tmp2.state.loaded && tmp2.original && tmp2.original.state && tmp2.original.state.undetermined && tmp2.original.state.undetermined === true) {
441
+ if(o[tmp2.id] === undefined && tmp2.id !== $.jstree.root) {
442
+ o[tmp2.id] = true;
443
+ p.push(tmp2.id);
444
+ }
445
+ for(k = 0, l = tmp2.parents.length; k < l; k++) {
446
+ if(o[tmp2.parents[k]] === undefined && tmp2.parents[k] !== $.jstree.root) {
447
+ o[tmp2.parents[k]] = true;
448
+ p.push(tmp2.parents[k]);
449
+ }
450
+ }
451
+ }
452
+ }
453
+ }
454
+ });
455
+ for (i = 0, j = p.length; i < j; i++) {
456
+ if(!m[p[i]].state[ t ? 'selected' : 'checked' ]) {
457
+ r.push(full ? m[p[i]] : p[i]);
458
+ }
459
+ }
460
+ return r;
461
+ };
462
+ /**
463
+ * set the undetermined state where and if necessary. Used internally.
464
+ * @private
465
+ * @name _undetermined()
466
+ * @plugin checkbox
467
+ */
468
+ this._undetermined = function () {
469
+ if(this.element === null) { return; }
470
+ var p = this.get_undetermined(false), i, j, s;
471
+
472
+ this.element.find('.jstree-undetermined').removeClass('jstree-undetermined');
473
+ for (i = 0, j = p.length; i < j; i++) {
474
+ s = this.get_node(p[i], true);
475
+ if(s && s.length) {
476
+ s.children('.jstree-anchor').children('.jstree-checkbox').addClass('jstree-undetermined');
477
+ }
478
+ }
479
+ };
480
+ this.redraw_node = function(obj, deep, is_callback, force_render) {
481
+ obj = parent.redraw_node.apply(this, arguments);
482
+ if(obj) {
483
+ var i, j, tmp = null, icon = null;
484
+ for(i = 0, j = obj.childNodes.length; i < j; i++) {
485
+ if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) {
486
+ tmp = obj.childNodes[i];
487
+ break;
488
+ }
489
+ }
490
+ if(tmp) {
491
+ if(!this.settings.checkbox.tie_selection && this._model.data[obj.id].state.checked) { tmp.className += ' jstree-checked'; }
492
+ icon = _i.cloneNode(false);
493
+ if(this._model.data[obj.id].state.checkbox_disabled) { icon.className += ' jstree-checkbox-disabled'; }
494
+ tmp.insertBefore(icon, tmp.childNodes[0]);
495
+ }
496
+ }
497
+ if(!is_callback && this.settings.checkbox.cascade.indexOf('undetermined') !== -1) {
498
+ if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); }
499
+ this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50);
500
+ }
501
+ return obj;
502
+ };
503
+ /**
504
+ * show the node checkbox icons
505
+ * @name show_checkboxes()
506
+ * @plugin checkbox
507
+ */
508
+ this.show_checkboxes = function () { this._data.core.themes.checkboxes = true; this.get_container_ul().removeClass("jstree-no-checkboxes"); };
509
+ /**
510
+ * hide the node checkbox icons
511
+ * @name hide_checkboxes()
512
+ * @plugin checkbox
513
+ */
514
+ this.hide_checkboxes = function () { this._data.core.themes.checkboxes = false; this.get_container_ul().addClass("jstree-no-checkboxes"); };
515
+ /**
516
+ * toggle the node icons
517
+ * @name toggle_checkboxes()
518
+ * @plugin checkbox
519
+ */
520
+ this.toggle_checkboxes = function () { if(this._data.core.themes.checkboxes) { this.hide_checkboxes(); } else { this.show_checkboxes(); } };
521
+ /**
522
+ * checks if a node is in an undetermined state
523
+ * @name is_undetermined(obj)
524
+ * @param {mixed} obj
525
+ * @return {Boolean}
526
+ */
527
+ this.is_undetermined = function (obj) {
528
+ obj = this.get_node(obj);
529
+ var s = this.settings.checkbox.cascade, i, j, t = this.settings.checkbox.tie_selection, d = this._data[ t ? 'core' : 'checkbox' ].selected, m = this._model.data;
530
+ if(!obj || obj.state[ t ? 'selected' : 'checked' ] === true || s.indexOf('undetermined') === -1 || (s.indexOf('down') === -1 && s.indexOf('up') === -1)) {
531
+ return false;
532
+ }
533
+ if(!obj.state.loaded && obj.original.state.undetermined === true) {
534
+ return true;
535
+ }
536
+ for(i = 0, j = obj.children_d.length; i < j; i++) {
537
+ if($.inArray(obj.children_d[i], d) !== -1 || (!m[obj.children_d[i]].state.loaded && m[obj.children_d[i]].original.state.undetermined)) {
538
+ return true;
539
+ }
540
+ }
541
+ return false;
542
+ };
543
+ /**
544
+ * disable a node's checkbox
545
+ * @name disable_checkbox(obj)
546
+ * @param {mixed} obj an array can be used too
547
+ * @trigger disable_checkbox.jstree
548
+ * @plugin checkbox
549
+ */
550
+ this.disable_checkbox = function (obj) {
551
+ var t1, t2, dom;
552
+ if($.isArray(obj)) {
553
+ obj = obj.slice();
554
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
555
+ this.disable_checkbox(obj[t1]);
556
+ }
557
+ return true;
558
+ }
559
+ obj = this.get_node(obj);
560
+ if(!obj || obj.id === $.jstree.root) {
561
+ return false;
562
+ }
563
+ dom = this.get_node(obj, true);
564
+ if(!obj.state.checkbox_disabled) {
565
+ obj.state.checkbox_disabled = true;
566
+ if(dom && dom.length) {
567
+ dom.children('.jstree-anchor').children('.jstree-checkbox').addClass('jstree-checkbox-disabled');
568
+ }
569
+ /**
570
+ * triggered when an node's checkbox is disabled
571
+ * @event
572
+ * @name disable_checkbox.jstree
573
+ * @param {Object} node
574
+ * @plugin checkbox
575
+ */
576
+ this.trigger('disable_checkbox', { 'node' : obj });
577
+ }
578
+ };
579
+ /**
580
+ * enable a node's checkbox
581
+ * @name enable_checkbox(obj)
582
+ * @param {mixed} obj an array can be used too
583
+ * @trigger enable_checkbox.jstree
584
+ * @plugin checkbox
585
+ */
586
+ this.enable_checkbox = function (obj) {
587
+ var t1, t2, dom;
588
+ if($.isArray(obj)) {
589
+ obj = obj.slice();
590
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
591
+ this.enable_checkbox(obj[t1]);
592
+ }
593
+ return true;
594
+ }
595
+ obj = this.get_node(obj);
596
+ if(!obj || obj.id === $.jstree.root) {
597
+ return false;
598
+ }
599
+ dom = this.get_node(obj, true);
600
+ if(obj.state.checkbox_disabled) {
601
+ obj.state.checkbox_disabled = false;
602
+ if(dom && dom.length) {
603
+ dom.children('.jstree-anchor').children('.jstree-checkbox').removeClass('jstree-checkbox-disabled');
604
+ }
605
+ /**
606
+ * triggered when an node's checkbox is enabled
607
+ * @event
608
+ * @name enable_checkbox.jstree
609
+ * @param {Object} node
610
+ * @plugin checkbox
611
+ */
612
+ this.trigger('enable_checkbox', { 'node' : obj });
613
+ }
614
+ };
615
+
616
+ this.activate_node = function (obj, e) {
617
+ if($(e.target).hasClass('jstree-checkbox-disabled')) {
618
+ return false;
619
+ }
620
+ if(this.settings.checkbox.tie_selection && (this.settings.checkbox.whole_node || $(e.target).hasClass('jstree-checkbox'))) {
621
+ e.ctrlKey = true;
622
+ }
623
+ if(this.settings.checkbox.tie_selection || (!this.settings.checkbox.whole_node && !$(e.target).hasClass('jstree-checkbox'))) {
624
+ return parent.activate_node.call(this, obj, e);
625
+ }
626
+ if(this.is_disabled(obj)) {
627
+ return false;
628
+ }
629
+ if(this.is_checked(obj)) {
630
+ this.uncheck_node(obj, e);
631
+ }
632
+ else {
633
+ this.check_node(obj, e);
634
+ }
635
+ this.trigger('activate_node', { 'node' : this.get_node(obj) });
636
+ };
637
+
638
+ /**
639
+ * Cascades checked state to a node and all its descendants. This function does NOT affect hidden and disabled nodes (or their descendants).
640
+ * However if these unaffected nodes are already selected their ids will be included in the returned array.
641
+ * @private
642
+ * @param {string} id the node ID
643
+ * @param {bool} checkedState should the nodes be checked or not
644
+ * @returns {Array} Array of all node id's (in this tree branch) that are checked.
645
+ */
646
+ this._cascade_new_checked_state = function (id, checkedState) {
647
+ var self = this;
648
+ var t = this.settings.checkbox.tie_selection;
649
+ var node = this._model.data[id];
650
+ var selectedNodeIds = [];
651
+ var selectedChildrenIds = [], i, j, selectedChildIds;
652
+
653
+ if (
654
+ (this.settings.checkbox.cascade_to_disabled || !node.state.disabled) &&
655
+ (this.settings.checkbox.cascade_to_hidden || !node.state.hidden)
656
+ ) {
657
+ //First try and check/uncheck the children
658
+ if (node.children) {
659
+ for (i = 0, j = node.children.length; i < j; i++) {
660
+ var childId = node.children[i];
661
+ selectedChildIds = self._cascade_new_checked_state(childId, checkedState);
662
+ selectedNodeIds = selectedNodeIds.concat(selectedChildIds);
663
+ if (selectedChildIds.indexOf(childId) > -1) {
664
+ selectedChildrenIds.push(childId);
665
+ }
666
+ }
667
+ }
668
+
669
+ var dom = self.get_node(node, true);
670
+
671
+ //A node's state is undetermined if some but not all of it's children are checked/selected .
672
+ var undetermined = selectedChildrenIds.length > 0 && selectedChildrenIds.length < node.children.length;
673
+
674
+ if(node.original && node.original.state && node.original.state.undetermined) {
675
+ node.original.state.undetermined = undetermined;
676
+ }
677
+
678
+ //If a node is undetermined then remove selected class
679
+ if (undetermined) {
680
+ node.state[ t ? 'selected' : 'checked' ] = false;
681
+ dom.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
682
+ }
683
+ //Otherwise, if the checkedState === true (i.e. the node is being checked now) and all of the node's children are checked (if it has any children),
684
+ //check the node and style it correctly.
685
+ else if (checkedState && selectedChildrenIds.length === node.children.length) {
686
+ node.state[ t ? 'selected' : 'checked' ] = checkedState;
687
+ selectedNodeIds.push(node.id);
688
+
689
+ dom.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
690
+ }
691
+ else {
692
+ node.state[ t ? 'selected' : 'checked' ] = false;
693
+ dom.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
694
+ }
695
+ }
696
+ else {
697
+ selectedChildIds = this.get_checked_descendants(id);
698
+
699
+ if (node.state[ t ? 'selected' : 'checked' ]) {
700
+ selectedChildIds.push(node.id);
701
+ }
702
+
703
+ selectedNodeIds = selectedNodeIds.concat(selectedChildIds);
704
+ }
705
+
706
+ return selectedNodeIds;
707
+ };
708
+
709
+ /**
710
+ * Gets ids of nodes selected in branch (of tree) specified by id (does not include the node specified by id)
711
+ * @name get_checked_descendants(obj)
712
+ * @param {string} id the node ID
713
+ * @return {Array} array of IDs
714
+ * @plugin checkbox
715
+ */
716
+ this.get_checked_descendants = function (id) {
717
+ var self = this;
718
+ var t = self.settings.checkbox.tie_selection;
719
+ var node = self._model.data[id];
720
+
721
+ return $.vakata.array_filter(node.children_d, function(_id) {
722
+ return self._model.data[_id].state[ t ? 'selected' : 'checked' ];
723
+ });
724
+ };
725
+
726
+ /**
727
+ * check a node (only if tie_selection in checkbox settings is false, otherwise select_node will be called internally)
728
+ * @name check_node(obj)
729
+ * @param {mixed} obj an array can be used to check multiple nodes
730
+ * @trigger check_node.jstree
731
+ * @plugin checkbox
732
+ */
733
+ this.check_node = function (obj, e) {
734
+ if(this.settings.checkbox.tie_selection) { return this.select_node(obj, false, true, e); }
735
+ var dom, t1, t2, th;
736
+ if($.isArray(obj)) {
737
+ obj = obj.slice();
738
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
739
+ this.check_node(obj[t1], e);
740
+ }
741
+ return true;
742
+ }
743
+ obj = this.get_node(obj);
744
+ if(!obj || obj.id === $.jstree.root) {
745
+ return false;
746
+ }
747
+ dom = this.get_node(obj, true);
748
+ if(!obj.state.checked) {
749
+ obj.state.checked = true;
750
+ this._data.checkbox.selected.push(obj.id);
751
+ if(dom && dom.length) {
752
+ dom.children('.jstree-anchor').addClass('jstree-checked');
753
+ }
754
+ /**
755
+ * triggered when an node is checked (only if tie_selection in checkbox settings is false)
756
+ * @event
757
+ * @name check_node.jstree
758
+ * @param {Object} node
759
+ * @param {Array} selected the current selection
760
+ * @param {Object} event the event (if any) that triggered this check_node
761
+ * @plugin checkbox
762
+ */
763
+ this.trigger('check_node', { 'node' : obj, 'selected' : this._data.checkbox.selected, 'event' : e });
764
+ }
765
+ };
766
+ /**
767
+ * uncheck a node (only if tie_selection in checkbox settings is false, otherwise deselect_node will be called internally)
768
+ * @name uncheck_node(obj)
769
+ * @param {mixed} obj an array can be used to uncheck multiple nodes
770
+ * @trigger uncheck_node.jstree
771
+ * @plugin checkbox
772
+ */
773
+ this.uncheck_node = function (obj, e) {
774
+ if(this.settings.checkbox.tie_selection) { return this.deselect_node(obj, false, e); }
775
+ var t1, t2, dom;
776
+ if($.isArray(obj)) {
777
+ obj = obj.slice();
778
+ for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
779
+ this.uncheck_node(obj[t1], e);
780
+ }
781
+ return true;
782
+ }
783
+ obj = this.get_node(obj);
784
+ if(!obj || obj.id === $.jstree.root) {
785
+ return false;
786
+ }
787
+ dom = this.get_node(obj, true);
788
+ if(obj.state.checked) {
789
+ obj.state.checked = false;
790
+ this._data.checkbox.selected = $.vakata.array_remove_item(this._data.checkbox.selected, obj.id);
791
+ if(dom.length) {
792
+ dom.children('.jstree-anchor').removeClass('jstree-checked');
793
+ }
794
+ /**
795
+ * triggered when an node is unchecked (only if tie_selection in checkbox settings is false)
796
+ * @event
797
+ * @name uncheck_node.jstree
798
+ * @param {Object} node
799
+ * @param {Array} selected the current selection
800
+ * @param {Object} event the event (if any) that triggered this uncheck_node
801
+ * @plugin checkbox
802
+ */
803
+ this.trigger('uncheck_node', { 'node' : obj, 'selected' : this._data.checkbox.selected, 'event' : e });
804
+ }
805
+ };
806
+
807
+ /**
808
+ * checks all nodes in the tree (only if tie_selection in checkbox settings is false, otherwise select_all will be called internally)
809
+ * @name check_all()
810
+ * @trigger check_all.jstree, changed.jstree
811
+ * @plugin checkbox
812
+ */
813
+ this.check_all = function () {
814
+ if(this.settings.checkbox.tie_selection) { return this.select_all(); }
815
+ var tmp = this._data.checkbox.selected.concat([]), i, j;
816
+ this._data.checkbox.selected = this._model.data[$.jstree.root].children_d.concat();
817
+ for(i = 0, j = this._data.checkbox.selected.length; i < j; i++) {
818
+ if(this._model.data[this._data.checkbox.selected[i]]) {
819
+ this._model.data[this._data.checkbox.selected[i]].state.checked = true;
820
+ }
821
+ }
822
+ this.redraw(true);
823
+ /**
824
+ * triggered when all nodes are checked (only if tie_selection in checkbox settings is false)
825
+ * @event
826
+ * @name check_all.jstree
827
+ * @param {Array} selected the current selection
828
+ * @plugin checkbox
829
+ */
830
+ this.trigger('check_all', { 'selected' : this._data.checkbox.selected });
831
+ };
832
+ /**
833
+ * uncheck all checked nodes (only if tie_selection in checkbox settings is false, otherwise deselect_all will be called internally)
834
+ * @name uncheck_all()
835
+ * @trigger uncheck_all.jstree
836
+ * @plugin checkbox
837
+ */
838
+ this.uncheck_all = function () {
839
+ if(this.settings.checkbox.tie_selection) { return this.deselect_all(); }
840
+ var tmp = this._data.checkbox.selected.concat([]), i, j;
841
+ for(i = 0, j = this._data.checkbox.selected.length; i < j; i++) {
842
+ if(this._model.data[this._data.checkbox.selected[i]]) {
843
+ this._model.data[this._data.checkbox.selected[i]].state.checked = false;
844
+ }
845
+ }
846
+ this._data.checkbox.selected = [];
847
+ this.element.find('.jstree-checked').removeClass('jstree-checked');
848
+ /**
849
+ * triggered when all nodes are unchecked (only if tie_selection in checkbox settings is false)
850
+ * @event
851
+ * @name uncheck_all.jstree
852
+ * @param {Object} node the previous selection
853
+ * @param {Array} selected the current selection
854
+ * @plugin checkbox
855
+ */
856
+ this.trigger('uncheck_all', { 'selected' : this._data.checkbox.selected, 'node' : tmp });
857
+ };
858
+ /**
859
+ * checks if a node is checked (if tie_selection is on in the settings this function will return the same as is_selected)
860
+ * @name is_checked(obj)
861
+ * @param {mixed} obj
862
+ * @return {Boolean}
863
+ * @plugin checkbox
864
+ */
865
+ this.is_checked = function (obj) {
866
+ if(this.settings.checkbox.tie_selection) { return this.is_selected(obj); }
867
+ obj = this.get_node(obj);
868
+ if(!obj || obj.id === $.jstree.root) { return false; }
869
+ return obj.state.checked;
870
+ };
871
+ /**
872
+ * get an array of all checked nodes (if tie_selection is on in the settings this function will return the same as get_selected)
873
+ * @name get_checked([full])
874
+ * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
875
+ * @return {Array}
876
+ * @plugin checkbox
877
+ */
878
+ this.get_checked = function (full) {
879
+ if(this.settings.checkbox.tie_selection) { return this.get_selected(full); }
880
+ return full ? $.map(this._data.checkbox.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.checkbox.selected.slice();
881
+ };
882
+ /**
883
+ * get an array of all top level checked nodes (ignoring children of checked nodes) (if tie_selection is on in the settings this function will return the same as get_top_selected)
884
+ * @name get_top_checked([full])
885
+ * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
886
+ * @return {Array}
887
+ * @plugin checkbox
888
+ */
889
+ this.get_top_checked = function (full) {
890
+ if(this.settings.checkbox.tie_selection) { return this.get_top_selected(full); }
891
+ var tmp = this.get_checked(true),
892
+ obj = {}, i, j, k, l;
893
+ for(i = 0, j = tmp.length; i < j; i++) {
894
+ obj[tmp[i].id] = tmp[i];
895
+ }
896
+ for(i = 0, j = tmp.length; i < j; i++) {
897
+ for(k = 0, l = tmp[i].children_d.length; k < l; k++) {
898
+ if(obj[tmp[i].children_d[k]]) {
899
+ delete obj[tmp[i].children_d[k]];
900
+ }
901
+ }
902
+ }
903
+ tmp = [];
904
+ for(i in obj) {
905
+ if(obj.hasOwnProperty(i)) {
906
+ tmp.push(i);
907
+ }
908
+ }
909
+ return full ? $.map(tmp, $.proxy(function (i) { return this.get_node(i); }, this)) : tmp;
910
+ };
911
+ /**
912
+ * get an array of all bottom level checked nodes (ignoring selected parents) (if tie_selection is on in the settings this function will return the same as get_bottom_selected)
913
+ * @name get_bottom_checked([full])
914
+ * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned
915
+ * @return {Array}
916
+ * @plugin checkbox
917
+ */
918
+ this.get_bottom_checked = function (full) {
919
+ if(this.settings.checkbox.tie_selection) { return this.get_bottom_selected(full); }
920
+ var tmp = this.get_checked(true),
921
+ obj = [], i, j;
922
+ for(i = 0, j = tmp.length; i < j; i++) {
923
+ if(!tmp[i].children.length) {
924
+ obj.push(tmp[i].id);
925
+ }
926
+ }
927
+ return full ? $.map(obj, $.proxy(function (i) { return this.get_node(i); }, this)) : obj;
928
+ };
929
+ this.load_node = function (obj, callback) {
930
+ var k, l, i, j, c, tmp;
931
+ if(!$.isArray(obj) && !this.settings.checkbox.tie_selection) {
932
+ tmp = this.get_node(obj);
933
+ if(tmp && tmp.state.loaded) {
934
+ for(k = 0, l = tmp.children_d.length; k < l; k++) {
935
+ if(this._model.data[tmp.children_d[k]].state.checked) {
936
+ c = true;
937
+ this._data.checkbox.selected = $.vakata.array_remove_item(this._data.checkbox.selected, tmp.children_d[k]);
938
+ }
939
+ }
940
+ }
941
+ }
942
+ return parent.load_node.apply(this, arguments);
943
+ };
944
+ this.get_state = function () {
945
+ var state = parent.get_state.apply(this, arguments);
946
+ if(this.settings.checkbox.tie_selection) { return state; }
947
+ state.checkbox = this._data.checkbox.selected.slice();
948
+ return state;
949
+ };
950
+ this.set_state = function (state, callback) {
951
+ var res = parent.set_state.apply(this, arguments);
952
+ if(res && state.checkbox) {
953
+ if(!this.settings.checkbox.tie_selection) {
954
+ this.uncheck_all();
955
+ var _this = this;
956
+ $.each(state.checkbox, function (i, v) {
957
+ _this.check_node(v);
958
+ });
959
+ }
960
+ delete state.checkbox;
961
+ this.set_state(state, callback);
962
+ return false;
963
+ }
964
+ return res;
965
+ };
966
+ this.refresh = function (skip_loading, forget_state) {
967
+ if(this.settings.checkbox.tie_selection) {
968
+ this._data.checkbox.selected = [];
969
+ }
970
+ return parent.refresh.apply(this, arguments);
971
+ };
972
+ };
973
+
974
+ // include the checkbox plugin by default
975
+ // $.jstree.defaults.plugins.push("checkbox");
976
+ }));