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.
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
+ }));