billy_cms 0.0.15 → 0.0.17

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.
@@ -13,7 +13,7 @@
13
13
  }(function ($, undefined) {
14
14
  "use strict";
15
15
  /*!
16
- * jsTree 3.2.1
16
+ * jsTree 3.3.3
17
17
  * http://jstree.com/
18
18
  *
19
19
  * Copyright (c) 2014 Ivan Bozhanov (http://vakata.com)
@@ -23,8 +23,9 @@
23
23
  */
24
24
  /*!
25
25
  * if using jslint please allow for the jQuery global and use following options:
26
- * jslint: browser: true, ass: true, bitwise: true, continue: true, nomen: true, plusplus: true, regexp: true, unparam: true, todo: true, white: true
26
+ * jslint: loopfunc: true, browser: true, ass: true, bitwise: true, continue: true, nomen: true, plusplus: true, regexp: true, unparam: true, todo: true, white: true
27
27
  */
28
+ /*jshint -W083 */
28
29
 
29
30
  // prevent another load? maybe there is a better way?
30
31
  if($.jstree) {
@@ -35,32 +36,14 @@
35
36
  * ### jsTree core functionality
36
37
  */
37
38
 
38
- // internal variables
39
+ // internal variables
39
40
  var instance_counter = 0,
40
41
  ccp_node = false,
41
42
  ccp_mode = false,
42
43
  ccp_inst = false,
43
44
  themes_loaded = [],
44
45
  src = $('script:last').attr('src'),
45
- document = window.document, // local variable is always faster to access then a global
46
- _node = document.createElement('LI'), _temp1, _temp2;
47
-
48
- _node.setAttribute('role', 'treeitem');
49
- _temp1 = document.createElement('I');
50
- _temp1.className = 'jstree-icon jstree-ocl';
51
- _temp1.setAttribute('role', 'presentation');
52
- _node.appendChild(_temp1);
53
- _temp1 = document.createElement('A');
54
- _temp1.className = 'jstree-anchor';
55
- _temp1.setAttribute('href','#');
56
- _temp1.setAttribute('tabindex','-1');
57
- _temp2 = document.createElement('I');
58
- _temp2.className = 'jstree-icon jstree-themeicon';
59
- _temp2.setAttribute('role', 'presentation');
60
- _temp1.appendChild(_temp2);
61
- _node.appendChild(_temp1);
62
- _temp1 = _temp2 = null;
63
-
46
+ document = window.document; // local variable is always faster to access then a global
64
47
 
65
48
  /**
66
49
  * holds all jstree related functions and variables, including the actual class and methods to create, access and manipulate instances.
@@ -71,7 +54,7 @@
71
54
  * specifies the jstree version in use
72
55
  * @name $.jstree.version
73
56
  */
74
- version : '3.2.1',
57
+ version : '3.3.3',
75
58
  /**
76
59
  * holds all the default options used when creating new instances
77
60
  * @name $.jstree.defaults
@@ -92,6 +75,7 @@
92
75
  idregex : /[\\:&!^|()\[\]<>@*'+~#";.,=\- \/${}%?`]/g,
93
76
  root : '#'
94
77
  };
78
+
95
79
  /**
96
80
  * creates a jstree instance
97
81
  * @name $.jstree.create(el [, options])
@@ -138,7 +122,8 @@
138
122
  themes : {
139
123
  name : false,
140
124
  dots : false,
141
- icons : false
125
+ icons : false,
126
+ ellipsis : false
142
127
  },
143
128
  selected : [],
144
129
  last_error : {},
@@ -260,7 +245,7 @@
260
245
  * @name $(':jstree')
261
246
  * @return {jQuery}
262
247
  */
263
- $.expr[':'].jstree = $.expr.createPseudo(function(search) {
248
+ $.expr.pseudos.jstree = $.expr.createPseudo(function(search) {
264
249
  return function(a) {
265
250
  return $(a).hasClass('jstree') &&
266
251
  $(a).data('jstree') !== undefined;
@@ -309,7 +294,8 @@
309
294
  * 'children' : [ { 'text' : 'Child 1' }, 'Child 2']
310
295
  * }
311
296
  * ]
312
- * });
297
+ * }
298
+ * });
313
299
  *
314
300
  * // function
315
301
  * $('#tree').jstree({
@@ -407,6 +393,11 @@
407
393
  * @name $.jstree.defaults.core.themes.icons
408
394
  */
409
395
  icons : true,
396
+ /**
397
+ * a boolean indicating if node ellipsis should be shown - this only works with a fixed with on the container
398
+ * @name $.jstree.defaults.core.themes.ellipsis
399
+ */
400
+ ellipsis : false,
410
401
  /**
411
402
  * a boolean indicating if the tree background is striped
412
403
  * @name $.jstree.defaults.core.themes.stripes
@@ -519,12 +510,13 @@
519
510
  this._data.core.original_container_html
520
511
  .find("li").addBack()
521
512
  .contents().filter(function() {
522
- return this.nodeType === 3 && (!this.nodeValue || /^\s+$/.test(this.nodeValue));
523
- })
513
+ return this.nodeType === 3 && (!this.nodeValue || /^\s+$/.test(this.nodeValue));
514
+ })
524
515
  .remove();
525
516
  this.element.html("<"+"ul class='jstree-container-ul jstree-children' role='group'><"+"li id='j"+this._id+"_loading' class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='tree-item'><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>");
526
517
  this.element.attr('aria-activedescendant','j' + this._id + '_loading');
527
518
  this._data.core.li_height = this.get_container_ul().children("li").first().height() || 24;
519
+ this._data.core.node = this._create_prototype_node();
528
520
  /**
529
521
  * triggered after the loading text is shown and before loading starts
530
522
  * @event
@@ -549,6 +541,29 @@
549
541
  if(!keep_html) { this.element.empty(); }
550
542
  this.teardown();
551
543
  },
544
+ /**
545
+ * Create prototype node
546
+ */
547
+ _create_prototype_node : function () {
548
+ var _node = document.createElement('LI'), _temp1, _temp2;
549
+ _node.setAttribute('role', 'treeitem');
550
+ _temp1 = document.createElement('I');
551
+ _temp1.className = 'jstree-icon jstree-ocl';
552
+ _temp1.setAttribute('role', 'presentation');
553
+ _node.appendChild(_temp1);
554
+ _temp1 = document.createElement('A');
555
+ _temp1.className = 'jstree-anchor';
556
+ _temp1.setAttribute('href','#');
557
+ _temp1.setAttribute('tabindex','-1');
558
+ _temp2 = document.createElement('I');
559
+ _temp2.className = 'jstree-icon jstree-themeicon';
560
+ _temp2.setAttribute('role', 'presentation');
561
+ _temp1.appendChild(_temp2);
562
+ _node.appendChild(_temp1);
563
+ _temp1 = _temp2 = null;
564
+
565
+ return _node;
566
+ },
552
567
  /**
553
568
  * part of the destroying of an instance. Used internally.
554
569
  * @private
@@ -631,7 +646,7 @@
631
646
  e.type = "click";
632
647
  $(e.currentTarget).trigger(e);
633
648
  break;
634
- case 37: // right
649
+ case 37: // left
635
650
  e.preventDefault();
636
651
  if(this.is_open(e.currentTarget)) {
637
652
  this.close_node(e.currentTarget);
@@ -646,7 +661,7 @@
646
661
  o = this.get_prev_dom(e.currentTarget);
647
662
  if(o && o.length) { o.children('.jstree-anchor').focus(); }
648
663
  break;
649
- case 39: // left
664
+ case 39: // right
650
665
  e.preventDefault();
651
666
  if(this.is_closed(e.currentTarget)) {
652
667
  this.open_node(e.currentTarget, function (o) { this.get_node(o, true).children('.jstree-anchor').focus(); });
@@ -673,6 +688,12 @@
673
688
  e.preventDefault();
674
689
  this.element.find('.jstree-anchor').filter(':visible').last().focus();
675
690
  break;
691
+ case 113: // f2 - safe to include - if check_callback is false it will fail
692
+ e.preventDefault();
693
+ this.edit(e.currentTarget);
694
+ break;
695
+ default:
696
+ break;
676
697
  /*!
677
698
  // delete
678
699
  case 46:
@@ -683,17 +704,7 @@
683
704
  this.delete_node(o);
684
705
  }
685
706
  break;
686
- // f2
687
- case 113:
688
- e.preventDefault();
689
- o = this.get_node(e.currentTarget);
690
- if(o && o.id && o.id !== $.jstree.root) {
691
- // this.edit(o);
692
- }
693
- break;
694
- default:
695
- // console.log(e.which);
696
- break;
707
+
697
708
  */
698
709
  }
699
710
  }, this))
@@ -803,6 +814,7 @@
803
814
  this._data.core.themes.dots = s.dots;
804
815
  this._data.core.themes.stripes = s.stripes;
805
816
  this._data.core.themes.icons = s.icons;
817
+ this._data.core.themes.ellipsis = s.ellipsis;
806
818
  this.set_theme(s.name || "default", s.url);
807
819
  this.set_theme_variant(s.variant);
808
820
  }, this))
@@ -810,6 +822,7 @@
810
822
  this[ this._data.core.themes.dots ? "show_dots" : "hide_dots" ]();
811
823
  this[ this._data.core.themes.icons ? "show_icons" : "hide_icons" ]();
812
824
  this[ this._data.core.themes.stripes ? "show_stripes" : "hide_stripes" ]();
825
+ this[ this._data.core.themes.ellipsis ? "show_ellipsis" : "hide_ellipsis" ]();
813
826
  }, this))
814
827
  .on('blur.jstree', '.jstree-anchor', $.proxy(function (e) {
815
828
  this._data.core.focused = null;
@@ -1191,16 +1204,22 @@
1191
1204
  // if(obj.state.loading) { } // the node is already loading - just wait for it to load and invoke callback? but if called implicitly it should be loaded again?
1192
1205
  if(obj.state.loaded) {
1193
1206
  obj.state.loaded = false;
1207
+ for(i = 0, j = obj.parents.length; i < j; i++) {
1208
+ this._model.data[obj.parents[i]].children_d = $.vakata.array_filter(this._model.data[obj.parents[i]].children_d, function (v) {
1209
+ return $.inArray(v, obj.children_d) === -1;
1210
+ });
1211
+ }
1194
1212
  for(k = 0, l = obj.children_d.length; k < l; k++) {
1195
- for(i = 0, j = obj.parents.length; i < j; i++) {
1196
- this._model.data[obj.parents[i]].children_d = $.vakata.array_remove_item(this._model.data[obj.parents[i]].children_d, obj.children_d[k]);
1197
- }
1198
1213
  if(this._model.data[obj.children_d[k]].state.selected) {
1199
1214
  c = true;
1200
- this._data.core.selected = $.vakata.array_remove_item(this._data.core.selected, obj.children_d[k]);
1201
1215
  }
1202
1216
  delete this._model.data[obj.children_d[k]];
1203
1217
  }
1218
+ if (c) {
1219
+ this._data.core.selected = $.vakata.array_filter(this._data.core.selected, function (v) {
1220
+ return $.inArray(v, obj.children_d) === -1;
1221
+ });
1222
+ }
1204
1223
  obj.children = [];
1205
1224
  obj.children_d = [];
1206
1225
  if(c) {
@@ -1222,8 +1241,16 @@
1222
1241
  break;
1223
1242
  }
1224
1243
  }
1225
- if(obj.state.loaded && !has_children && dom && dom.length && !dom.hasClass('jstree-leaf')) {
1226
- dom.removeClass('jstree-closed jstree-open').addClass('jstree-leaf');
1244
+ if(obj.state.loaded && dom && dom.length) {
1245
+ dom.removeClass('jstree-closed jstree-open jstree-leaf');
1246
+ if (!has_children) {
1247
+ dom.addClass('jstree-leaf');
1248
+ }
1249
+ else {
1250
+ if (obj.id !== '#') {
1251
+ dom.addClass(obj.state.opened ? 'jstree-open' : 'jstree-closed');
1252
+ }
1253
+ }
1227
1254
  }
1228
1255
  dom.removeClass("jstree-loading").attr('aria-busy',false);
1229
1256
  /**
@@ -1247,12 +1274,12 @@
1247
1274
  * @param {array} nodes
1248
1275
  * @param {function} callback a function to be executed once loading is complete, the function is executed in the instance's scope and receives one argument - the array passed to _load_nodes
1249
1276
  */
1250
- _load_nodes : function (nodes, callback, is_callback) {
1277
+ _load_nodes : function (nodes, callback, is_callback, force_reload) {
1251
1278
  var r = true,
1252
1279
  c = function () { this._load_nodes(nodes, callback, true); },
1253
1280
  m = this._model.data, i, j, tmp = [];
1254
1281
  for(i = 0, j = nodes.length; i < j; i++) {
1255
- if(m[nodes[i]] && ( (!m[nodes[i]].state.loaded && !m[nodes[i]].state.failed) || !is_callback)) {
1282
+ if(m[nodes[i]] && ( (!m[nodes[i]].state.loaded && !m[nodes[i]].state.failed) || (!is_callback && force_reload) )) {
1256
1283
  if(!this.is_loading(nodes[i])) {
1257
1284
  this.load_node(nodes[i], c);
1258
1285
  }
@@ -1320,6 +1347,9 @@
1320
1347
  */
1321
1348
  _load_node : function (obj, callback) {
1322
1349
  var s = this.settings.core.data, t;
1350
+ var notTextOrCommentNode = function notTextOrCommentNode () {
1351
+ return this.nodeType !== 3 && this.nodeType !== 8;
1352
+ };
1323
1353
  // use original HTML
1324
1354
  if(!s) {
1325
1355
  if(obj.id === $.jstree.root) {
@@ -1337,9 +1367,11 @@
1337
1367
  if(d === false) {
1338
1368
  callback.call(this, false);
1339
1369
  }
1340
- this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $($.parseHTML(d)).filter(function () { return this.nodeType !== 3; }) : d, function (status) {
1341
- callback.call(this, status);
1342
- });
1370
+ else {
1371
+ this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $($.parseHTML(d)).filter(notTextOrCommentNode) : d, function (status) {
1372
+ callback.call(this, status);
1373
+ });
1374
+ }
1343
1375
  // return d === false ? callback.call(this, false) : callback.call(this, this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $(d) : d));
1344
1376
  }, this));
1345
1377
  }
@@ -1360,7 +1392,7 @@
1360
1392
  //return callback.call(this, this._append_json_data(obj, d));
1361
1393
  }
1362
1394
  if((type && type.indexOf('html') !== -1) || typeof d === "string") {
1363
- return this._append_html_data(obj, $($.parseHTML(d)).filter(function () { return this.nodeType !== 3; }), function (status) { callback.call(this, status); });
1395
+ return this._append_html_data(obj, $($.parseHTML(d)).filter(notTextOrCommentNode), function (status) { callback.call(this, status); });
1364
1396
  // return callback.call(this, this._append_html_data(obj, $(d)));
1365
1397
  }
1366
1398
  this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : x }) };
@@ -1388,7 +1420,7 @@
1388
1420
  }
1389
1421
  if(typeof s === 'string') {
1390
1422
  if(obj.id === $.jstree.root) {
1391
- return this._append_html_data(obj, $($.parseHTML(s)).filter(function () { return this.nodeType !== 3; }), function (status) {
1423
+ return this._append_html_data(obj, $($.parseHTML(s)).filter(notTextOrCommentNode), function (status) {
1392
1424
  callback.call(this, status);
1393
1425
  });
1394
1426
  }
@@ -1715,9 +1747,13 @@
1715
1747
  }
1716
1748
  // 2) populate children (foreach)
1717
1749
  for(i = 0, j = dat.length; i < j; i++) {
1718
- m[dat[i].parent.toString()].children.push(dat[i].id.toString());
1719
- // populate parent.children_d
1720
- p.children_d.push(dat[i].id.toString());
1750
+ try {
1751
+ m[dat[i].parent.toString()].children.push(dat[i].id.toString());
1752
+ // populate parent.children_d
1753
+ p.children_d.push(dat[i].id.toString());
1754
+ } catch(e) {
1755
+ debugger;
1756
+ }
1721
1757
  }
1722
1758
  // 3) normalize && populate parents and children_d with recursion
1723
1759
  for(i = 0, j = p.children.length; i < j; i++) {
@@ -1775,10 +1811,17 @@
1775
1811
  rslt = function (rslt, worker) {
1776
1812
  if(this.element === null) { return; }
1777
1813
  this._cnt = rslt.cnt;
1814
+ var i, m = this._model.data;
1815
+ for (i in m) {
1816
+ if (m.hasOwnProperty(i) && m[i].state && m[i].state.loading && rslt.mod[i]) {
1817
+ rslt.mod[i].state.loading = true;
1818
+ }
1819
+ }
1778
1820
  this._model.data = rslt.mod; // breaks the reference in load_node - careful
1779
1821
 
1780
1822
  if(worker) {
1781
- var i, j, a = rslt.add, r = rslt.sel, s = this._data.core.selected.slice(), m = this._model.data;
1823
+ var j, a = rslt.add, r = rslt.sel, s = this._data.core.selected.slice();
1824
+ m = this._model.data;
1782
1825
  // if selection was changed while calculating in worker
1783
1826
  if(r.length !== s.length || $.vakata.array_unique(r.concat(s)).length !== r.length) {
1784
1827
  // deselect nodes that are no longer selected
@@ -2334,7 +2377,7 @@
2334
2377
  //node = d.createElement('LI');
2335
2378
  //node = node[0];
2336
2379
  }
2337
- node = _node.cloneNode(true);
2380
+ node = this._data.core.node.cloneNode(true);
2338
2381
  // node is DOM, deep is boolean
2339
2382
 
2340
2383
  c = 'jstree-node ';
@@ -2419,7 +2462,7 @@
2419
2462
  node.childNodes[1].childNodes[0].className += ' ' + obj.icon + ' jstree-themeicon-custom';
2420
2463
  }
2421
2464
  else {
2422
- node.childNodes[1].childNodes[0].style.backgroundImage = 'url('+obj.icon+')';
2465
+ node.childNodes[1].childNodes[0].style.backgroundImage = 'url("'+obj.icon+'")';
2423
2466
  node.childNodes[1].childNodes[0].style.backgroundPosition = 'center center';
2424
2467
  node.childNodes[1].childNodes[0].style.backgroundSize = 'auto';
2425
2468
  node.childNodes[1].childNodes[0].className += ' jstree-themeicon-custom';
@@ -2549,7 +2592,9 @@
2549
2592
  .children(".jstree-children").stop(true, true)
2550
2593
  .slideDown(animation, function () {
2551
2594
  this.style.display = "";
2552
- t.trigger("after_open", { "node" : obj });
2595
+ if (t.element) {
2596
+ t.trigger("after_open", { "node" : obj });
2597
+ }
2553
2598
  });
2554
2599
  }
2555
2600
  }
@@ -2630,22 +2675,7 @@
2630
2675
  animation = animation === undefined ? this.settings.core.animation : animation;
2631
2676
  t = this;
2632
2677
  d = this.get_node(obj, true);
2633
- if(d.length) {
2634
- if(!animation) {
2635
- d[0].className = d[0].className.replace('jstree-open', 'jstree-closed');
2636
- d.attr("aria-expanded", false).children('.jstree-children').remove();
2637
- }
2638
- else {
2639
- d
2640
- .children(".jstree-children").attr("style","display:block !important").end()
2641
- .removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded", false)
2642
- .children(".jstree-children").stop(true, true).slideUp(animation, function () {
2643
- this.style.display = "";
2644
- d.children('.jstree-children').remove();
2645
- t.trigger("after_close", { "node" : obj });
2646
- });
2647
- }
2648
- }
2678
+
2649
2679
  obj.state.opened = false;
2650
2680
  /**
2651
2681
  * triggered when a node is closed (if there is an animation it will not be complete yet)
@@ -2654,7 +2684,7 @@
2654
2684
  * @param {Object} node the closed node
2655
2685
  */
2656
2686
  this.trigger('close_node',{ "node" : obj });
2657
- if(!animation || !d.length) {
2687
+ if(!d.length) {
2658
2688
  /**
2659
2689
  * triggered when a node is closed and the animation is complete
2660
2690
  * @event
@@ -2663,6 +2693,25 @@
2663
2693
  */
2664
2694
  this.trigger("after_close", { "node" : obj });
2665
2695
  }
2696
+ else {
2697
+ if(!animation) {
2698
+ d[0].className = d[0].className.replace('jstree-open', 'jstree-closed');
2699
+ d.attr("aria-expanded", false).children('.jstree-children').remove();
2700
+ this.trigger("after_close", { "node" : obj });
2701
+ }
2702
+ else {
2703
+ d
2704
+ .children(".jstree-children").attr("style","display:block !important").end()
2705
+ .removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded", false)
2706
+ .children(".jstree-children").stop(true, true).slideUp(animation, function () {
2707
+ this.style.display = "";
2708
+ d.children('.jstree-children').remove();
2709
+ if (t.element) {
2710
+ t.trigger("after_close", { "node" : obj });
2711
+ }
2712
+ });
2713
+ }
2714
+ }
2666
2715
  },
2667
2716
  /**
2668
2717
  * toggles a node - closing it if it is open, opening it if it is closed
@@ -2822,11 +2871,20 @@
2822
2871
  */
2823
2872
  this.trigger('disable_node', { 'node' : obj });
2824
2873
  },
2874
+ /**
2875
+ * determines if a node is hidden
2876
+ * @name is_hidden(obj)
2877
+ * @param {mixed} obj the node
2878
+ */
2879
+ is_hidden : function (obj) {
2880
+ obj = this.get_node(obj);
2881
+ return obj.state.hidden === true;
2882
+ },
2825
2883
  /**
2826
2884
  * hides a node - it is still in the structure but will not be visible
2827
2885
  * @name hide_node(obj)
2828
2886
  * @param {mixed} obj the node to hide
2829
- * @param {Boolean} redraw internal parameter controlling if redraw is called
2887
+ * @param {Boolean} skip_redraw internal parameter controlling if redraw is called
2830
2888
  * @trigger hide_node.jstree
2831
2889
  */
2832
2890
  hide_node : function (obj, skip_redraw) {
@@ -2836,7 +2894,9 @@
2836
2894
  for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
2837
2895
  this.hide_node(obj[t1], true);
2838
2896
  }
2839
- this.redraw();
2897
+ if (!skip_redraw) {
2898
+ this.redraw();
2899
+ }
2840
2900
  return true;
2841
2901
  }
2842
2902
  obj = this.get_node(obj);
@@ -2872,7 +2932,9 @@
2872
2932
  for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
2873
2933
  this.show_node(obj[t1], true);
2874
2934
  }
2875
- this.redraw();
2935
+ if (!skip_redraw) {
2936
+ this.redraw();
2937
+ }
2876
2938
  return true;
2877
2939
  }
2878
2940
  obj = this.get_node(obj);
@@ -2993,7 +3055,9 @@
2993
3055
  c = !c;
2994
3056
  }
2995
3057
  if(!this.is_disabled(p[i]) && (c || p[i] === o || p[i] === l)) {
2996
- this.select_node(p[i], true, false, e);
3058
+ if (!this.is_hidden(p[i])) {
3059
+ this.select_node(p[i], true, false, e);
3060
+ }
2997
3061
  }
2998
3062
  else {
2999
3063
  this.deselect_node(p[i], true, e);
@@ -3338,7 +3402,7 @@
3338
3402
  this.open_node(nodes, false, 0);
3339
3403
  delete state.core.open;
3340
3404
  this.set_state(state, callback);
3341
- }, true);
3405
+ });
3342
3406
  }
3343
3407
  return false;
3344
3408
  }
@@ -3448,10 +3512,10 @@
3448
3512
  var opened = [], to_load = [], s = this._data.core.selected.concat([]);
3449
3513
  to_load.push(obj.id);
3450
3514
  if(obj.state.opened === true) { opened.push(obj.id); }
3451
- this.get_node(obj, true).find('.jstree-open').each(function() { opened.push(this.id); });
3515
+ this.get_node(obj, true).find('.jstree-open').each(function() { to_load.push(this.id); opened.push(this.id); });
3452
3516
  this._load_nodes(to_load, $.proxy(function (nodes) {
3453
3517
  this.open_node(opened, false, 0);
3454
- this.select_node(this._data.core.selected);
3518
+ this.select_node(s);
3455
3519
  /**
3456
3520
  * triggered when a node is refreshed
3457
3521
  * @event
@@ -3460,7 +3524,7 @@
3460
3524
  * @param {Array} nodes - an array of the IDs of the nodes that were reloaded
3461
3525
  */
3462
3526
  this.trigger('refresh_node', { 'node' : obj, 'nodes' : nodes });
3463
- }, this));
3527
+ }, this), false, true);
3464
3528
  },
3465
3529
  /**
3466
3530
  * set (change) the ID of a node
@@ -3468,11 +3532,12 @@
3468
3532
  * @param {mixed} obj the node
3469
3533
  * @param {String} id the new ID
3470
3534
  * @return {Boolean}
3535
+ * @trigger set_id.jstree
3471
3536
  */
3472
3537
  set_id : function (obj, id) {
3473
3538
  obj = this.get_node(obj);
3474
3539
  if(!obj || obj.id === $.jstree.root) { return false; }
3475
- var i, j, m = this._model.data;
3540
+ var i, j, m = this._model.data, old = obj.id;
3476
3541
  id = id.toString();
3477
3542
  // update parents (replace current ID with new one in children and children_d)
3478
3543
  m[obj.parent].children[$.inArray(obj.id, m[obj.parent].children)] = id;
@@ -3491,7 +3556,7 @@
3491
3556
  // update model and obj itself (obj.id, this._model.data[KEY])
3492
3557
  i = this.get_node(obj.id, true);
3493
3558
  if(i) {
3494
- i.attr('id', id).children('.jstree-anchor').attr('id', id + '_anchor').end().attr('aria-labelledby', id + '_anchor');
3559
+ i.attr('id', id); //.children('.jstree-anchor').attr('id', id + '_anchor').end().attr('aria-labelledby', id + '_anchor');
3495
3560
  if(this.element.attr('aria-activedescendant') === obj.id) {
3496
3561
  this.element.attr('aria-activedescendant', id);
3497
3562
  }
@@ -3500,6 +3565,14 @@
3500
3565
  obj.id = id;
3501
3566
  obj.li_attr.id = id;
3502
3567
  m[id] = obj;
3568
+ /**
3569
+ * triggered when a node id value is changed
3570
+ * @event
3571
+ * @name set_id.jstree
3572
+ * @param {Object} node
3573
+ * @param {String} old the old id
3574
+ */
3575
+ this.trigger('set_id',{ "node" : obj, "new" : obj.id, "old" : old });
3503
3576
  return true;
3504
3577
  },
3505
3578
  /**
@@ -3555,6 +3628,8 @@
3555
3628
  * @param {Boolean} options.no_id do not return ID
3556
3629
  * @param {Boolean} options.no_children do not include children
3557
3630
  * @param {Boolean} options.no_data do not include node data
3631
+ * @param {Boolean} options.no_li_attr do not include LI attributes
3632
+ * @param {Boolean} options.no_a_attr do not include A attributes
3558
3633
  * @param {Boolean} options.flat return flat JSON instead of nested
3559
3634
  * @return {Object}
3560
3635
  */
@@ -3584,6 +3659,14 @@
3584
3659
  tmp.state[i] = obj.state[i];
3585
3660
  }
3586
3661
  }
3662
+ } else {
3663
+ delete tmp.state;
3664
+ }
3665
+ if(options && options.no_li_attr) {
3666
+ delete tmp.li_attr;
3667
+ }
3668
+ if(options && options.no_a_attr) {
3669
+ delete tmp.a_attr;
3587
3670
  }
3588
3671
  if(options && options.no_id) {
3589
3672
  delete tmp.id;
@@ -3611,7 +3694,7 @@
3611
3694
  },
3612
3695
  /**
3613
3696
  * create a new node (do not confuse with load_node)
3614
- * @name create_node([obj, node, pos, callback, is_loaded])
3697
+ * @name create_node([par, node, pos, callback, is_loaded])
3615
3698
  * @param {mixed} par the parent node (to create a root node use either "#" (string) or `null`)
3616
3699
  * @param {mixed} node the data for the new node (a valid JSON object, or a simple string with the name)
3617
3700
  * @param {mixed} pos the index at which to insert the node, "first" and "last" are also supported, default is "last"
@@ -3765,21 +3848,22 @@
3765
3848
  }
3766
3849
  tmp = obj.children_d.concat([]);
3767
3850
  tmp.push(obj.id);
3851
+ for(i = 0, j = obj.parents.length; i < j; i++) {
3852
+ this._model.data[obj.parents[i]].children_d = $.vakata.array_filter(this._model.data[obj.parents[i]].children_d, function (v) {
3853
+ return $.inArray(v, tmp) === -1;
3854
+ });
3855
+ }
3768
3856
  for(k = 0, l = tmp.length; k < l; k++) {
3769
- for(i = 0, j = obj.parents.length; i < j; i++) {
3770
- pos = $.inArray(tmp[k], this._model.data[obj.parents[i]].children_d);
3771
- if(pos !== -1) {
3772
- this._model.data[obj.parents[i]].children_d = $.vakata.array_remove(this._model.data[obj.parents[i]].children_d, pos);
3773
- }
3774
- }
3775
3857
  if(this._model.data[tmp[k]].state.selected) {
3776
3858
  c = true;
3777
- pos = $.inArray(tmp[k], this._data.core.selected);
3778
- if(pos !== -1) {
3779
- this._data.core.selected = $.vakata.array_remove(this._data.core.selected, pos);
3780
- }
3859
+ break;
3781
3860
  }
3782
3861
  }
3862
+ if (c) {
3863
+ this._data.core.selected = $.vakata.array_filter(this._data.core.selected, function (v) {
3864
+ return $.inArray(v, tmp) === -1;
3865
+ });
3866
+ }
3783
3867
  /**
3784
3868
  * triggered when a node is deleted
3785
3869
  * @event
@@ -3799,7 +3883,9 @@
3799
3883
  top = this.element[0].scrollTop;
3800
3884
  lft = this.element[0].scrollLeft;
3801
3885
  if(par.id === $.jstree.root) {
3802
- this.get_node(this._model.data[$.jstree.root].children[0], true).children('.jstree-anchor').focus();
3886
+ if (this._model.data[$.jstree.root].children[0]) {
3887
+ this.get_node(this._model.data[$.jstree.root].children[0], true).children('.jstree-anchor').focus();
3888
+ }
3803
3889
  }
3804
3890
  else {
3805
3891
  this.get_node(par, true).children('.jstree-anchor').focus();
@@ -3827,7 +3913,7 @@
3827
3913
  var tmp = chk.match(/^move_node|copy_node|create_node$/i) ? par : obj,
3828
3914
  chc = this.settings.core.check_callback;
3829
3915
  if(chk === "move_node" || chk === "copy_node") {
3830
- if((!more || !more.is_multi) && (obj.id === par.id || $.inArray(obj.id, par.children) === pos || $.inArray(par.id, obj.children_d) !== -1)) {
3916
+ if((!more || !more.is_multi) && (obj.id === par.id || (chk === "move_node" && $.inArray(obj.id, par.children) === pos) || $.inArray(par.id, obj.children_d) !== -1)) {
3831
3917
  this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_01', 'reason' : 'Moving parent inside child', 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
3832
3918
  return false;
3833
3919
  }
@@ -4342,6 +4428,7 @@
4342
4428
  if(callback) {
4343
4429
  callback.call(this, tmp, nv, cancel);
4344
4430
  }
4431
+ h2 = null;
4345
4432
  }, this),
4346
4433
  "keydown" : function (e) {
4347
4434
  var key = e.which;
@@ -4380,6 +4467,11 @@
4380
4467
  a.replaceWith(s);
4381
4468
  h1.css(fn);
4382
4469
  h2.css(fn).width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select();
4470
+ $(document).one('mousedown.jstree touchstart.jstree dnd_start.vakata', function (e) {
4471
+ if (h2 && e.target !== h2) {
4472
+ $(h2).blur();
4473
+ }
4474
+ });
4383
4475
  },
4384
4476
 
4385
4477
 
@@ -4445,12 +4537,30 @@
4445
4537
  * shows a striped background on the container (if the theme supports it)
4446
4538
  * @name show_stripes()
4447
4539
  */
4448
- show_stripes : function () { this._data.core.themes.stripes = true; this.get_container_ul().addClass("jstree-striped"); },
4540
+ show_stripes : function () {
4541
+ this._data.core.themes.stripes = true;
4542
+ this.get_container_ul().addClass("jstree-striped");
4543
+ /**
4544
+ * triggered when stripes are shown
4545
+ * @event
4546
+ * @name show_stripes.jstree
4547
+ */
4548
+ this.trigger('show_stripes');
4549
+ },
4449
4550
  /**
4450
4551
  * hides the striped background on the container
4451
4552
  * @name hide_stripes()
4452
4553
  */
4453
- hide_stripes : function () { this._data.core.themes.stripes = false; this.get_container_ul().removeClass("jstree-striped"); },
4554
+ hide_stripes : function () {
4555
+ this._data.core.themes.stripes = false;
4556
+ this.get_container_ul().removeClass("jstree-striped");
4557
+ /**
4558
+ * triggered when stripes are hidden
4559
+ * @event
4560
+ * @name hide_stripes.jstree
4561
+ */
4562
+ this.trigger('hide_stripes');
4563
+ },
4454
4564
  /**
4455
4565
  * toggles the striped background on the container
4456
4566
  * @name toggle_stripes()
@@ -4460,12 +4570,30 @@
4460
4570
  * shows the connecting dots (if the theme supports it)
4461
4571
  * @name show_dots()
4462
4572
  */
4463
- show_dots : function () { this._data.core.themes.dots = true; this.get_container_ul().removeClass("jstree-no-dots"); },
4573
+ show_dots : function () {
4574
+ this._data.core.themes.dots = true;
4575
+ this.get_container_ul().removeClass("jstree-no-dots");
4576
+ /**
4577
+ * triggered when dots are shown
4578
+ * @event
4579
+ * @name show_dots.jstree
4580
+ */
4581
+ this.trigger('show_dots');
4582
+ },
4464
4583
  /**
4465
4584
  * hides the connecting dots
4466
4585
  * @name hide_dots()
4467
4586
  */
4468
- hide_dots : function () { this._data.core.themes.dots = false; this.get_container_ul().addClass("jstree-no-dots"); },
4587
+ hide_dots : function () {
4588
+ this._data.core.themes.dots = false;
4589
+ this.get_container_ul().addClass("jstree-no-dots");
4590
+ /**
4591
+ * triggered when dots are hidden
4592
+ * @event
4593
+ * @name hide_dots.jstree
4594
+ */
4595
+ this.trigger('hide_dots');
4596
+ },
4469
4597
  /**
4470
4598
  * toggles the connecting dots
4471
4599
  * @name toggle_dots()
@@ -4475,17 +4603,68 @@
4475
4603
  * show the node icons
4476
4604
  * @name show_icons()
4477
4605
  */
4478
- show_icons : function () { this._data.core.themes.icons = true; this.get_container_ul().removeClass("jstree-no-icons"); },
4606
+ show_icons : function () {
4607
+ this._data.core.themes.icons = true;
4608
+ this.get_container_ul().removeClass("jstree-no-icons");
4609
+ /**
4610
+ * triggered when icons are shown
4611
+ * @event
4612
+ * @name show_icons.jstree
4613
+ */
4614
+ this.trigger('show_icons');
4615
+ },
4479
4616
  /**
4480
4617
  * hide the node icons
4481
4618
  * @name hide_icons()
4482
4619
  */
4483
- hide_icons : function () { this._data.core.themes.icons = false; this.get_container_ul().addClass("jstree-no-icons"); },
4620
+ hide_icons : function () {
4621
+ this._data.core.themes.icons = false;
4622
+ this.get_container_ul().addClass("jstree-no-icons");
4623
+ /**
4624
+ * triggered when icons are hidden
4625
+ * @event
4626
+ * @name hide_icons.jstree
4627
+ */
4628
+ this.trigger('hide_icons');
4629
+ },
4484
4630
  /**
4485
4631
  * toggle the node icons
4486
4632
  * @name toggle_icons()
4487
4633
  */
4488
4634
  toggle_icons : function () { if(this._data.core.themes.icons) { this.hide_icons(); } else { this.show_icons(); } },
4635
+ /**
4636
+ * show the node ellipsis
4637
+ * @name show_icons()
4638
+ */
4639
+ show_ellipsis : function () {
4640
+ this._data.core.themes.ellipsis = true;
4641
+ this.get_container_ul().addClass("jstree-ellipsis");
4642
+ /**
4643
+ * triggered when ellisis is shown
4644
+ * @event
4645
+ * @name show_ellipsis.jstree
4646
+ */
4647
+ this.trigger('show_ellipsis');
4648
+ },
4649
+ /**
4650
+ * hide the node ellipsis
4651
+ * @name hide_ellipsis()
4652
+ */
4653
+ hide_ellipsis : function () {
4654
+ this._data.core.themes.ellipsis = false;
4655
+ this.get_container_ul().removeClass("jstree-ellipsis");
4656
+ /**
4657
+ * triggered when ellisis is hidden
4658
+ * @event
4659
+ * @name hide_ellipsis.jstree
4660
+ */
4661
+ this.trigger('hide_ellipsis');
4662
+ },
4663
+ /**
4664
+ * toggle the node ellipsis
4665
+ * @name toggle_icons()
4666
+ */
4667
+ toggle_ellipsis : function () { if(this._data.core.themes.ellipsis) { this.hide_ellipsis(); } else { this.show_ellipsis(); } },
4489
4668
  /**
4490
4669
  * set the node icon for a node
4491
4670
  * @name set_icon(obj, icon)
@@ -4607,17 +4786,31 @@
4607
4786
  return a;
4608
4787
  };
4609
4788
  // remove item from array
4610
- $.vakata.array_remove = function(array, from, to) {
4611
- var rest = array.slice((to || from) + 1 || array.length);
4612
- array.length = from < 0 ? array.length + from : from;
4613
- array.push.apply(array, rest);
4789
+ $.vakata.array_remove = function(array, from) {
4790
+ array.splice(from, 1);
4614
4791
  return array;
4792
+ //var rest = array.slice((to || from) + 1 || array.length);
4793
+ //array.length = from < 0 ? array.length + from : from;
4794
+ //array.push.apply(array, rest);
4795
+ //return array;
4615
4796
  };
4616
4797
  // remove item from array
4617
4798
  $.vakata.array_remove_item = function(array, item) {
4618
4799
  var tmp = $.inArray(item, array);
4619
4800
  return tmp !== -1 ? $.vakata.array_remove(array, tmp) : array;
4620
4801
  };
4802
+ $.vakata.array_filter = function(c,a,b,d,e) {
4803
+ if (c.filter) {
4804
+ return c.filter(a, b);
4805
+ }
4806
+ d=[];
4807
+ for (e in c) {
4808
+ if (~~e+''===e+'' && e>=0 && a.call(b,c[e],+e,c)) {
4809
+ d.push(c[e]);
4810
+ }
4811
+ }
4812
+ return d;
4813
+ };
4621
4814
 
4622
4815
 
4623
4816
  /**
@@ -4839,12 +5032,17 @@
4839
5032
  m = this._model.data,
4840
5033
  par = this.get_node(obj.parent),
4841
5034
  dom = this.get_node(obj, true),
4842
- i, j, c, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection;
5035
+ i, j, c, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection,
5036
+ sel = {}, cur = this._data[ t ? 'core' : 'checkbox' ].selected;
4843
5037
 
5038
+ for (i = 0, j = cur.length; i < j; i++) {
5039
+ sel[cur[i]] = true;
5040
+ }
4844
5041
  // apply down
4845
5042
  if(s.indexOf('down') !== -1) {
4846
- this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected.concat(obj.children_d));
5043
+ //this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected.concat(obj.children_d));
4847
5044
  for(i = 0, j = obj.children_d.length; i < j; i++) {
5045
+ sel[obj.children_d[i]] = true;
4848
5046
  tmp = m[obj.children_d[i]];
4849
5047
  tmp.state[ t ? 'selected' : 'checked' ] = true;
4850
5048
  if(tmp && tmp.original && tmp.original.state && tmp.original.state.undetermined) {
@@ -4862,7 +5060,8 @@
4862
5060
  }
4863
5061
  if(c === j) {
4864
5062
  par.state[ t ? 'selected' : 'checked' ] = true;
4865
- this._data[ t ? 'core' : 'checkbox' ].selected.push(par.id);
5063
+ sel[par.id] = true;
5064
+ //this._data[ t ? 'core' : 'checkbox' ].selected.push(par.id);
4866
5065
  tmp = this.get_node(par, true);
4867
5066
  if(tmp && tmp.length) {
4868
5067
  tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
@@ -4875,6 +5074,14 @@
4875
5074
  }
4876
5075
  }
4877
5076
 
5077
+ cur = [];
5078
+ for (i in sel) {
5079
+ if (sel.hasOwnProperty(i)) {
5080
+ cur.push(i);
5081
+ }
5082
+ }
5083
+ this._data[ t ? 'core' : 'checkbox' ].selected = cur;
5084
+
4878
5085
  // apply down (process .children separately?)
4879
5086
  if(s.indexOf('down') !== -1 && dom.length) {
4880
5087
  dom.find('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked').parent().attr('aria-selected', true);
@@ -4894,7 +5101,8 @@
4894
5101
  .on(this.settings.checkbox.tie_selection ? 'deselect_node.jstree' : 'uncheck_node.jstree', $.proxy(function (e, data) {
4895
5102
  var obj = data.node,
4896
5103
  dom = this.get_node(obj, true),
4897
- i, j, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection;
5104
+ i, j, tmp, s = this.settings.checkbox.cascade, t = this.settings.checkbox.tie_selection,
5105
+ cur = this._data[ t ? 'core' : 'checkbox' ].selected, sel = {};
4898
5106
  if(obj && obj.original && obj.original.state && obj.original.state.undetermined) {
4899
5107
  obj.original.state.undetermined = false;
4900
5108
  }
@@ -4924,17 +5132,23 @@
4924
5132
  }
4925
5133
  }
4926
5134
  }
4927
- tmp = [];
4928
- for(i = 0, j = this._data[ t ? 'core' : 'checkbox' ].selected.length; i < j; i++) {
5135
+ sel = {};
5136
+ for(i = 0, j = cur.length; i < j; i++) {
4929
5137
  // apply down + apply up
4930
5138
  if(
4931
- (s.indexOf('down') === -1 || $.inArray(this._data[ t ? 'core' : 'checkbox' ].selected[i], obj.children_d) === -1) &&
4932
- (s.indexOf('up') === -1 || $.inArray(this._data[ t ? 'core' : 'checkbox' ].selected[i], obj.parents) === -1)
5139
+ (s.indexOf('down') === -1 || $.inArray(cur[i], obj.children_d) === -1) &&
5140
+ (s.indexOf('up') === -1 || $.inArray(cur[i], obj.parents) === -1)
4933
5141
  ) {
4934
- tmp.push(this._data[ t ? 'core' : 'checkbox' ].selected[i]);
5142
+ sel[cur[i]] = true;
5143
+ }
5144
+ }
5145
+ cur = [];
5146
+ for (i in sel) {
5147
+ if (sel.hasOwnProperty(i)) {
5148
+ cur.push(i);
4935
5149
  }
4936
5150
  }
4937
- this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(tmp);
5151
+ this._data[ t ? 'core' : 'checkbox' ].selected = cur;
4938
5152
 
4939
5153
  // apply down (process .children separately?)
4940
5154
  if(s.indexOf('down') !== -1 && dom.length) {
@@ -5042,7 +5256,10 @@
5042
5256
  for(i = 0, j = s.length; i < j; i++) {
5043
5257
  if(m[s[i]] && m[s[i]].parents) {
5044
5258
  for(k = 0, l = m[s[i]].parents.length; k < l; k++) {
5045
- if(o[m[s[i]].parents[k]] === undefined && m[s[i]].parents[k] !== $.jstree.root) {
5259
+ if(o[m[s[i]].parents[k]] !== undefined) {
5260
+ break;
5261
+ }
5262
+ if(m[s[i]].parents[k] !== $.jstree.root) {
5046
5263
  o[m[s[i]].parents[k]] = true;
5047
5264
  p.push(m[s[i]].parents[k]);
5048
5265
  }
@@ -5553,16 +5770,18 @@
5553
5770
  /**
5554
5771
  * an object of actions, or a function that accepts a node and a callback function and calls the callback function with an object of actions available for that node (you can also return the items too).
5555
5772
  *
5556
- * Each action consists of a key (a unique name) and a value which is an object with the following properties (only label and action are required):
5773
+ * Each action consists of a key (a unique name) and a value which is an object with the following properties (only label and action are required). Once a menu item is activated the `action` function will be invoked with an object containing the following keys: item - the contextmenu item definition as seen below, reference - the DOM node that was used (the tree node), element - the contextmenu DOM element, position - an object with x/y properties indicating the position of the menu.
5557
5774
  *
5558
5775
  * * `separator_before` - a boolean indicating if there should be a separator before this item
5559
5776
  * * `separator_after` - a boolean indicating if there should be a separator after this item
5560
5777
  * * `_disabled` - a boolean indicating if this action should be disabled
5561
5778
  * * `label` - a string - the name of the action (could be a function returning a string)
5562
- * * `action` - a function to be executed if this item is chosen
5779
+ * * `title` - a string - an optional tooltip for the item
5780
+ * * `action` - a function to be executed if this item is chosen, the function will receive
5563
5781
  * * `icon` - a string, can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class
5564
5782
  * * `shortcut` - keyCode which will trigger the action if the menu is open (for example `113` for rename, which equals F2)
5565
5783
  * * `shortcut_label` - shortcut label (like for example `F2` for rename)
5784
+ * * `submenu` - an object with the same structure as $.jstree.defaults.contextmenu.items which can be used to create a submenu - each key will be rendered as a separate option in a submenu that will appear once the current item is hovered
5566
5785
  *
5567
5786
  * @name $.jstree.defaults.contextmenu.items
5568
5787
  * @plugin contextmenu
@@ -5680,6 +5899,9 @@
5680
5899
  var last_ts = 0, cto = null, ex, ey;
5681
5900
  this.element
5682
5901
  .on("contextmenu.jstree", ".jstree-anchor", $.proxy(function (e, data) {
5902
+ if (e.target.tagName.toLowerCase() === 'input') {
5903
+ return;
5904
+ }
5683
5905
  e.preventDefault();
5684
5906
  last_ts = e.ctrlKey ? +new Date() : 0;
5685
5907
  if(data || cto) {
@@ -5702,14 +5924,14 @@
5702
5924
  if(!e.originalEvent || !e.originalEvent.changedTouches || !e.originalEvent.changedTouches[0]) {
5703
5925
  return;
5704
5926
  }
5705
- ex = e.pageX;
5706
- ey = e.pageY;
5927
+ ex = e.originalEvent.changedTouches[0].clientX;
5928
+ ey = e.originalEvent.changedTouches[0].clientY;
5707
5929
  cto = setTimeout(function () {
5708
5930
  $(e.currentTarget).trigger('contextmenu', true);
5709
5931
  }, 750);
5710
5932
  })
5711
5933
  .on('touchmove.vakata.jstree', function (e) {
5712
- if(cto && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0] && (Math.abs(ex - e.pageX) > 50 || Math.abs(ey - e.pageY) > 50)) {
5934
+ if(cto && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0] && (Math.abs(ex - e.originalEvent.changedTouches[0].clientX) > 50 || Math.abs(ey - e.originalEvent.changedTouches[0].clientY) > 50)) {
5713
5935
  clearTimeout(cto);
5714
5936
  }
5715
5937
  })
@@ -5740,7 +5962,10 @@
5740
5962
  });
5741
5963
  }
5742
5964
  */
5743
- $(document).on("context_hide.vakata.jstree", $.proxy(function () { this._data.contextmenu.visible = false; }, this));
5965
+ $(document).on("context_hide.vakata.jstree", $.proxy(function (e, data) {
5966
+ this._data.contextmenu.visible = false;
5967
+ $(data.reference).removeClass('jstree-context');
5968
+ }, this));
5744
5969
  };
5745
5970
  this.teardown = function () {
5746
5971
  if(this._data.contextmenu.visible) {
@@ -5803,6 +6028,7 @@
5803
6028
  $(document).one("context_show.vakata.jstree", $.proxy(function (e, data) {
5804
6029
  var cls = 'jstree-contextmenu jstree-' + this.get_theme() + '-contextmenu';
5805
6030
  $(data.element).addClass(cls);
6031
+ a.addClass('jstree-context');
5806
6032
  }, this));
5807
6033
  this._data.contextmenu.visible = true;
5808
6034
  $.vakata.context.show(a, { 'x' : x, 'y' : y }, i);
@@ -5878,7 +6104,7 @@
5878
6104
  }
5879
6105
  sep = false;
5880
6106
  str += "<"+"li class='" + (val._class || "") + (val._disabled === true || ($.isFunction(val._disabled) && val._disabled({ "item" : val, "reference" : vakata_context.reference, "element" : vakata_context.element })) ? " vakata-contextmenu-disabled " : "") + "' "+(val.shortcut?" data-shortcut='"+val.shortcut+"' ":'')+">";
5881
- str += "<"+"a href='#' rel='" + (vakata_context.items.length - 1) + "'>";
6107
+ str += "<"+"a href='#' rel='" + (vakata_context.items.length - 1) + "' " + (val.title ? "title='" + val.title + "'" : "") + ">";
5882
6108
  if($.vakata.context.settings.icons) {
5883
6109
  str += "<"+"i ";
5884
6110
  if(val.icon) {
@@ -5916,7 +6142,8 @@
5916
6142
  o = $(o);
5917
6143
  if(!o.length || !o.children("ul").length) { return; }
5918
6144
  var e = o.children("ul"),
5919
- x = o.offset().left + o.outerWidth(),
6145
+ xl = o.offset().left,
6146
+ x = xl + o.outerWidth(),
5920
6147
  y = o.offset().top,
5921
6148
  w = e.width(),
5922
6149
  h = e.height(),
@@ -5927,11 +6154,23 @@
5927
6154
  o[x - (w + 10 + o.outerWidth()) < 0 ? "addClass" : "removeClass"]("vakata-context-left");
5928
6155
  }
5929
6156
  else {
5930
- o[x + w + 10 > dw ? "addClass" : "removeClass"]("vakata-context-right");
6157
+ o[x + w > dw && xl > dw - x ? "addClass" : "removeClass"]("vakata-context-right");
5931
6158
  }
5932
6159
  if(y + h + 10 > dh) {
5933
6160
  e.css("bottom","-1px");
5934
6161
  }
6162
+
6163
+ //if does not fit - stick it to the side
6164
+ if (o.hasClass('vakata-context-right')) {
6165
+ if (xl < w) {
6166
+ e.css("margin-right", xl - w);
6167
+ }
6168
+ } else {
6169
+ if (dw - x < w) {
6170
+ e.css("margin-left", dw - x - w);
6171
+ }
6172
+ }
6173
+
5935
6174
  e.show();
5936
6175
  },
5937
6176
  show : function (reference, position, data) {
@@ -6070,7 +6309,7 @@
6070
6309
  switch(e.which) {
6071
6310
  case 13:
6072
6311
  case 32:
6073
- e.type = "mouseup";
6312
+ e.type = "click";
6074
6313
  e.preventDefault();
6075
6314
  $(e.currentTarget).trigger(e);
6076
6315
  break;
@@ -6141,6 +6380,7 @@
6141
6380
  }($));
6142
6381
  // $.jstree.defaults.plugins.push("contextmenu");
6143
6382
 
6383
+
6144
6384
  /**
6145
6385
  * ### Drag'n'drop plugin
6146
6386
  *
@@ -6212,15 +6452,27 @@
6212
6452
  * @name $.jstree.defaults.dnd.large_drag_target
6213
6453
  * @plugin dnd
6214
6454
  */
6215
- large_drag_target : false
6455
+ large_drag_target : false,
6456
+ /**
6457
+ * controls whether use HTML5 dnd api instead of classical. That will allow better integration of dnd events with other HTML5 controls.
6458
+ * @reference http://caniuse.com/#feat=dragndrop
6459
+ * @name $.jstree.defaults.dnd.use_html5
6460
+ * @plugin dnd
6461
+ */
6462
+ use_html5: false
6216
6463
  };
6464
+ var drg, elm;
6217
6465
  // TODO: now check works by checking for each node individually, how about max_children, unique, etc?
6218
6466
  $.jstree.plugins.dnd = function (options, parent) {
6467
+ this.init = function (el, options) {
6468
+ parent.init.call(this, el, options);
6469
+ this.settings.dnd.use_html5 = this.settings.dnd.use_html5 && ('draggable' in document.createElement('span'));
6470
+ };
6219
6471
  this.bind = function () {
6220
6472
  parent.bind.call(this);
6221
6473
 
6222
6474
  this.element
6223
- .on('mousedown.jstree touchstart.jstree', this.settings.dnd.large_drag_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) {
6475
+ .on(this.settings.dnd.use_html5 ? 'dragstart.jstree' : 'mousedown.jstree touchstart.jstree', this.settings.dnd.large_drag_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) {
6224
6476
  if(this.settings.dnd.large_drag_target && $(e.target).closest('.jstree-node')[0] !== e.currentTarget) {
6225
6477
  return true;
6226
6478
  }
@@ -6233,13 +6485,57 @@
6233
6485
  if(this.settings.core.force_text) {
6234
6486
  txt = $.vakata.html.escape(txt);
6235
6487
  }
6236
- if(obj && obj.id && obj.id !== $.jstree.root && (e.which === 1 || e.type === "touchstart") &&
6488
+ if(obj && obj.id && obj.id !== $.jstree.root && (e.which === 1 || e.type === "touchstart" || e.type === "dragstart") &&
6237
6489
  (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)))
6238
6490
  ) {
6239
- this.element.trigger('mousedown.jstree');
6240
- 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>');
6491
+ drg = { 'jstree' : true, 'origin' : this, 'obj' : this.get_node(obj,true), 'nodes' : mlt > 1 ? this.get_top_selected() : [obj.id] };
6492
+ elm = e.currentTarget;
6493
+ if (this.settings.dnd.use_html5) {
6494
+ $.vakata.dnd._trigger('start', e, { 'helper': $(), 'element': elm, 'data': drg });
6495
+ } else {
6496
+ this.element.trigger('mousedown.jstree');
6497
+ return $.vakata.dnd.start(e, drg, '<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>');
6498
+ }
6241
6499
  }
6242
6500
  }, this));
6501
+ if (this.settings.dnd.use_html5) {
6502
+ this.element
6503
+ .on('dragover.jstree', function (e) {
6504
+ e.preventDefault();
6505
+ $.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg });
6506
+ return false;
6507
+ })
6508
+ //.on('dragenter.jstree', this.settings.dnd.large_drop_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) {
6509
+ // e.preventDefault();
6510
+ // $.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg });
6511
+ // return false;
6512
+ // }, this))
6513
+ .on('drop.jstree', $.proxy(function (e) {
6514
+ e.preventDefault();
6515
+ $.vakata.dnd._trigger('stop', e, { 'helper': $(), 'element': elm, 'data': drg });
6516
+ return false;
6517
+ }, this));
6518
+ }
6519
+ };
6520
+ this.redraw_node = function(obj, deep, callback, force_render) {
6521
+ obj = parent.redraw_node.apply(this, arguments);
6522
+ if (obj && this.settings.dnd.use_html5) {
6523
+ if (this.settings.dnd.large_drag_target) {
6524
+ obj.setAttribute('draggable', true);
6525
+ } else {
6526
+ var i, j, tmp = null;
6527
+ for(i = 0, j = obj.childNodes.length; i < j; i++) {
6528
+ if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) {
6529
+ tmp = obj.childNodes[i];
6530
+ break;
6531
+ }
6532
+ }
6533
+ if(tmp) {
6534
+ tmp.setAttribute('draggable', true);
6535
+ }
6536
+ }
6537
+ }
6538
+ return obj;
6243
6539
  };
6244
6540
  };
6245
6541
 
@@ -6259,7 +6555,11 @@
6259
6555
  marker.appendTo('body'); //.show();
6260
6556
  })
6261
6557
  .on('dnd_move.vakata.jstree', function (e, data) {
6262
- if(opento) { clearTimeout(opento); }
6558
+ if(opento) {
6559
+ if (!data.event || data.event.type !== 'dragover' || data.event.target !== lastev.target) {
6560
+ clearTimeout(opento);
6561
+ }
6562
+ }
6263
6563
  if(!data || !data.data || !data.data.jstree) { return; }
6264
6564
 
6265
6565
  // if we are hovering the marker image do nothing (can happen on "inside" drags)
@@ -6272,16 +6572,17 @@
6272
6572
  ref = false,
6273
6573
  off = false,
6274
6574
  rel = false,
6275
- tmp, l, t, h, p, i, o, ok, t1, t2, op, ps, pr, ip, tm;
6575
+ tmp, l, t, h, p, i, o, ok, t1, t2, op, ps, pr, ip, tm, is_copy, pn;
6276
6576
  // if we are over an instance
6277
6577
  if(ins && ins._data && ins._data.dnd) {
6278
6578
  marker.attr('class', 'jstree-' + ins.get_theme() + ( ins.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' ));
6579
+ is_copy = data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey)));
6279
6580
  data.helper
6280
6581
  .children().attr('class', 'jstree-' + ins.get_theme() + ' jstree-' + ins.get_theme() + '-' + ins.get_theme_variant() + ' ' + ( ins.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' ))
6281
- .find('.jstree-copy').first()[ data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))) ? 'show' : 'hide' ]();
6282
-
6582
+ .find('.jstree-copy').first()[ is_copy ? 'show' : 'hide' ]();
6283
6583
 
6284
6584
  // if are hovering the container itself add a new root node
6585
+ //console.log(data.event);
6285
6586
  if( (data.event.target === ins.element[0] || data.event.target === ins.get_container_ul()[0]) && ins.get_container_ul().children().length === 0) {
6286
6587
  ok = true;
6287
6588
  for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) {
@@ -6292,6 +6593,9 @@
6292
6593
  lastmv = { 'ins' : ins, 'par' : $.jstree.root, 'pos' : 'last' };
6293
6594
  marker.hide();
6294
6595
  data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok');
6596
+ if (data.event.originalEvent && data.event.originalEvent.dataTransfer) {
6597
+ data.event.originalEvent.dataTransfer.dropEffect = is_copy ? 'copy' : 'move';
6598
+ }
6295
6599
  return;
6296
6600
  }
6297
6601
  }
@@ -6300,7 +6604,7 @@
6300
6604
  ref = ins.settings.dnd.large_drop_target ? $(data.event.target).closest('.jstree-node').children('.jstree-anchor') : $(data.event.target).closest('.jstree-anchor');
6301
6605
  if(ref && ref.length && ref.parent().is('.jstree-closed, .jstree-open, .jstree-leaf')) {
6302
6606
  off = ref.offset();
6303
- rel = data.event.pageY - off.top;
6607
+ rel = (data.event.pageY !== undefined ? data.event.pageY : data.event.originalEvent.pageY) - off.top;
6304
6608
  h = ref.outerHeight();
6305
6609
  if(rel < h / 3) {
6306
6610
  o = ['b', 'i', 'a'];
@@ -6354,9 +6658,17 @@
6354
6658
  opento = setTimeout((function (x, z) { return function () { x.open_node(z); }; }(ins, ref)), ins.settings.dnd.open_timeout);
6355
6659
  }
6356
6660
  if(ok) {
6661
+ pn = ins.get_node(p, true);
6662
+ if (!pn.hasClass('.jstree-dnd-parent')) {
6663
+ $('.jstree-dnd-parent').removeClass('jstree-dnd-parent');
6664
+ pn.addClass('jstree-dnd-parent');
6665
+ }
6357
6666
  lastmv = { 'ins' : ins, 'par' : p, 'pos' : v === 'i' && ip === 'last' && i === 0 && !ins.is_loaded(tm) ? 'last' : i };
6358
6667
  marker.css({ 'left' : l + 'px', 'top' : t + 'px' }).show();
6359
6668
  data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok');
6669
+ if (data.event.originalEvent && data.event.originalEvent.dataTransfer) {
6670
+ data.event.originalEvent.dataTransfer.dropEffect = is_copy ? 'copy' : 'move';
6671
+ }
6360
6672
  laster = {};
6361
6673
  o = true;
6362
6674
  return false;
@@ -6366,8 +6678,12 @@
6366
6678
  }
6367
6679
  }
6368
6680
  }
6681
+ $('.jstree-dnd-parent').removeClass('jstree-dnd-parent');
6369
6682
  lastmv = false;
6370
6683
  data.helper.find('.jstree-icon').removeClass('jstree-ok').addClass('jstree-er');
6684
+ if (data.event.originalEvent && data.event.originalEvent.dataTransfer) {
6685
+ data.event.originalEvent.dataTransfer.dropEffect = 'none';
6686
+ }
6371
6687
  marker.hide();
6372
6688
  })
6373
6689
  .on('dnd_scroll.vakata.jstree', function (e, data) {
@@ -6378,6 +6694,7 @@
6378
6694
  data.helper.find('.jstree-icon').first().removeClass('jstree-ok').addClass('jstree-er');
6379
6695
  })
6380
6696
  .on('dnd_stop.vakata.jstree', function (e, data) {
6697
+ $('.jstree-dnd-parent').removeClass('jstree-dnd-parent');
6381
6698
  if(opento) { clearTimeout(opento); }
6382
6699
  if(!data || !data.data || !data.data.jstree) { return; }
6383
6700
  marker.hide().detach();
@@ -6403,11 +6720,21 @@
6403
6720
  .on('keyup.jstree keydown.jstree', function (e, data) {
6404
6721
  data = $.vakata.dnd._get();
6405
6722
  if(data && data.data && data.data.jstree) {
6406
- 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' ]();
6407
- if(lastev) {
6408
- lastev.metaKey = e.metaKey;
6409
- lastev.ctrlKey = e.ctrlKey;
6410
- $.vakata.dnd._trigger('move', lastev);
6723
+ if (e.type === "keyup" && e.which === 27) {
6724
+ if (opento) { clearTimeout(opento); }
6725
+ lastmv = false;
6726
+ laster = false;
6727
+ lastev = false;
6728
+ opento = false;
6729
+ marker.hide().detach();
6730
+ $.vakata.dnd._clean();
6731
+ } else {
6732
+ 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' ]();
6733
+ if(lastev) {
6734
+ lastev.metaKey = e.metaKey;
6735
+ lastev.ctrlKey = e.ctrlKey;
6736
+ $.vakata.dnd._trigger('move', lastev);
6737
+ }
6411
6738
  }
6412
6739
  }
6413
6740
  });
@@ -6450,8 +6777,10 @@
6450
6777
  threshold : 5,
6451
6778
  threshold_touch : 50
6452
6779
  },
6453
- _trigger : function (event_name, e) {
6454
- var data = $.vakata.dnd._get();
6780
+ _trigger : function (event_name, e, data) {
6781
+ if (data === undefined) {
6782
+ data = $.vakata.dnd._get();
6783
+ }
6455
6784
  data.event = e;
6456
6785
  $(document).triggerHandler("dnd_" + event_name + ".vakata", data);
6457
6786
  },
@@ -6523,7 +6852,11 @@
6523
6852
  try {
6524
6853
  e.currentTarget.unselectable = "on";
6525
6854
  e.currentTarget.onselectstart = function() { return false; };
6526
- if(e.currentTarget.style) { e.currentTarget.style.MozUserSelect = "none"; }
6855
+ if(e.currentTarget.style) {
6856
+ e.currentTarget.style.touchAction = "none";
6857
+ e.currentTarget.style.msTouchAction = "none";
6858
+ e.currentTarget.style.MozUserSelect = "none";
6859
+ }
6527
6860
  } catch(ignore) { }
6528
6861
  vakata_dnd.init_x = e.pageX;
6529
6862
  vakata_dnd.init_y = e.pageY;
@@ -6564,6 +6897,7 @@
6564
6897
  vakata_dnd.helper_w = vakata_dnd.helper.outerWidth();
6565
6898
  }
6566
6899
  vakata_dnd.is_drag = true;
6900
+ $(vakata_dnd.target).one('click.vakata', false);
6567
6901
  /**
6568
6902
  * triggered on the document when a drag starts
6569
6903
  * @event
@@ -6664,6 +6998,9 @@
6664
6998
  * @param {jQuery} helper the helper shown next to the mouse
6665
6999
  * @param {Object} event the event that caused the stop
6666
7000
  */
7001
+ if (e.target !== vakata_dnd.target) {
7002
+ $(vakata_dnd.target).off('click.vakata');
7003
+ }
6667
7004
  $.vakata.dnd._trigger("stop", e);
6668
7005
  }
6669
7006
  else {
@@ -6709,58 +7046,95 @@
6709
7046
  $.jstree.defaults.massload = null;
6710
7047
  $.jstree.plugins.massload = function (options, parent) {
6711
7048
  this.init = function (el, options) {
6712
- parent.init.call(this, el, options);
6713
7049
  this._data.massload = {};
7050
+ parent.init.call(this, el, options);
6714
7051
  };
6715
- this._load_nodes = function (nodes, callback, is_callback) {
6716
- var s = this.settings.massload;
6717
- if(is_callback && !$.isEmptyObject(this._data.massload)) {
6718
- return parent._load_nodes.call(this, nodes, callback, is_callback);
6719
- }
6720
- if($.isFunction(s)) {
6721
- return s.call(this, nodes, $.proxy(function (data) {
6722
- if(data) {
6723
- for(var i in data) {
6724
- if(data.hasOwnProperty(i)) {
6725
- this._data.massload[i] = data[i];
6726
- }
7052
+ this._load_nodes = function (nodes, callback, is_callback, force_reload) {
7053
+ var s = this.settings.massload,
7054
+ nodesString = JSON.stringify(nodes),
7055
+ toLoad = [],
7056
+ m = this._model.data,
7057
+ i, j, dom;
7058
+ if (!is_callback) {
7059
+ for(i = 0, j = nodes.length; i < j; i++) {
7060
+ if(!m[nodes[i]] || ( (!m[nodes[i]].state.loaded && !m[nodes[i]].state.failed) || force_reload) ) {
7061
+ toLoad.push(nodes[i]);
7062
+ dom = this.get_node(nodes[i], true);
7063
+ if (dom && dom.length) {
7064
+ dom.addClass("jstree-loading").attr('aria-busy',true);
6727
7065
  }
6728
7066
  }
6729
- parent._load_nodes.call(this, nodes, callback, is_callback);
6730
- }, this));
6731
- }
6732
- if(typeof s === 'object' && s && s.url) {
6733
- s = $.extend(true, {}, s);
6734
- if($.isFunction(s.url)) {
6735
- s.url = s.url.call(this, nodes);
6736
- }
6737
- if($.isFunction(s.data)) {
6738
- s.data = s.data.call(this, nodes);
6739
7067
  }
6740
- return $.ajax(s)
6741
- .done($.proxy(function (data,t,x) {
6742
- if(data) {
6743
- for(var i in data) {
6744
- if(data.hasOwnProperty(i)) {
6745
- this._data.massload[i] = data[i];
7068
+ this._data.massload = {};
7069
+ if (toLoad.length) {
7070
+ if($.isFunction(s)) {
7071
+ return s.call(this, toLoad, $.proxy(function (data) {
7072
+ var i, j;
7073
+ if(data) {
7074
+ for(i in data) {
7075
+ if(data.hasOwnProperty(i)) {
7076
+ this._data.massload[i] = data[i];
7077
+ }
7078
+ }
7079
+ }
7080
+ for(i = 0, j = nodes.length; i < j; i++) {
7081
+ dom = this.get_node(nodes[i], true);
7082
+ if (dom && dom.length) {
7083
+ dom.removeClass("jstree-loading").attr('aria-busy',false);
6746
7084
  }
6747
7085
  }
7086
+ parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
7087
+ }, this));
7088
+ }
7089
+ if(typeof s === 'object' && s && s.url) {
7090
+ s = $.extend(true, {}, s);
7091
+ if($.isFunction(s.url)) {
7092
+ s.url = s.url.call(this, toLoad);
6748
7093
  }
6749
- parent._load_nodes.call(this, nodes, callback, is_callback);
6750
- }, this))
6751
- .fail($.proxy(function (f) {
6752
- parent._load_nodes.call(this, nodes, callback, is_callback);
6753
- }, this));
7094
+ if($.isFunction(s.data)) {
7095
+ s.data = s.data.call(this, toLoad);
7096
+ }
7097
+ return $.ajax(s)
7098
+ .done($.proxy(function (data,t,x) {
7099
+ var i, j;
7100
+ if(data) {
7101
+ for(i in data) {
7102
+ if(data.hasOwnProperty(i)) {
7103
+ this._data.massload[i] = data[i];
7104
+ }
7105
+ }
7106
+ }
7107
+ for(i = 0, j = nodes.length; i < j; i++) {
7108
+ dom = this.get_node(nodes[i], true);
7109
+ if (dom && dom.length) {
7110
+ dom.removeClass("jstree-loading").attr('aria-busy',false);
7111
+ }
7112
+ }
7113
+ parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
7114
+ }, this))
7115
+ .fail($.proxy(function (f) {
7116
+ parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
7117
+ }, this));
7118
+ }
7119
+ }
6754
7120
  }
6755
- return parent._load_nodes.call(this, nodes, callback, is_callback);
7121
+ return parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
6756
7122
  };
6757
7123
  this._load_node = function (obj, callback) {
6758
- var d = this._data.massload[obj.id];
6759
- if(d) {
6760
- return this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $($.parseHTML(d)).filter(function () { return this.nodeType !== 3; }) : d, function (status) {
6761
- callback.call(this, status);
6762
- delete this._data.massload[obj.id];
6763
- });
7124
+ var data = this._data.massload[obj.id],
7125
+ rslt = null, dom;
7126
+ if(data) {
7127
+ rslt = this[typeof data === 'string' ? '_append_html_data' : '_append_json_data'](
7128
+ obj,
7129
+ typeof data === 'string' ? $($.parseHTML(data)).filter(function () { return this.nodeType !== 3; }) : data,
7130
+ function (status) { callback.call(this, status); }
7131
+ );
7132
+ dom = this.get_node(obj.id, true);
7133
+ if (dom && dom.length) {
7134
+ dom.removeClass("jstree-loading").attr('aria-busy',false);
7135
+ }
7136
+ delete this._data.massload[obj.id];
7137
+ return rslt;
6764
7138
  }
6765
7139
  return parent._load_node.call(this, obj, callback);
6766
7140
  };
@@ -6849,24 +7223,30 @@
6849
7223
  this.element
6850
7224
  .on("search.jstree", $.proxy(function (e, data) {
6851
7225
  if(this._data.search.som && data.res.length) {
6852
- var m = this._model.data, i, j, p = [];
7226
+ var m = this._model.data, i, j, p = [], k, l;
6853
7227
  for(i = 0, j = data.res.length; i < j; i++) {
6854
7228
  if(m[data.res[i]] && !m[data.res[i]].state.hidden) {
6855
7229
  p.push(data.res[i]);
6856
7230
  p = p.concat(m[data.res[i]].parents);
6857
7231
  if(this._data.search.smc) {
6858
- p = p.concat(m[data.res[i]].children_d);
7232
+ for (k = 0, l = m[data.res[i]].children_d.length; k < l; k++) {
7233
+ if (m[m[data.res[i]].children_d[k]] && !m[m[data.res[i]].children_d[k]].state.hidden) {
7234
+ p.push(m[data.res[i]].children_d[k]);
7235
+ }
7236
+ }
6859
7237
  }
6860
7238
  }
6861
7239
  }
6862
7240
  p = $.vakata.array_remove_item($.vakata.array_unique(p), $.jstree.root);
6863
7241
  this._data.search.hdn = this.hide_all(true);
6864
- this.show_node(p);
7242
+ this.show_node(p, true);
7243
+ this.redraw(true);
6865
7244
  }
6866
7245
  }, this))
6867
7246
  .on("clear_search.jstree", $.proxy(function (e, data) {
6868
7247
  if(this._data.search.som && data.res.length) {
6869
- this.show_node(this._data.search.hdn);
7248
+ this.show_node(this._data.search.hdn, true);
7249
+ this.redraw(true);
6870
7250
  }
6871
7251
  }, this));
6872
7252
  };
@@ -6908,8 +7288,8 @@
6908
7288
  return a.call(this, str, $.proxy(function (d) {
6909
7289
  if(d && d.d) { d = d.d; }
6910
7290
  this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () {
6911
- this.search(str, true, show_only_matches, inside, append);
6912
- }, true);
7291
+ this.search(str, true, show_only_matches, inside, append, show_only_matches_children);
7292
+ });
6913
7293
  }, this), inside);
6914
7294
  }
6915
7295
  else {
@@ -6919,7 +7299,10 @@
6919
7299
  if(inside) {
6920
7300
  a.data.inside = inside;
6921
7301
  }
6922
- return $.ajax(a)
7302
+ if (this._data.search.lastRequest) {
7303
+ this._data.search.lastRequest.abort();
7304
+ }
7305
+ this._data.search.lastRequest = $.ajax(a)
6923
7306
  .fail($.proxy(function () {
6924
7307
  this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'search', 'id' : 'search_01', 'reason' : 'Could not load search parents', 'data' : JSON.stringify(a) };
6925
7308
  this.settings.core.error.call(this, this._data.core.last_error);
@@ -6927,9 +7310,10 @@
6927
7310
  .done($.proxy(function (d) {
6928
7311
  if(d && d.d) { d = d.d; }
6929
7312
  this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () {
6930
- this.search(str, true, show_only_matches, inside, append);
6931
- }, true);
7313
+ this.search(str, true, show_only_matches, inside, append, show_only_matches_children);
7314
+ });
6932
7315
  }, this));
7316
+ return this._data.search.lastRequest;
6933
7317
  }
6934
7318
  }
6935
7319
  if(!append) {
@@ -6944,7 +7328,7 @@
6944
7328
  f = new $.vakata.search(str, true, { caseSensitive : s.case_sensitive, fuzzy : s.fuzzy });
6945
7329
  $.each(m[inside ? inside : $.jstree.root].children_d, function (ii, i) {
6946
7330
  var v = m[i];
6947
- 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) ) ) {
7331
+ if(v.text && !v.state.hidden && (!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) ) ) {
6948
7332
  r.push(i);
6949
7333
  p = p.concat(v.parents);
6950
7334
  }
@@ -7342,6 +7726,8 @@
7342
7726
  * * `max_depth` the maximum number of nesting this node type can have. A value of `1` would mean that the node can have children, but no grandchildren. Do not specify or set to `-1` for unlimited.
7343
7727
  * * `valid_children` an array of node type strings, that nodes of this type can have as children. Do not specify or set to `-1` for no limits.
7344
7728
  * * `icon` a string - can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class. Omit to use the default icon from your theme.
7729
+ * * `li_attr` an object of values which will be used to add HTML attributes on the resulting LI DOM node (merged with the node's own data)
7730
+ * * `a_attr` an object of values which will be used to add HTML attributes on the resulting A DOM node (merged with the node's own data)
7345
7731
  *
7346
7732
  * There are two predefined types:
7347
7733
  *
@@ -7383,7 +7769,7 @@
7383
7769
  var m = this._model.data,
7384
7770
  dpc = data.nodes,
7385
7771
  t = this.settings.types,
7386
- i, j, c = 'default';
7772
+ i, j, c = 'default', k;
7387
7773
  for(i = 0, j = dpc.length; i < j; i++) {
7388
7774
  c = 'default';
7389
7775
  if(m[dpc[i]].original && m[dpc[i]].original.type && t[m[dpc[i]].original.type]) {
@@ -7396,6 +7782,39 @@
7396
7782
  if(m[dpc[i]].icon === true && t[c].icon !== undefined) {
7397
7783
  m[dpc[i]].icon = t[c].icon;
7398
7784
  }
7785
+ if(t[c].li_attr !== undefined && typeof t[c].li_attr === 'object') {
7786
+ for (k in t[c].li_attr) {
7787
+ if (t[c].li_attr.hasOwnProperty(k)) {
7788
+ if (k === 'id') {
7789
+ continue;
7790
+ }
7791
+ else if (m[dpc[i]].li_attr[k] === undefined) {
7792
+ m[dpc[i]].li_attr[k] = t[c].li_attr[k];
7793
+ }
7794
+ else if (k === 'class') {
7795
+ m[dpc[i]].li_attr['class'] = t[c].li_attr['class'] + ' ' + m[dpc[i]].li_attr['class'];
7796
+ }
7797
+ }
7798
+ }
7799
+ }
7800
+ if(t[c].a_attr !== undefined && typeof t[c].a_attr === 'object') {
7801
+ for (k in t[c].a_attr) {
7802
+ if (t[c].a_attr.hasOwnProperty(k)) {
7803
+ if (k === 'id') {
7804
+ continue;
7805
+ }
7806
+ else if (m[dpc[i]].a_attr[k] === undefined) {
7807
+ m[dpc[i]].a_attr[k] = t[c].a_attr[k];
7808
+ }
7809
+ else if (k === 'href' && m[dpc[i]].a_attr[k] === '#') {
7810
+ m[dpc[i]].a_attr['href'] = t[c].a_attr['href'];
7811
+ }
7812
+ else if (k === 'class') {
7813
+ m[dpc[i]].a_attr['class'] = t[c].a_attr['class'] + ' ' + m[dpc[i]].a_attr['class'];
7814
+ }
7815
+ }
7816
+ }
7817
+ }
7399
7818
  }
7400
7819
  m[$.jstree.root].type = $.jstree.root;
7401
7820
  }, this));
@@ -7526,7 +7945,7 @@
7526
7945
  * @plugin types
7527
7946
  */
7528
7947
  this.set_type = function (obj, type) {
7529
- var t, t1, t2, old_type, old_icon;
7948
+ var m = this._model.data, t, t1, t2, old_type, old_icon, k, d, a;
7530
7949
  if($.isArray(obj)) {
7531
7950
  obj = obj.slice();
7532
7951
  for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
@@ -7537,18 +7956,120 @@
7537
7956
  t = this.settings.types;
7538
7957
  obj = this.get_node(obj);
7539
7958
  if(!t[type] || !obj) { return false; }
7959
+ d = this.get_node(obj, true);
7960
+ if (d && d.length) {
7961
+ a = d.children('.jstree-anchor');
7962
+ }
7540
7963
  old_type = obj.type;
7541
7964
  old_icon = this.get_icon(obj);
7542
7965
  obj.type = type;
7543
- if(old_icon === true || (t[old_type] && t[old_type].icon !== undefined && old_icon === t[old_type].icon)) {
7966
+ if(old_icon === true || !t[old_type] || (t[old_type].icon !== undefined && old_icon === t[old_type].icon)) {
7544
7967
  this.set_icon(obj, t[type].icon !== undefined ? t[type].icon : true);
7545
7968
  }
7969
+
7970
+ // remove old type props
7971
+ if(t[old_type] && t[old_type].li_attr !== undefined && typeof t[old_type].li_attr === 'object') {
7972
+ for (k in t[old_type].li_attr) {
7973
+ if (t[old_type].li_attr.hasOwnProperty(k)) {
7974
+ if (k === 'id') {
7975
+ continue;
7976
+ }
7977
+ else if (k === 'class') {
7978
+ m[obj.id].li_attr['class'] = (m[obj.id].li_attr['class'] || '').replace(t[old_type].li_attr[k], '');
7979
+ if (d) { d.removeClass(t[old_type].li_attr[k]); }
7980
+ }
7981
+ else if (m[obj.id].li_attr[k] === t[old_type].li_attr[k]) {
7982
+ m[obj.id].li_attr[k] = null;
7983
+ if (d) { d.removeAttr(k); }
7984
+ }
7985
+ }
7986
+ }
7987
+ }
7988
+ if(t[old_type] && t[old_type].a_attr !== undefined && typeof t[old_type].a_attr === 'object') {
7989
+ for (k in t[old_type].a_attr) {
7990
+ if (t[old_type].a_attr.hasOwnProperty(k)) {
7991
+ if (k === 'id') {
7992
+ continue;
7993
+ }
7994
+ else if (k === 'class') {
7995
+ m[obj.id].a_attr['class'] = (m[obj.id].a_attr['class'] || '').replace(t[old_type].a_attr[k], '');
7996
+ if (a) { a.removeClass(t[old_type].a_attr[k]); }
7997
+ }
7998
+ else if (m[obj.id].a_attr[k] === t[old_type].a_attr[k]) {
7999
+ if (k === 'href') {
8000
+ m[obj.id].a_attr[k] = '#';
8001
+ if (a) { a.attr('href', '#'); }
8002
+ }
8003
+ else {
8004
+ delete m[obj.id].a_attr[k];
8005
+ if (a) { a.removeAttr(k); }
8006
+ }
8007
+ }
8008
+ }
8009
+ }
8010
+ }
8011
+
8012
+ // add new props
8013
+ if(t[type].li_attr !== undefined && typeof t[type].li_attr === 'object') {
8014
+ for (k in t[type].li_attr) {
8015
+ if (t[type].li_attr.hasOwnProperty(k)) {
8016
+ if (k === 'id') {
8017
+ continue;
8018
+ }
8019
+ else if (m[obj.id].li_attr[k] === undefined) {
8020
+ m[obj.id].li_attr[k] = t[type].li_attr[k];
8021
+ if (d) {
8022
+ if (k === 'class') {
8023
+ d.addClass(t[type].li_attr[k]);
8024
+ }
8025
+ else {
8026
+ d.attr(k, t[type].li_attr[k]);
8027
+ }
8028
+ }
8029
+ }
8030
+ else if (k === 'class') {
8031
+ m[obj.id].li_attr['class'] = t[type].li_attr[k] + ' ' + m[obj.id].li_attr['class'];
8032
+ if (d) { d.addClass(t[type].li_attr[k]); }
8033
+ }
8034
+ }
8035
+ }
8036
+ }
8037
+ if(t[type].a_attr !== undefined && typeof t[type].a_attr === 'object') {
8038
+ for (k in t[type].a_attr) {
8039
+ if (t[type].a_attr.hasOwnProperty(k)) {
8040
+ if (k === 'id') {
8041
+ continue;
8042
+ }
8043
+ else if (m[obj.id].a_attr[k] === undefined) {
8044
+ m[obj.id].a_attr[k] = t[type].a_attr[k];
8045
+ if (a) {
8046
+ if (k === 'class') {
8047
+ a.addClass(t[type].a_attr[k]);
8048
+ }
8049
+ else {
8050
+ a.attr(k, t[type].a_attr[k]);
8051
+ }
8052
+ }
8053
+ }
8054
+ else if (k === 'href' && m[obj.id].a_attr[k] === '#') {
8055
+ m[obj.id].a_attr['href'] = t[type].a_attr['href'];
8056
+ if (a) { a.attr('href', t[type].a_attr['href']); }
8057
+ }
8058
+ else if (k === 'class') {
8059
+ m[obj.id].a_attr['class'] = t[type].a_attr['class'] + ' ' + m[obj.id].a_attr['class'];
8060
+ if (a) { a.addClass(t[type].a_attr[k]); }
8061
+ }
8062
+ }
8063
+ }
8064
+ }
8065
+
7546
8066
  return true;
7547
8067
  };
7548
8068
  };
7549
8069
  // include the types plugin by default
7550
8070
  // $.jstree.defaults.plugins.push("types");
7551
8071
 
8072
+
7552
8073
  /**
7553
8074
  * ### Unique plugin
7554
8075
  *
@@ -7699,9 +8220,11 @@
7699
8220
  this.get_node(data.node, true).children('.jstree-wholerow')[e.type === "hover_node"?"addClass":"removeClass"]('jstree-wholerow-hovered');
7700
8221
  }, this))
7701
8222
  .on("contextmenu.jstree", ".jstree-wholerow", $.proxy(function (e) {
7702
- e.preventDefault();
7703
- var tmp = $.Event('contextmenu', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey, pageX : e.pageX, pageY : e.pageY });
7704
- $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp);
8223
+ if (this._data.contextmenu) {
8224
+ e.preventDefault();
8225
+ var tmp = $.Event('contextmenu', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey, pageX : e.pageX, pageY : e.pageY });
8226
+ $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp);
8227
+ }
7705
8228
  }, this))
7706
8229
  /*!
7707
8230
  .on("mousedown.jstree touchstart.jstree", ".jstree-wholerow", function (e) {
@@ -7717,6 +8240,11 @@
7717
8240
  var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey });
7718
8241
  $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus();
7719
8242
  })
8243
+ .on("dblclick.jstree", ".jstree-wholerow", function (e) {
8244
+ e.stopImmediatePropagation();
8245
+ var tmp = $.Event('dblclick', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey });
8246
+ $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus();
8247
+ })
7720
8248
  .on("click.jstree", ".jstree-leaf > .jstree-ocl", $.proxy(function (e) {
7721
8249
  e.stopImmediatePropagation();
7722
8250
  var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey });