billy_cms 0.0.15 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 });