fancytree-rails 2.0.0.pre.11.pre.1 → 2.1.0.pre.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/3th-party/jquery-ui.License.txt +2 -0
  3. data/README.md +7 -1
  4. data/Rakefile +21 -5
  5. data/{vendor → app}/assets/images/fancytree/icons.gif +0 -0
  6. data/{vendor → app}/assets/images/fancytree/loading.gif +0 -0
  7. data/app/assets/images/fancytree/skin-lion/icons.gif +0 -0
  8. data/{vendor → app}/assets/images/fancytree/skin-lion/loading.gif +0 -0
  9. data/app/assets/images/fancytree/skin-themeroller/icons.gif +0 -0
  10. data/{vendor → app}/assets/images/fancytree/skin-themeroller/loading.gif +0 -0
  11. data/app/assets/images/fancytree/skin-vista/icons.gif +0 -0
  12. data/{vendor → app}/assets/images/fancytree/skin-vista/loading.gif +0 -0
  13. data/app/assets/images/fancytree/skin-win7/icons.gif +0 -0
  14. data/{vendor → app}/assets/images/fancytree/skin-win7/loading.gif +0 -0
  15. data/{vendor → app}/assets/images/fancytree/skin-win8-xxl/icons.gif +0 -0
  16. data/{vendor → app}/assets/images/fancytree/skin-win8-xxl/loading.gif +0 -0
  17. data/app/assets/images/fancytree/skin-win8/icons.gif +0 -0
  18. data/{vendor → app}/assets/images/fancytree/skin-win8/loading.gif +0 -0
  19. data/{vendor → app}/assets/images/fancytree/skin-xp/icons-rtl.gif +0 -0
  20. data/{vendor → app}/assets/images/fancytree/skin-xp/icons.gif +0 -0
  21. data/{vendor → app}/assets/images/fancytree/skin-xp/loading.gif +0 -0
  22. data/{vendor → app}/assets/images/fancytree/skin-xp/vline-rtl.gif +0 -0
  23. data/{vendor → app}/assets/images/fancytree/skin-xp/vline.gif +0 -0
  24. data/{vendor → app}/assets/javascripts/fancytree.js +0 -0
  25. data/{vendor → app}/assets/javascripts/fancytree/MIT-LICENSE.txt +0 -0
  26. data/{vendor → app}/assets/javascripts/fancytree/jquery.fancytree-all.js +346 -333
  27. data/app/assets/javascripts/fancytree/jquery.fancytree-custom.min.js +41 -0
  28. data/{vendor → app}/assets/javascripts/fancytree/jquery.fancytree.js +109 -66
  29. data/app/assets/javascripts/fancytree/jquery.fancytree.min.js +14 -0
  30. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.childcounter.js +3 -3
  31. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.clones.js +36 -6
  32. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.columnview.js +2 -2
  33. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.debug.js +2 -2
  34. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.dnd.js +35 -51
  35. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.edit.js +5 -9
  36. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.filter.js +54 -66
  37. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.glyph.js +6 -9
  38. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.gridnav.js +2 -2
  39. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.js +109 -66
  40. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.menu.js +2 -2
  41. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.persist.js +106 -112
  42. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.table.js +23 -9
  43. data/{vendor → app}/assets/javascripts/fancytree/src/jquery.fancytree.themeroller.js +3 -6
  44. data/{vendor/assets/stylesheets/fancytree/skin-awesome/ui.fancytree.css → app/assets/stylesheets/fancytree/skin-awesome/ui.fancytree.css.erb} +30 -5
  45. data/app/assets/stylesheets/fancytree/skin-awesome/ui.fancytree.min.css.erb +6 -0
  46. data/{vendor/assets/stylesheets/fancytree/skin-bootstrap/ui.fancytree.css → app/assets/stylesheets/fancytree/skin-bootstrap/ui.fancytree.css.erb} +31 -6
  47. data/app/assets/stylesheets/fancytree/skin-bootstrap/ui.fancytree.min.css.erb +6 -0
  48. data/{vendor/assets/stylesheets/fancytree/skin-lion/ui.fancytree.css → app/assets/stylesheets/fancytree/skin-lion/ui.fancytree.css.erb} +35 -14
  49. data/app/assets/stylesheets/fancytree/skin-lion/ui.fancytree.min.css.erb +6 -0
  50. data/{vendor/assets/stylesheets/fancytree/skin-themeroller/ui.fancytree.css → app/assets/stylesheets/fancytree/skin-themeroller/ui.fancytree.css.erb} +1 -1
  51. data/{vendor/assets/stylesheets/fancytree/skin-themeroller/ui.fancytree.min.css → app/assets/stylesheets/fancytree/skin-themeroller/ui.fancytree.min.css.erb} +0 -0
  52. data/{vendor/assets/stylesheets/fancytree/skin-vista/ui.fancytree.css → app/assets/stylesheets/fancytree/skin-vista/ui.fancytree.css.erb} +35 -14
  53. data/app/assets/stylesheets/fancytree/skin-vista/ui.fancytree.min.css.erb +6 -0
  54. data/{vendor/assets/stylesheets/fancytree/skin-win7/ui.fancytree.css → app/assets/stylesheets/fancytree/skin-win7/ui.fancytree.css.erb} +35 -14
  55. data/app/assets/stylesheets/fancytree/skin-win7/ui.fancytree.min.css.erb +6 -0
  56. data/{vendor/assets/stylesheets/fancytree/skin-win8-xxl/ui.fancytree.css → app/assets/stylesheets/fancytree/skin-win8-xxl/ui.fancytree.css.erb} +37 -16
  57. data/app/assets/stylesheets/fancytree/skin-win8-xxl/ui.fancytree.min.css.erb +11 -0
  58. data/{vendor/assets/stylesheets/fancytree/skin-win8/ui.fancytree.css → app/assets/stylesheets/fancytree/skin-win8/ui.fancytree.css.erb} +37 -16
  59. data/app/assets/stylesheets/fancytree/skin-win8/ui.fancytree.min.css.erb +6 -0
  60. data/{vendor/assets/stylesheets/fancytree/skin-xp/ui.fancytree.css → app/assets/stylesheets/fancytree/skin-xp/ui.fancytree.css.erb} +35 -14
  61. data/app/assets/stylesheets/fancytree/skin-xp/ui.fancytree.min.css.erb +6 -0
  62. data/{vendor → app}/assets/stylesheets/ui.fancytree.css +0 -0
  63. data/lib/fancytree/rails/version.rb +2 -2
  64. metadata +77 -76
  65. data/vendor/assets/images/fancytree/skin-lion/icons.gif +0 -0
  66. data/vendor/assets/images/fancytree/skin-themeroller/icons.gif +0 -0
  67. data/vendor/assets/images/fancytree/skin-vista/icons.gif +0 -0
  68. data/vendor/assets/images/fancytree/skin-win7/icons.gif +0 -0
  69. data/vendor/assets/images/fancytree/skin-win8/icons.gif +0 -0
  70. data/vendor/assets/javascripts/fancytree/jquery.fancytree-custom.min.js +0 -41
  71. data/vendor/assets/javascripts/fancytree/jquery.fancytree.min.js +0 -14
  72. data/vendor/assets/stylesheets/fancytree/skin-awesome/ui.fancytree.min.css +0 -6
  73. data/vendor/assets/stylesheets/fancytree/skin-bootstrap/ui.fancytree.min.css +0 -6
  74. data/vendor/assets/stylesheets/fancytree/skin-lion/ui.fancytree.min.css +0 -6
  75. data/vendor/assets/stylesheets/fancytree/skin-vista/ui.fancytree.min.css +0 -6
  76. data/vendor/assets/stylesheets/fancytree/skin-win7/ui.fancytree.min.css +0 -6
  77. data/vendor/assets/stylesheets/fancytree/skin-win8-xxl/ui.fancytree.min.css +0 -11
  78. data/vendor/assets/stylesheets/fancytree/skin-win8/ui.fancytree.min.css +0 -6
  79. data/vendor/assets/stylesheets/fancytree/skin-xp/ui.fancytree.min.css +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1f8597dbe02db0bcac1ca59245d2b4b1ef806241
4
- data.tar.gz: 6f23c661681871ae96ea0f8e6bf6408c3c8f1031
3
+ metadata.gz: 5a8617873a677ecca45f5f10e1878b044e209a57
4
+ data.tar.gz: d48c2f46d24a79dace0daf77f3e395f0d797ebcf
5
5
  SHA512:
6
- metadata.gz: fd9930807b36cffe63374ee0ecc41dd5d8c334300122d27379ed07136eb7aa099b0f2a2842574e7fc3818338a196e214c0d4eefc6a64cae78484640ab550805a
7
- data.tar.gz: 1d1e2ab886857144211259f04c889765b75ee3b22ad7422b2716754c5cf971ec327ba880cc43aa0149eb03600981e18f4d38e25bcc4c602b5cd0cdc16a172a90
6
+ metadata.gz: 958f86489eb8b3742f11b524c80a513fa64343820821c40ec4ff3bd9bc4b0e7f0da21746980a1ea45cf2ea07b03d8ead4341f531dd10e20313f819797b003016
7
+ data.tar.gz: 6651dc979969d811827f7f1aaa95774600ee234087d73ec82dcf5239c484943f8e81f3b6731e1728ecd84167068d3845c1a2959912016c3bac6a5f599f08ef2b
@@ -0,0 +1,2 @@
1
+ jQuery UI as well as this gem are licensed under the MIT license (see
2
+ jquery-ui/MIT-LICENSE.txt).
data/README.md CHANGED
@@ -53,10 +53,16 @@ Note that for awesome style (extension) to work you to:
53
53
  2. Enable ```awesome``` extension in Fancytree.
54
54
  3. Include extension code (```//= require fancytree/jquery.fancytree.awesome```) to ```app/assets/javascripts/application.js```.
55
55
 
56
+ ## Credits
57
+
58
+ Pice of code of Raikefile copied form joliss/jquery-ui-rails. See
59
+ 3th-party for its license.
60
+
56
61
  ## Contributing
57
62
 
58
63
  1. Fork it
59
- 2. Create your feature branch (`git checkout -b my-new-feature`)
64
+ 2. Create your feature branch (`git checkout -b my-new-feature`). You
65
+ can use rake fancytree:update for semiautomatic update of mar10/fancytree
60
66
  3. Commit your changes (`git commit -am 'Add some feature'`)
61
67
  4. Push to the branch (`git push origin my-new-feature`)
62
68
  5. Create new Pull Request
data/Rakefile CHANGED
@@ -2,6 +2,14 @@ require "bundler/gem_tasks"
2
2
  require 'fileutils'
3
3
  require 'fancytree/rails/version'
4
4
 
5
+ def build_image_dependencies(source_code)
6
+ image_dependencies = Set.new source_code.scan(/url\("?images\/([-_.a-zA-Z0-9]+)"?\)/).map(&:first)
7
+ code = image_dependencies.inject("") do |acc, img|
8
+ acc += " *= depend_on_asset \"jquery-ui/#{img}\"\n"
9
+ end
10
+ end
11
+
12
+
5
13
  namespace :fancytree do
6
14
  desc "Update FancyTree library from current version"
7
15
  task :update => :build do
@@ -9,18 +17,26 @@ namespace :fancytree do
9
17
 
10
18
  cd "dist" do
11
19
  js = FileList['*'].exclude(/\Askip*/)
12
- FileUtils.cp_r(js, '../../../vendor/assets/javascripts/fancytree')
20
+ FileUtils.cp_r(js, '../../../app/assets/javascripts/fancytree')
13
21
 
14
22
  css_files = Dir.glob("skin*/*.css")
15
23
  css_files.each do |file|
16
- mkdir_p "../../../vendor/assets/stylesheets/fancytree/#{File.dirname(file)}"
17
- FileUtils.cp file, "../../../vendor/assets/stylesheets/fancytree/#{file}"
24
+ source_code = File.read(file)
25
+ #source_code.gsub!(/url\("?images\/([-_.a-zA-Z0-9]+)"?\)/, 'url(<%= image_path("fancytree/\1") %>)')
26
+ source_code.gsub!(/url\("icons.gif"\)/, 'url(<%= image_path("fancytree/icons.gif") %>)')
27
+ source_code.gsub!(/\A(\/\*!.+?\*\/\s)/m, "\\1\n/*\n#{build_image_dependencies(source_code)} */\n\n") unless build_image_dependencies(source_code).empty?
28
+
29
+ output_path = "../../../app/assets/stylesheets/fancytree/#{file}.erb"
30
+ mkdir_p File.dirname(output_path)
31
+ File.open(output_path, "w") do |out|
32
+ out.write(source_code)
33
+ end
18
34
  end
19
35
 
20
36
  images_files = Dir.glob("skin*/*.gif")
21
37
  images_files.each do |file|
22
- mkdir_p "../../../vendor/assets/images/fancytree/#{File.dirname(file)}"
23
- FileUtils.cp file, "../../../vendor/assets/images/fancytree/#{file}"
38
+ mkdir_p "../../../app/assets/images/fancytree/#{File.dirname(file)}"
39
+ FileUtils.cp file, "../../../app/assets/images/fancytree/#{file}"
24
40
  end
25
41
  end
26
42
 
File without changes
File without changes
File without changes
@@ -7,8 +7,8 @@
7
7
  * Released under the MIT license
8
8
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
9
9
  *
10
- * @version 2.0.0-11
11
- * @date 2014-04-27T22:28
10
+ * @version 2.1.0
11
+ * @date 2014-05-29T16:44
12
12
  */
13
13
 
14
14
  /** Core Fancytree module.
@@ -61,6 +61,11 @@ function consoleApply(method, args){
61
61
  }
62
62
  }
63
63
 
64
+ /*Return true if x is a FancytreeNode.*/
65
+ function _isNode(x){
66
+ return !!(x.tree && x.statusNodeType !== undefined);
67
+ }
68
+
64
69
  /** Return true if dotted version string is equal or higher than requested version.
65
70
  *
66
71
  * See http://jsfiddle.net/mar10/FjSAN/
@@ -275,6 +280,8 @@ function FancytreeNode(parent, obj){
275
280
  } else {
276
281
  this.key = "_" + (FT._nextNodeKey++);
277
282
  }
283
+ } else {
284
+ this.key = "" + this.key; // Convert to string (#217)
278
285
  }
279
286
 
280
287
  // Fix tree.activeNode
@@ -683,9 +690,8 @@ FancytreeNode.prototype = /** @lends FancytreeNode# */{
683
690
  // recursively set children and render
684
691
  this.removeChildren();
685
692
  this.addChildren(dict.children);
686
- }else{
687
- this.renderTitle();
688
693
  }
694
+ this.renderTitle();
689
695
  /*
690
696
  var children = dict.children;
691
697
  if(children === undefined){
@@ -1350,79 +1356,93 @@ FancytreeNode.prototype = /** @lends FancytreeNode# */{
1350
1356
  /**
1351
1357
  *
1352
1358
  * @param {boolean | PlainObject} [effects=false] animation options.
1353
- * @param {FancytreeNode} [topNode=null] this node will remain visible in
1359
+ * @param {object} [options=null] {topNode: null, effects: ..., parent: ...} this node will remain visible in
1354
1360
  * any case, even if `this` is outside the scroll pane.
1355
1361
  * @returns {$.Promise}
1356
1362
  */
1357
- scrollIntoView: function(effects, topNode) {
1358
- effects = (effects === true) ? {duration: 200, queue: false} : effects;
1359
- var topNodeY,
1363
+ scrollIntoView: function(effects, options) {
1364
+ if( options !== undefined && _isNode(options) ) {
1365
+ this.warn("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead.");
1366
+ options = {topNode: options};
1367
+ }
1368
+ // this.$scrollParent = (this.options.scrollParent === "auto") ? $ul.scrollParent() : $(this.options.scrollParent);
1369
+ // this.$scrollParent = this.$scrollParent.length ? this.$scrollParent || this.$container;
1370
+
1371
+ var topNodeY, nodeY, horzScrollbarHeight, containerOffsetTop,
1372
+ opts = $.extend({
1373
+ effects: (effects === true) ? {duration: 200, queue: false} : effects,
1374
+ scrollOfs: this.tree.options.scrollOfs,
1375
+ scrollParent: this.tree.options.scrollParent || this.tree.$container,
1376
+ topNode: null
1377
+ }, options),
1360
1378
  dfd = new $.Deferred(),
1361
1379
  that = this,
1362
- nodeY = $(this.span).position().top,
1363
1380
  nodeHeight = $(this.span).height(),
1364
- $container = this.tree.$container,
1365
- scrollTop = $container[0].scrollTop,
1366
- horzScrollHeight = Math.max(0, ($container.innerHeight() - $container[0].clientHeight)),
1367
- // containerHeight = $container.height(),
1368
- containerHeight = $container.height() - horzScrollHeight,
1381
+ $container = $(opts.scrollParent),
1382
+ topOfs = opts.scrollOfs.top || 0,
1383
+ bottomOfs = opts.scrollOfs.bottom || 0,
1384
+ containerHeight = $container.height(),// - topOfs - bottomOfs,
1385
+ scrollTop = $container.scrollTop(),
1386
+ $animateTarget = $container,
1387
+ isParentWindow = $container[0] === window,
1388
+ topNode = opts.topNode || null,
1369
1389
  newScrollTop = null;
1370
1390
 
1371
- // console.log("horzScrollHeight: " + horzScrollHeight);
1372
- // console.log("$container[0].scrollTop: " + $container[0].scrollTop);
1373
- // console.log("$container[0].scrollHeight: " + $container[0].scrollHeight);
1374
- // console.log("$container[0].clientHeight: " + $container[0].clientHeight);
1375
- // console.log("$container.innerHeight(): " + $container.innerHeight());
1376
- // console.log("$container.height(): " + $container.height());
1377
-
1378
- if(nodeY < 0){
1379
- newScrollTop = scrollTop + nodeY;
1380
- }else if((nodeY + nodeHeight) > containerHeight){
1381
- newScrollTop = scrollTop + nodeY - containerHeight + nodeHeight;
1391
+ // this.debug("scrollIntoView(), scrollTop=", scrollTop, opts.scrollOfs);
1392
+ _assert($(this.span).is(":visible"), "scrollIntoView node is invisible"); // otherwise we cannot calc offsets
1393
+
1394
+ if( isParentWindow ) {
1395
+ nodeY = $(this.span).offset().top;
1396
+ topNodeY = topNode ? $(topNode.span).offset().top : 0;
1397
+ $animateTarget = $("html,body");
1398
+
1399
+ } else {
1400
+ _assert($container[0] !== document && $container[0] !== document.body, "scrollParent should be an simple element or `window`, not document or body.");
1401
+
1402
+ containerOffsetTop = $container.offset().top,
1403
+ nodeY = $(this.span).offset().top - containerOffsetTop + scrollTop; // relative to scroll parent
1404
+ topNodeY = topNode ? $(topNode.span).offset().top - containerOffsetTop + scrollTop : 0;
1405
+ horzScrollbarHeight = Math.max(0, ($container.innerHeight() - $container[0].clientHeight));
1406
+ containerHeight -= horzScrollbarHeight;
1407
+ }
1408
+
1409
+ // this.debug(" scrollIntoView(), nodeY=", nodeY, "containerHeight=", containerHeight);
1410
+ if( nodeY < (scrollTop + topOfs) ){
1411
+ // Node is above visible container area
1412
+ newScrollTop = nodeY - topOfs;
1413
+ // this.debug(" scrollIntoView(), UPPER newScrollTop=", newScrollTop);
1414
+
1415
+ }else if((nodeY + nodeHeight) > (scrollTop + containerHeight - bottomOfs)){
1416
+ newScrollTop = nodeY + nodeHeight - containerHeight + bottomOfs;
1417
+ // this.debug(" scrollIntoView(), LOWER newScrollTop=", newScrollTop);
1382
1418
  // If a topNode was passed, make sure that it is never scrolled
1383
1419
  // outside the upper border
1384
1420
  if(topNode){
1385
- topNodeY = topNode ? $(topNode.span).position().top : 0;
1386
- if((nodeY - topNodeY) > containerHeight){
1387
- newScrollTop = scrollTop + topNodeY;
1421
+ _assert($(topNode.span).is(":visible"));
1422
+ if( topNodeY < newScrollTop ){
1423
+ newScrollTop = topNodeY - topOfs;
1424
+ // this.debug(" scrollIntoView(), TOP newScrollTop=", newScrollTop);
1388
1425
  }
1389
1426
  }
1390
1427
  }
1428
+
1391
1429
  if(newScrollTop !== null){
1392
- if(effects){
1393
- // TODO: resolve dfd after animation
1394
- // var that = this;
1395
- effects.complete = function(){
1430
+ // this.debug(" scrollIntoView(), SET newScrollTop=", newScrollTop);
1431
+ if(opts.effects){
1432
+ opts.effects.complete = function(){
1396
1433
  dfd.resolveWith(that);
1397
1434
  };
1398
- $container.animate({
1435
+ $animateTarget.stop(true).animate({
1399
1436
  scrollTop: newScrollTop
1400
- }, effects);
1437
+ }, opts.effects);
1401
1438
  }else{
1402
- $container[0].scrollTop = newScrollTop;
1439
+ $animateTarget[0].scrollTop = newScrollTop;
1403
1440
  dfd.resolveWith(this);
1404
1441
  }
1405
1442
  }else{
1406
1443
  dfd.resolveWith(this);
1407
1444
  }
1408
1445
  return dfd.promise();
1409
- /* from jQuery.menu:
1410
- var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
1411
- if ( this._hasScroll() ) {
1412
- borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
1413
- paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
1414
- offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
1415
- scroll = this.activeMenu.scrollTop();
1416
- elementHeight = this.activeMenu.height();
1417
- itemHeight = item.height();
1418
-
1419
- if ( offset < 0 ) {
1420
- this.activeMenu.scrollTop( scroll + offset );
1421
- } else if ( offset + itemHeight > elementHeight ) {
1422
- this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
1423
- }
1424
- }
1425
- */
1426
1446
  },
1427
1447
 
1428
1448
  /**Activate this node.
@@ -2817,8 +2837,8 @@ $.extend(Fancytree.prototype,
2817
2837
  // folder or doctype icon
2818
2838
  role = aria ? " role='img'" : "";
2819
2839
  if ( icon && typeof icon === "string" ) {
2820
- imageSrc = (icon.charAt(0) === "/") ? icon : (opts.imagePath + icon);
2821
- ares.push("<img src='" + imageSrc + "' alt='' />");
2840
+ imageSrc = (icon.charAt(0) === "/") ? icon : ((opts.imagePath || "") + icon);
2841
+ ares.push("<img src='" + imageSrc + "' class='fancytree-icon' alt='' />");
2822
2842
  } else if ( node.data.iconclass ) {
2823
2843
  // TODO: review and test and document
2824
2844
  ares.push("<span " + role + " class='fancytree-custom-icon" + " " + node.data.iconclass + "'></span>");
@@ -2834,7 +2854,6 @@ $.extend(Fancytree.prototype,
2834
2854
  nodeTitle = opts.renderTitle.call(tree, {type: "renderTitle"}, ctx) || "";
2835
2855
  }
2836
2856
  if(!nodeTitle){
2837
- // TODO: escape tooltip string
2838
2857
  tooltip = node.tooltip ? " title='" + FT.escapeHtml(node.tooltip) + "'" : "";
2839
2858
  id = aria ? " id='ftal_" + node.key + "'" : "";
2840
2859
  role = aria ? " role='treeitem'" : "";
@@ -2979,7 +2998,6 @@ $.extend(Fancytree.prototype,
2979
2998
  node = ctx.node,
2980
2999
  tree = ctx.tree,
2981
3000
  opts = ctx.options,
2982
- // userEvent = !!ctx.originalEvent,
2983
3001
  noEvents = (callOpts.noEvents === true),
2984
3002
  isActive = (node === tree.activeNode);
2985
3003
 
@@ -3003,7 +3021,7 @@ $.extend(Fancytree.prototype,
3003
3021
  }
3004
3022
  if(opts.activeVisible){
3005
3023
  // tree.nodeMakeVisible(ctx);
3006
- node.makeVisible();
3024
+ node.makeVisible({scrollIntoView: false}); // nodeSetFocus will scroll
3007
3025
  }
3008
3026
  tree.activeNode = node;
3009
3027
  tree.nodeRenderStatus(ctx);
@@ -3080,9 +3098,9 @@ $.extend(Fancytree.prototype,
3080
3098
  }
3081
3099
  // Trigger expand/collapse after expanding
3082
3100
  dfd.done(function(){
3083
- if( opts.autoScroll && !noAnimation ) {
3101
+ if( flag && opts.autoScroll && !noAnimation ) {
3084
3102
  // Scroll down to last child, but keep current node visible
3085
- node.getLastChild().scrollIntoView(true, node).always(function(){
3103
+ node.getLastChild().scrollIntoView(true, {topNode: node}).always(function(){
3086
3104
  if( !noEvents ) {
3087
3105
  ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
3088
3106
  }
@@ -3093,7 +3111,6 @@ $.extend(Fancytree.prototype,
3093
3111
  }
3094
3112
  }
3095
3113
  });
3096
-
3097
3114
  // vvv Code below is executed after loading finished:
3098
3115
  _afterLoad = function(callback){
3099
3116
  var duration, easing, isVisible, isExpanded;
@@ -3201,7 +3218,7 @@ $.extend(Fancytree.prototype,
3201
3218
  this._callHook("treeSetFocus", ctx, true, true);
3202
3219
  }
3203
3220
  // this.nodeMakeVisible(ctx);
3204
- node.makeVisible();
3221
+ node.makeVisible({scrollIntoView: false});
3205
3222
  tree.focusNode = node;
3206
3223
  // node.debug("FOCUS...");
3207
3224
  // $(node.span).find(".fancytree-title").focus();
@@ -3512,6 +3529,8 @@ $.widget("ui.fancytree",
3512
3529
  keyboard: true,
3513
3530
  keyPathSeparator: "/",
3514
3531
  minExpandLevel: 1,
3532
+ scrollOfs: {top: 0, bottom: 0},
3533
+ scrollParent: null,
3515
3534
  selectMode: 2,
3516
3535
  strings: {
3517
3536
  loading: "Loading&#8230;",
@@ -3772,7 +3791,7 @@ $.extend($.ui.fancytree,
3772
3791
  /** @lends Fancytree_Static# */
3773
3792
  {
3774
3793
  /** @type {string} */
3775
- version: "2.0.0-11", // Set to semver by 'grunt release'
3794
+ version: "2.1.0", // Set to semver by 'grunt release'
3776
3795
  /** @type {string} */
3777
3796
  buildType: "production", // Set to 'production' by 'grunt build'
3778
3797
  /** @type {int} */
@@ -3800,6 +3819,29 @@ $.extend($.ui.fancytree,
3800
3819
  assert: function(cond, msg){
3801
3820
  return _assert(cond, msg);
3802
3821
  },
3822
+ /** Return a function that executes *fn* at most every *timeout* ms.
3823
+ * @param {integer} timeout
3824
+ * @param {function} fn
3825
+ * @param {boolean} [invokeAsap=false]
3826
+ * @param {any} [ctx]
3827
+ */
3828
+ debounce : function(timeout, fn, invokeAsap, ctx) {
3829
+ var timer;
3830
+ if(arguments.length === 3 && typeof invokeAsap !== "boolean") {
3831
+ ctx = invokeAsap;
3832
+ invokeAsap = false;
3833
+ }
3834
+ return function() {
3835
+ var args = arguments;
3836
+ ctx = ctx || this;
3837
+ invokeAsap && !timer && fn.apply(ctx, args);
3838
+ clearTimeout(timer);
3839
+ timer = setTimeout(function() {
3840
+ invokeAsap || fn.apply(ctx, args);
3841
+ timer = null;
3842
+ }, timeout);
3843
+ };
3844
+ },
3803
3845
  /** Write message to console if debugLevel >= 2
3804
3846
  * @param {string} msg
3805
3847
  */
@@ -3850,8 +3892,7 @@ $.extend($.ui.fancytree,
3850
3892
  getEventTarget: function(event){
3851
3893
  var tcn = event && event.target ? event.target.className : "",
3852
3894
  res = {node: this.getNode(event.target), type: undefined};
3853
- // tcn may contains UI themeroller or Font Awesome classes, so we use
3854
- // a fast version of $(res.node).hasClass()
3895
+ // We use a fast version of $(res.node).hasClass()
3855
3896
  // See http://jsperf.com/test-for-classname/2
3856
3897
  if( /\bfancytree-title\b/.test(tcn) ){
3857
3898
  res.type = "title";
@@ -3862,8 +3903,10 @@ $.extend($.ui.fancytree,
3862
3903
  }else if( /\bfancytree-icon\b/.test(tcn) ){
3863
3904
  res.type = "icon";
3864
3905
  }else if( /\bfancytree-node\b/.test(tcn) ){
3865
- // TODO: (http://code.google.com/p/dynatree/issues/detail?id=93)
3866
- // res.type = this._getTypeForOuterNodeEvent(event);
3906
+ // Somewhere near the title
3907
+ res.type = "title";
3908
+ }else if( event && event.target && $(event.target).closest(".fancytree-title").length ) {
3909
+ // #228: clicking an embedded element inside a title
3867
3910
  res.type = "title";
3868
3911
  }
3869
3912
  return res;
@@ -4047,8 +4090,8 @@ $.extend($.ui.fancytree,
4047
4090
  * Released under the MIT license
4048
4091
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
4049
4092
  *
4050
- * @version 2.0.0-11
4051
- * @date 2014-04-27T22:28
4093
+ * @version 2.1.0
4094
+ * @date 2014-05-29T16:44
4052
4095
  */
4053
4096
 
4054
4097
  // To keep the global namespace clean, we wrap everything in a closure
@@ -4170,7 +4213,7 @@ $.ui.fancytree.registerExtension({
4170
4213
  opts = ctx.options,
4171
4214
  extOpts = ctx.options.childcounter;
4172
4215
  // Optionally check for dependencies with other extensions
4173
- // this._requireExtension("glyph", false, false);
4216
+ /* this._requireExtension("glyph", false, false); */
4174
4217
  // Call the base implementation
4175
4218
  this._super(ctx);
4176
4219
  // Add a class to the tree container
@@ -4223,8 +4266,8 @@ $.ui.fancytree.registerExtension({
4223
4266
  * Released under the MIT license
4224
4267
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
4225
4268
  *
4226
- * @version 2.0.0-11
4227
- * @date 2014-04-27T22:28
4269
+ * @version 2.1.0
4270
+ * @date 2014-05-29T16:44
4228
4271
  */
4229
4272
 
4230
4273
  ;(function($, window, document, undefined) {
@@ -4287,8 +4330,7 @@ function _initDragAndDrop(tree) {
4287
4330
  addClasses: false,
4288
4331
  tolerance: "intersect",
4289
4332
  greedy: false
4290
- /*
4291
- ,
4333
+ /*
4292
4334
  activate: function(event, ui) {
4293
4335
  logMsg("droppable - activate", event, ui, this);
4294
4336
  },
@@ -4326,32 +4368,24 @@ function _registerDnd() {
4326
4368
  // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
4327
4369
  var draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
4328
4370
  sourceNode = ui.helper.data("ftSourceNode") || null;
4329
- // logMsg("draggable-connectToFancytree.start, %s", sourceNode);
4330
- // logMsg(" this: %o", this);
4331
- // logMsg(" event: %o", event);
4332
- // logMsg(" draggable: %o", draggable);
4333
- // logMsg(" ui: %o", ui);
4334
4371
 
4335
4372
  if(sourceNode) {
4336
4373
  // Adjust helper offset, so cursor is slightly outside top/left corner
4337
4374
  draggable.offset.click.top = -2;
4338
4375
  draggable.offset.click.left = + 16;
4339
- // logMsg(" draggable2: %o", draggable);
4340
- // logMsg(" draggable.offset.click FIXED: %s/%s", draggable.offset.click.left, draggable.offset.click.top);
4341
4376
  // Trigger dragStart event
4342
4377
  // TODO: when called as connectTo..., the return value is ignored(?)
4343
4378
  return sourceNode.tree.ext.dnd._onDragEvent("start", sourceNode, null, event, ui, draggable);
4344
4379
  }
4345
4380
  },
4346
4381
  drag: function(event, ui) {
4347
- // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
4348
4382
  var isHelper,
4383
+ // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
4349
4384
  draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
4350
4385
  sourceNode = ui.helper.data("ftSourceNode") || null,
4351
4386
  prevTargetNode = ui.helper.data("ftTargetNode") || null,
4352
4387
  targetNode = $.ui.fancytree.getNode(event.target);
4353
- // logMsg("$.ui.fancytree.getNode(%o): %s", event.target, targetNode);
4354
- // logMsg("connectToFancytree.drag: helper: %o", ui.helper[0]);
4388
+
4355
4389
  if(event.target && !targetNode){
4356
4390
  // We got a drag event, but the targetNode could not be found
4357
4391
  // at the event location. This may happen,
@@ -4364,7 +4398,6 @@ function _registerDnd() {
4364
4398
  return;
4365
4399
  }
4366
4400
  }
4367
- // logMsg("draggable-connectToFancytree.drag: targetNode(from event): %s, ftTargetNode: %s", targetNode, ui.helper.data("ftTargetNode"));
4368
4401
  ui.helper.data("ftTargetNode", targetNode);
4369
4402
  // Leaving a tree node
4370
4403
  if(prevTargetNode && prevTargetNode !== targetNode ) {
@@ -4391,10 +4424,7 @@ function _registerDnd() {
4391
4424
  // mouseDownEvent = draggable._mouseDownEvent,
4392
4425
  eventType = event.type,
4393
4426
  dropped = (eventType === "mouseup" && event.which === 1);
4394
- // logMsg("draggable-connectToFancytree.stop: targetNode(from event): %s, ftTargetNode: %s", targetNode, ui.helper.data("ftTargetNode"));
4395
- // logMsg("draggable-connectToFancytree.stop, %s", sourceNode);
4396
- // logMsg(" type: %o, downEvent: %o, upEvent: %o", eventType, mouseDownEvent, event);
4397
- // logMsg(" targetNode: %o", targetNode);
4427
+
4398
4428
  if(!dropped){
4399
4429
  logMsg("Drag was cancelled");
4400
4430
  }
@@ -4418,8 +4448,7 @@ function _registerDnd() {
4418
4448
  *
4419
4449
  */
4420
4450
 
4421
- $.ui.fancytree.registerExtension(
4422
- {
4451
+ $.ui.fancytree.registerExtension({
4423
4452
  name: "dnd",
4424
4453
  version: "0.1.0",
4425
4454
  // Default options for this extension.
@@ -4440,9 +4469,7 @@ $.ui.fancytree.registerExtension(
4440
4469
  draggable: null, // Additional options passed to jQuery draggable
4441
4470
  droppable: null // Additional options passed to jQuery droppable
4442
4471
  },
4443
- // Override virtual methods for this extension.
4444
- // `this` : Fancytree instance
4445
- // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
4472
+
4446
4473
  treeInit: function(ctx){
4447
4474
  var tree = ctx.tree;
4448
4475
  this._super(ctx);
@@ -4471,15 +4498,7 @@ $.ui.fancytree.registerExtension(
4471
4498
  .css({"z-index": 1000})
4472
4499
  .prependTo($(this.$div).parent());
4473
4500
  // .prependTo("body");
4474
- // logMsg("Creating marker: %o", this.$dropMarker);
4475
- }
4476
- /*
4477
- if(hitMode === "start"){
4478
4501
  }
4479
- if(hitMode === "stop"){
4480
- // sourceNode.removeClass("fancytree-drop-target");
4481
- }
4482
- */
4483
4502
  // this.$dropMarker.attr("class", hitMode);
4484
4503
  if(hitMode === "after" || hitMode === "before" || hitMode === "over"){
4485
4504
  // $source && $source.addClass("fancytree-drag-source");
@@ -4488,18 +4507,19 @@ $.ui.fancytree.registerExtension(
4488
4507
 
4489
4508
  switch(hitMode){
4490
4509
  case "before":
4491
- instData.$dropMarker.removeClass("fancytree-drop-after fancytree-drop-over");
4492
- instData.$dropMarker.addClass("fancytree-drop-before");
4510
+ instData
4511
+ .$dropMarker.removeClass("fancytree-drop-after fancytree-drop-over")
4512
+ .addClass("fancytree-drop-before");
4493
4513
  markerAt = "top";
4494
4514
  break;
4495
4515
  case "after":
4496
- instData.$dropMarker.removeClass("fancytree-drop-before fancytree-drop-over");
4497
- instData.$dropMarker.addClass("fancytree-drop-after");
4516
+ instData.$dropMarker.removeClass("fancytree-drop-before fancytree-drop-over")
4517
+ .addClass("fancytree-drop-after");
4498
4518
  markerAt = "bottom";
4499
4519
  break;
4500
4520
  default:
4501
- instData.$dropMarker.removeClass("fancytree-drop-after fancytree-drop-before");
4502
- instData.$dropMarker.addClass("fancytree-drop-over");
4521
+ instData.$dropMarker.removeClass("fancytree-drop-after fancytree-drop-before")
4522
+ .addClass("fancytree-drop-over");
4503
4523
  $target.addClass("fancytree-drop-target");
4504
4524
  markerOffsetX = 8;
4505
4525
  }
@@ -4594,15 +4614,15 @@ $.ui.fancytree.registerExtension(
4594
4614
  dnd = opts.dnd,
4595
4615
  ctx = this._makeHookContext(node, event, {otherNode: otherNode, ui: ui, draggable: draggable}),
4596
4616
  res = null,
4597
- nodeTag = $(node.span);
4617
+ $nodeTag = $(node.span);
4598
4618
 
4599
4619
  switch (eventName) {
4600
4620
  case "helper":
4601
4621
  // Only event and node argument is available
4602
4622
  $helper = $("<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>")
4603
- // .append($(event.target).closest("span.fancytree-node").find("span.fancytree-title").clone());
4604
- .append(nodeTag.find("span.fancytree-title").clone());
4605
- // issue 244: helper should be child of scrollParent
4623
+ .css({zIndex: 3, position: "relative"}) // so it appears above ext-wide selection bar
4624
+ .append($nodeTag.find("span.fancytree-title").clone());
4625
+ // DT issue 244: helper should be child of scrollParent
4606
4626
  $("ul.fancytree-container", node.tree.$div).append($helper);
4607
4627
  // Attach node reference to helper object
4608
4628
  $helper.data("ftSourceNode", node);
@@ -4610,6 +4630,7 @@ $.ui.fancytree.registerExtension(
4610
4630
  // logMsg("helper.sourceNode=%o", $helper.data("ftSourceNode"));
4611
4631
  res = $helper;
4612
4632
  break;
4633
+
4613
4634
  case "start":
4614
4635
  if( node.isStatusNode() ) {
4615
4636
  res = false;
@@ -4621,12 +4642,13 @@ $.ui.fancytree.registerExtension(
4621
4642
  //draggable._clear();
4622
4643
  // NOTE: the return value seems to be ignored (drag is not canceled, when false is returned)
4623
4644
  // TODO: call this._cancelDrag()?
4624
- ui.helper.trigger("mouseup");
4625
- ui.helper.hide();
4645
+ ui.helper.trigger("mouseup")
4646
+ .hide();
4626
4647
  } else {
4627
- nodeTag.addClass("fancytree-drag-source");
4648
+ $nodeTag.addClass("fancytree-drag-source");
4628
4649
  }
4629
4650
  break;
4651
+
4630
4652
  case "enter":
4631
4653
  if(dnd.preventRecursiveMoves && node.isDescendantOf(otherNode)){
4632
4654
  r = false;
@@ -4653,6 +4675,7 @@ $.ui.fancytree.registerExtension(
4653
4675
  ui.helper.data("enterResponse", res);
4654
4676
  logMsg("helper.enterResponse: %o", res);
4655
4677
  break;
4678
+
4656
4679
  case "over":
4657
4680
  enterResponse = ui.helper.data("enterResponse");
4658
4681
  hitMode = null;
@@ -4664,11 +4687,11 @@ $.ui.fancytree.registerExtension(
4664
4687
  hitMode = enterResponse;
4665
4688
  } else {
4666
4689
  // Calculate hitMode from relative cursor position.
4667
- nodeOfs = nodeTag.offset();
4690
+ nodeOfs = $nodeTag.offset();
4668
4691
  relPos = { x: event.pageX - nodeOfs.left,
4669
4692
  y: event.pageY - nodeOfs.top };
4670
- relPos2 = { x: relPos.x / nodeTag.width(),
4671
- y: relPos.y / nodeTag.height() };
4693
+ relPos2 = { x: relPos.x / $nodeTag.width(),
4694
+ y: relPos.y / $nodeTag.height() };
4672
4695
 
4673
4696
  if( enterResponse.after && relPos2.y > 0.75 ){
4674
4697
  hitMode = "after";
@@ -4710,10 +4733,11 @@ $.ui.fancytree.registerExtension(
4710
4733
  ctx.hitMode = hitMode;
4711
4734
  res = dnd.dragOver(node, ctx);
4712
4735
  }
4713
- // issue 332
4736
+ // DT issue 332
4714
4737
  // this._setDndStatus(otherNode, node, ui.helper, hitMode, res!==false);
4715
4738
  this._local._setDndStatus(otherNode, node, ui.helper, hitMode, res!==false && hitMode !== null);
4716
4739
  break;
4740
+
4717
4741
  case "drop":
4718
4742
  hitMode = ui.helper.data("hitMode");
4719
4743
  if(hitMode && dnd.dragDrop){
@@ -4721,6 +4745,7 @@ $.ui.fancytree.registerExtension(
4721
4745
  dnd.dragDrop(node, ctx);
4722
4746
  }
4723
4747
  break;
4748
+
4724
4749
  case "leave":
4725
4750
  // Cancel pending expand request
4726
4751
  node.scheduleAction("cancel");
@@ -4731,14 +4756,16 @@ $.ui.fancytree.registerExtension(
4731
4756
  dnd.dragLeave(node, ctx);
4732
4757
  }
4733
4758
  break;
4759
+
4734
4760
  case "stop":
4735
- nodeTag.removeClass("fancytree-drag-source");
4761
+ $nodeTag.removeClass("fancytree-drag-source");
4736
4762
  if(dnd.dragStop){
4737
4763
  dnd.dragStop(node, ctx);
4738
4764
  }
4739
4765
  break;
4766
+
4740
4767
  default:
4741
- throw "Unsupported drag event: " + eventName;
4768
+ $.error("Unsupported drag event: " + eventName);
4742
4769
  }
4743
4770
  return res;
4744
4771
  },
@@ -4763,8 +4790,8 @@ $.ui.fancytree.registerExtension(
4763
4790
  * Released under the MIT license
4764
4791
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
4765
4792
  *
4766
- * @version 2.0.0-11
4767
- * @date 2014-04-27T22:28
4793
+ * @version 2.1.0
4794
+ * @date 2014-05-29T16:44
4768
4795
  */
4769
4796
 
4770
4797
  ;(function($, window, document, undefined) {
@@ -4985,7 +5012,7 @@ $.ui.fancytree._FancytreeNodeClass.prototype.endEdit = function(){
4985
5012
  * [ext-edit] Check if any node in this tree in edit mode.
4986
5013
  *
4987
5014
  * @returns {FancytreeNode | null}
4988
- * @lends Fancytree.prototype
5015
+ * @alias Fancytree#isEditing
4989
5016
  * @requires jquery.fancytree.edit.js
4990
5017
  */
4991
5018
  $.ui.fancytree._FancytreeClass.prototype.isEditing = function(){
@@ -4996,7 +5023,7 @@ $.ui.fancytree._FancytreeClass.prototype.isEditing = function(){
4996
5023
  /**
4997
5024
  * [ext-edit] Check if this node is in edit mode.
4998
5025
  * @returns {Boolean} true if node is currently beeing edited
4999
- * @lends FancytreeNode.prototype
5026
+ * @alias FancytreeNode#isEditing
5000
5027
  * @requires jquery.fancytree.edit.js
5001
5028
  */
5002
5029
  $.ui.fancytree._FancytreeNodeClass.prototype.isEditing = function(){
@@ -5027,10 +5054,6 @@ $.ui.fancytree.registerExtension({
5027
5054
  // Local attributes
5028
5055
  currentNode: null,
5029
5056
 
5030
- // Override virtual methods for this extension.
5031
- // `this` : the Fancytree instance
5032
- // `this._local`: the namespace that contains extension attributes and private methods (same as this.ext.EXTNAME)
5033
- // `this._super`: the virtual function that was overridden (member of previous extension or Fancytree)
5034
5057
  treeInit: function(ctx){
5035
5058
  this._super(ctx);
5036
5059
  this.$container.addClass("fancytree-ext-edit");
@@ -5042,7 +5065,7 @@ $.ui.fancytree.registerExtension({
5042
5065
  return false;
5043
5066
  }
5044
5067
  }
5045
- this._super(ctx);
5068
+ return this._super(ctx);
5046
5069
  },
5047
5070
  nodeDblclick: function(ctx) {
5048
5071
  if( $.inArray("dblclick", ctx.options.edit.triggerStart) >= 0 ){
@@ -5082,8 +5105,8 @@ $.ui.fancytree.registerExtension({
5082
5105
  * Released under the MIT license
5083
5106
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
5084
5107
  *
5085
- * @version 2.0.0-11
5086
- * @date 2014-04-27T22:28
5108
+ * @version 2.1.0
5109
+ * @date 2014-05-29T16:44
5087
5110
  */
5088
5111
 
5089
5112
  ;(function($, window, document, undefined) {
@@ -5100,33 +5123,12 @@ function _escapeRegex(str){
5100
5123
  return (str + "").replace(/([.?*+\^\$\[\]\\(){}|-])/g, "\\$1");
5101
5124
  }
5102
5125
 
5103
- /* EXT-TABLE: Show/hide all rows that are structural descendants of `parent`. */
5104
- // function setChildRowVisibility(parent, flag) {
5105
- // parent.visit(function(node){
5106
- // var tr = node.tr;
5107
- // if(tr){
5108
- // tr.style.display = flag ? "" : "none";
5109
- // }
5110
- // node.debug(flag ? "SHOW" : "HIDE");
5111
- // if(!node.expanded){
5112
- // return "skip";
5113
- // }
5114
- // });
5115
- // }
5116
-
5117
- /**
5118
- * [ext-filter] Dimm or hide nodes.
5119
- *
5120
- * @param {function | string} filter
5121
- * @returns {integer} count
5122
- * @alias Fancytree#applyFilter
5123
- * @requires jquery.fancytree.filter.js
5124
- */
5125
- $.ui.fancytree._FancytreeClass.prototype.applyFilter = function(filter){
5126
+ $.ui.fancytree._FancytreeClass.prototype._applyFilterImpl = function(filter, branchMode, leavesOnly){
5126
5127
  var match, re,
5127
5128
  count = 0,
5128
- hideMode = this.options.filter.mode === "hide",
5129
- leavesOnly = this.options.filter.leavesOnly;
5129
+ hideMode = this.options.filter.mode === "hide";
5130
+ // leavesOnly = !branchMode && this.options.filter.leavesOnly;
5131
+ leavesOnly = !!leavesOnly && !branchMode;
5130
5132
 
5131
5133
  // Default to 'match title substring (not case sensitive)'
5132
5134
  if(typeof filter === "string"){
@@ -5146,7 +5148,6 @@ $.ui.fancytree._FancytreeClass.prototype.applyFilter = function(filter){
5146
5148
  }
5147
5149
  // Reset current filter
5148
5150
  this.visit(function(node){
5149
- // node.hide = hideMode && true;
5150
5151
  delete node.match;
5151
5152
  delete node.subMatch;
5152
5153
  });
@@ -5154,12 +5155,16 @@ $.ui.fancytree._FancytreeClass.prototype.applyFilter = function(filter){
5154
5155
  this.visit(function(node){
5155
5156
  if ((!leavesOnly || node.children == null) && filter(node)) {
5156
5157
  count++;
5157
- // node.hide = false;
5158
5158
  node.match = true;
5159
5159
  node.visitParents(function(p){
5160
- // p.hide = false;
5161
5160
  p.subMatch = true;
5162
5161
  });
5162
+ if( branchMode ) {
5163
+ node.visit(function(p){
5164
+ p.match = true;
5165
+ });
5166
+ return "skip";
5167
+ }
5163
5168
  }
5164
5169
  });
5165
5170
  // Redraw
@@ -5167,15 +5172,45 @@ $.ui.fancytree._FancytreeClass.prototype.applyFilter = function(filter){
5167
5172
  return count;
5168
5173
  };
5169
5174
 
5175
+ /**
5176
+ * [ext-filter] Dimm or hide nodes.
5177
+ *
5178
+ * @param {function | string} filter
5179
+ * @param {boolean} [leavesOnly=false]
5180
+ * @returns {integer} count
5181
+ * @alias Fancytree#filterNodes
5182
+ * @requires jquery.fancytree.filter.js
5183
+ */
5184
+ $.ui.fancytree._FancytreeClass.prototype.filterNodes = function(filter, leavesOnly){
5185
+ return this._applyFilterImpl(filter, false, leavesOnly);
5186
+ };
5187
+
5188
+ $.ui.fancytree._FancytreeClass.prototype.applyFilter = function(filter){
5189
+ this.warn("Fancytree.applyFilter() is deprecated since 2014-05-10. Use .filterNodes() instead.");
5190
+ return this.filterNodes.apply(this, arguments);
5191
+ };
5192
+
5193
+ /**
5194
+ * [ext-filter] Dimm or hide whole branches.
5195
+ *
5196
+ * @param {function | string} filter
5197
+ * @returns {integer} count
5198
+ * @alias Fancytree#filterBranches
5199
+ * @requires jquery.fancytree.filter.js
5200
+ */
5201
+ $.ui.fancytree._FancytreeClass.prototype.filterBranches = function(filter){
5202
+ return this._applyFilterImpl(filter, true, null);
5203
+ };
5204
+
5205
+
5170
5206
  /**
5171
5207
  * [ext-filter] Reset the filter.
5172
5208
  *
5173
- * @alias Fancytree#applyFilter
5209
+ * @alias Fancytree#clearFilter
5174
5210
  * @requires jquery.fancytree.filter.js
5175
5211
  */
5176
5212
  $.ui.fancytree._FancytreeClass.prototype.clearFilter = function(){
5177
5213
  this.visit(function(node){
5178
- // delete node.hide;
5179
5214
  delete node.match;
5180
5215
  delete node.subMatch;
5181
5216
  });
@@ -5190,22 +5225,14 @@ $.ui.fancytree._FancytreeClass.prototype.clearFilter = function(){
5190
5225
  */
5191
5226
  $.ui.fancytree.registerExtension({
5192
5227
  name: "filter",
5193
- version: "0.0.2",
5228
+ version: "0.2.0",
5194
5229
  // Default options for this extension.
5195
5230
  options: {
5196
- mode: "dimm",
5197
- leavesOnly: false
5231
+ mode: "dimm"
5232
+ // leavesOnly: false
5198
5233
  },
5199
- // Override virtual methods for this extension.
5200
- // `this` : is this extension object
5201
- // `this._base` : the Fancytree instance
5202
- // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
5203
5234
  treeInit: function(ctx){
5204
5235
  this._super(ctx);
5205
- // ctx.tree.filter = false;
5206
- },
5207
- treeDestroy: function(ctx){
5208
- this._super(ctx);
5209
5236
  },
5210
5237
  nodeRenderStatus: function(ctx) {
5211
5238
  // Set classes for current status
@@ -5215,31 +5242,15 @@ $.ui.fancytree.registerExtension({
5215
5242
  $span = $(node[tree.statusClassPropName]);
5216
5243
 
5217
5244
  res = this._super(ctx);
5218
-
5219
- if(!$span.length){
5220
- return res; // nothing to do, if node was not yet rendered
5221
- }
5222
- if(!tree.enableFilter){
5245
+ // nothing to do, if node was not yet rendered
5246
+ if( !$span.length || !tree.enableFilter ) {
5223
5247
  return res;
5224
5248
  }
5225
- $span.toggleClass("fancytree-match", !!node.match);
5226
- $span.toggleClass("fancytree-submatch", !!node.subMatch);
5227
- $span.toggleClass("fancytree-hide", !(node.match || node.subMatch));
5228
-
5229
- // if(opts.filter.mode === "hide"){
5230
- // // visible = !!(node.match || node.subMatch);
5231
- // visible = !node.hide;
5232
- // node.debug(node.title + ": visible=" + visible);
5233
- // if( node.li ) {
5234
- // $(node.li).toggle(visible);
5235
- // } else if( node.tr ) {
5236
- // // Show/hide all rows that are structural descendants of `parent`
5237
- // $(node.tr).toggle(visible);
5238
- // // if( !visible ) {
5239
- // // setChildRowVisibility(node, visible);
5240
- // // }
5241
- // }
5242
- // }
5249
+ $span
5250
+ .toggleClass("fancytree-match", !!node.match)
5251
+ .toggleClass("fancytree-submatch", !!node.subMatch)
5252
+ .toggleClass("fancytree-hide", !(node.match || node.subMatch));
5253
+
5243
5254
  return res;
5244
5255
  }
5245
5256
  });
@@ -5256,8 +5267,8 @@ $.ui.fancytree.registerExtension({
5256
5267
  * Released under the MIT license
5257
5268
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
5258
5269
  *
5259
- * @version 2.0.0-11
5260
- * @date 2014-04-27T22:28
5270
+ * @version 2.1.0
5271
+ * @date 2014-05-29T16:44
5261
5272
  */
5262
5273
 
5263
5274
  ;(function($, window, document, undefined) {
@@ -5274,7 +5285,7 @@ function _getIcon(opts, type){
5274
5285
 
5275
5286
  $.ui.fancytree.registerExtension({
5276
5287
  name: "glyph",
5277
- version: "0.0.2",
5288
+ version: "0.1.0",
5278
5289
  // Default options for this extension.
5279
5290
  options: {
5280
5291
  prefix: "icon-",
@@ -5288,19 +5299,15 @@ $.ui.fancytree.registerExtension({
5288
5299
  error: "icon-exclamation-sign",
5289
5300
  expanderClosed: "icon-caret-right",
5290
5301
  expanderLazy: "icon-angle-right",
5291
- // expanderLazy: "icon-refresh icon-spin",
5292
5302
  expanderOpen: "icon-caret-down",
5293
5303
  folder: "icon-folder-close-alt",
5294
5304
  folderOpen: "icon-folder-open-alt",
5295
5305
  loading: "icon-refresh icon-spin",
5296
- // loading: "icon-spinner icon-spin"
5297
5306
  noExpander: ""
5298
5307
  },
5299
5308
  icon: null // TODO: allow callback here
5300
5309
  },
5301
- // Overide virtual methods for this extension.
5302
- // `this` : is this extension object
5303
- // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
5310
+
5304
5311
  treeInit: function(ctx){
5305
5312
  var tree = ctx.tree;
5306
5313
  this._super(ctx);
@@ -5364,7 +5371,8 @@ $.ui.fancytree.registerExtension({
5364
5371
  if(node.parent){
5365
5372
  span = $("span.fancytree-expander", node.span).get(0);
5366
5373
  }else{
5367
- span = $(".fancytree-statusnode-wait, .fancytree-statusnode-error", node[this.nodeContainerAttrName]).find("span.fancytree-expander").get(0);
5374
+ span = $(".fancytree-statusnode-wait, .fancytree-statusnode-error", node[this.nodeContainerAttrName])
5375
+ .find("span.fancytree-expander").get(0);
5368
5376
  }
5369
5377
  if( status === "loading"){
5370
5378
  // $("span.fancytree-expander", ctx.node.span).addClass(_getIcon(opts, "loading"));
@@ -5387,8 +5395,8 @@ $.ui.fancytree.registerExtension({
5387
5395
  * Released under the MIT license
5388
5396
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
5389
5397
  *
5390
- * @version 2.0.0-11
5391
- * @date 2014-04-27T22:28
5398
+ * @version 2.1.0
5399
+ * @date 2014-05-29T16:44
5392
5400
  */
5393
5401
 
5394
5402
  ;(function($, window, document, undefined) {
@@ -5589,8 +5597,8 @@ $.ui.fancytree.registerExtension({
5589
5597
  * Released under the MIT license
5590
5598
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
5591
5599
  *
5592
- * @version 2.0.0-11
5593
- * @date 2014-04-27T22:28
5600
+ * @version 2.1.0
5601
+ * @date 2014-05-29T16:44
5594
5602
  */
5595
5603
 
5596
5604
  ;(function($, window, document, undefined) {
@@ -5617,15 +5625,13 @@ var ACTIVE = "active",
5617
5625
  /* Recursively load lazy nodes
5618
5626
  * @param {string} mode 'load', 'expand', false
5619
5627
  */
5620
- function _loadLazyNodes(tree, instData, keyList, mode, dfd) {
5628
+ function _loadLazyNodes(tree, local, keyList, mode, dfd) {
5621
5629
  var i, key, l, node,
5622
5630
  foundOne = false,
5623
5631
  deferredList = [],
5624
- // lazyNodeList = [],
5625
- missingKeyList = []; //keyList.slice(0),
5632
+ missingKeyList = [];
5626
5633
 
5627
5634
  keyList = keyList || [];
5628
- // expand = expand !== false;
5629
5635
  dfd = dfd || $.Deferred();
5630
5636
 
5631
5637
  for( i=0, l=keyList.length; i<l; i++ ) {
@@ -5633,7 +5639,6 @@ function _loadLazyNodes(tree, instData, keyList, mode, dfd) {
5633
5639
  node = tree.getNodeByKey(key);
5634
5640
  if( node ) {
5635
5641
  if( mode && node.isUndefined() ) {
5636
- // lazyNodeList.push(node);
5637
5642
  foundOne = true;
5638
5643
  tree.debug("_loadLazyNodes: " + node + " is lazy: loading...");
5639
5644
  if( mode === "expand" ) {
@@ -5644,8 +5649,6 @@ function _loadLazyNodes(tree, instData, keyList, mode, dfd) {
5644
5649
  } else {
5645
5650
  tree.debug("_loadLazyNodes: " + node + " already loaded.");
5646
5651
  node.setExpanded();
5647
- // node.expanded = true;
5648
- // node.render();
5649
5652
  }
5650
5653
  } else {
5651
5654
  missingKeyList.push(key);
@@ -5657,13 +5660,13 @@ function _loadLazyNodes(tree, instData, keyList, mode, dfd) {
5657
5660
  // All lazy-expands have finished
5658
5661
  if( foundOne && missingKeyList.length > 0 ) {
5659
5662
  // If we read new nodes from server, try to resolve yet-missing keys
5660
- _loadLazyNodes(tree, instData, missingKeyList, mode, dfd);
5663
+ _loadLazyNodes(tree, local, missingKeyList, mode, dfd);
5661
5664
  } else {
5662
5665
  if( missingKeyList.length ) {
5663
5666
  tree.warn("_loadLazyNodes: could not load those keys: ", missingKeyList);
5664
5667
  for( i=0, l=missingKeyList.length; i<l; i++ ) {
5665
5668
  key = keyList[i];
5666
- instData._setKey(EXPANDED, keyList[i], false);
5669
+ local._appendKey(EXPANDED, keyList[i], false);
5667
5670
  }
5668
5671
  }
5669
5672
  dfd.resolve();
@@ -5682,26 +5685,21 @@ function _loadLazyNodes(tree, instData, keyList, mode, dfd) {
5682
5685
  * @requires jquery.fancytree.persist.js
5683
5686
  */
5684
5687
  $.ui.fancytree._FancytreeClass.prototype.clearCookies = function(types){
5685
- var inst = this.ext.persist,
5686
- cookiePrefix = inst.cookiePrefix;
5688
+ var local = this.ext.persist,
5689
+ prefix = local.cookiePrefix;
5687
5690
 
5688
5691
  types = types || "active expanded focus selected";
5689
- // TODO: optimize
5690
5692
  if(types.indexOf(ACTIVE) >= 0){
5691
- // $.cookie(cookiePrefix + ACTIVE, null);
5692
- $.removeCookie(cookiePrefix + ACTIVE);
5693
+ local._data(prefix + ACTIVE, null);
5693
5694
  }
5694
5695
  if(types.indexOf(EXPANDED) >= 0){
5695
- // $.cookie(cookiePrefix + EXPANDED, null);
5696
- $.removeCookie(cookiePrefix + EXPANDED);
5696
+ local._data(prefix + EXPANDED, null);
5697
5697
  }
5698
5698
  if(types.indexOf(FOCUS) >= 0){
5699
- // $.cookie(cookiePrefix + FOCUS, null);
5700
- $.removeCookie(cookiePrefix + FOCUS);
5699
+ local._data(prefix + FOCUS, null);
5701
5700
  }
5702
5701
  if(types.indexOf(SELECTED) >= 0){
5703
- // $.cookie(cookiePrefix + SELECTED, null);
5704
- $.removeCookie(cookiePrefix + SELECTED);
5702
+ local._data(prefix + SELECTED, null);
5705
5703
  }
5706
5704
  };
5707
5705
 
@@ -5716,15 +5714,15 @@ $.ui.fancytree._FancytreeClass.prototype.clearCookies = function(types){
5716
5714
  * @requires jquery.fancytree.persist.js
5717
5715
  */
5718
5716
  $.ui.fancytree._FancytreeClass.prototype.getPersistData = function(){
5719
- var inst = this.ext.persist,
5720
- instOpts= this.options.persist,
5721
- delim = instOpts.cookieDelimiter,
5717
+ var local = this.ext.persist,
5718
+ prefix = local.cookiePrefix,
5719
+ delim = local.cookieDelimiter,
5722
5720
  res = {};
5723
5721
 
5724
- res[ACTIVE] = $.cookie(inst.cookiePrefix + ACTIVE);
5725
- res[EXPANDED] = ($.cookie(inst.cookiePrefix + EXPANDED) || "").split(delim);
5726
- res[SELECTED] = ($.cookie(inst.cookiePrefix + SELECTED) || "").split(delim);
5727
- res[FOCUS] = $.cookie(inst.cookiePrefix + FOCUS);
5722
+ res[ACTIVE] = local._data(prefix + ACTIVE);
5723
+ res[EXPANDED] = (local._data(prefix + EXPANDED) || "").split(delim);
5724
+ res[SELECTED] = (local._data(prefix + SELECTED) || "").split(delim);
5725
+ res[FOCUS] = local._data(prefix + FOCUS);
5728
5726
  return res;
5729
5727
  };
5730
5728
 
@@ -5734,10 +5732,9 @@ $.ui.fancytree._FancytreeClass.prototype.getPersistData = function(){
5734
5732
  */
5735
5733
  $.ui.fancytree.registerExtension({
5736
5734
  name: "persist",
5737
- version: "0.2.0",
5735
+ version: "0.3.0",
5738
5736
  // Default options for this extension.
5739
5737
  options: {
5740
- // appendRequestInfo: false,
5741
5738
  cookieDelimiter: "~",
5742
5739
  cookiePrefix: undefined, // 'fancytree-<treeId>-' by default
5743
5740
  cookie: {
@@ -5747,89 +5744,96 @@ $.ui.fancytree.registerExtension({
5747
5744
  domain: "",
5748
5745
  secure: false
5749
5746
  },
5750
- expandLazy: false, // true: recursively expand and load lazy nodes
5751
- overrideSource: false, // true: cookie takes precedence over `source` data attributes.
5747
+ expandLazy: false, // true: recursively expand and load lazy nodes
5748
+ overrideSource: false, // true: cookie takes precedence over `source` data attributes.
5749
+ store: "auto", // 'cookie': force cookie, 'local': force localStore, 'session': force sessionStore
5752
5750
  types: "active expanded focus selected"
5753
5751
  },
5754
5752
 
5753
+ /* Generic read/write string data to cookie, sessionStorage or localStorage. */
5754
+ _data: function(key, value){
5755
+ var ls = this._local.localStorage; // null, sessionStorage, or localStorage
5756
+
5757
+ if( value === undefined ) {
5758
+ return ls ? ls.getItem(key) : $.cookie(key);
5759
+ } else if ( value === null ) {
5760
+ if( ls ) {
5761
+ ls.removeItem(key);
5762
+ } else {
5763
+ $.removeCookie(key);
5764
+ }
5765
+ } else {
5766
+ if( ls ) {
5767
+ ls.setItem(key, value);
5768
+ } else {
5769
+ $.cookie(key, value, this.options.persist.cookie);
5770
+ }
5771
+ }
5772
+ },
5773
+
5755
5774
  /* Append `key` to a cookie. */
5756
- _setKey: function(type, key, flag){
5775
+ _appendKey: function(type, key, flag){
5757
5776
  key = "" + key; // #90
5758
- var instData = this._local,
5777
+ var local = this._local,
5759
5778
  instOpts = this.options.persist,
5760
- cookieName = instData.cookiePrefix + type,
5761
- cookie = $.cookie(cookieName),
5762
- cookieList = cookie ? cookie.split(instOpts.cookieDelimiter) : [],
5763
- idx = $.inArray(key, cookieList);
5779
+ delim = instOpts.cookieDelimiter,
5780
+ cookieName = local.cookiePrefix + type,
5781
+ data = local._data(cookieName),
5782
+ keyList = data ? data.split(delim) : [],
5783
+ idx = $.inArray(key, keyList);
5764
5784
  // Remove, even if we add a key, so the key is always the last entry
5765
5785
  if(idx >= 0){
5766
- cookieList.splice(idx, 1);
5786
+ keyList.splice(idx, 1);
5767
5787
  }
5768
5788
  // Append key to cookie
5769
5789
  if(flag){
5770
- cookieList.push(key);
5790
+ keyList.push(key);
5771
5791
  }
5772
- $.cookie(cookieName, cookieList.join(instOpts.cookieDelimiter), instOpts.cookie);
5792
+ local._data(cookieName, keyList.join(delim));
5773
5793
  },
5774
- // Overide virtual methods for this extension.
5775
- // `this` : is this Fancytree object
5776
- // `this._super`: the virtual function that was overridden (member of prev. extension or Fancytree)
5794
+
5777
5795
  treeInit: function(ctx){
5778
5796
  var tree = ctx.tree,
5779
5797
  opts = ctx.options,
5780
- instData = this._local,
5798
+ local = this._local,
5781
5799
  instOpts = this.options.persist;
5782
5800
 
5783
- _assert($.cookie, "Missing required plugin for 'persist' extension: jquery.cookie.js");
5801
+ // For 'auto' or 'cookie' mode, the cookie plugin must be available
5802
+ _assert(instOpts.store === "localStore" || $.cookie, "Missing required plugin for 'persist' extension: jquery.cookie.js");
5784
5803
 
5785
- instData.cookiePrefix = instOpts.cookiePrefix || ("fancytree-" + tree._id + "-");
5786
- instData.storeActive = instOpts.types.indexOf(ACTIVE) >= 0;
5787
- instData.storeExpanded = instOpts.types.indexOf(EXPANDED) >= 0;
5788
- instData.storeSelected = instOpts.types.indexOf(SELECTED) >= 0;
5789
- instData.storeFocus = instOpts.types.indexOf(FOCUS) >= 0;
5804
+ local.cookiePrefix = instOpts.cookiePrefix || ("fancytree-" + tree._id + "-");
5805
+ local.storeActive = instOpts.types.indexOf(ACTIVE) >= 0;
5806
+ local.storeExpanded = instOpts.types.indexOf(EXPANDED) >= 0;
5807
+ local.storeSelected = instOpts.types.indexOf(SELECTED) >= 0;
5808
+ local.storeFocus = instOpts.types.indexOf(FOCUS) >= 0;
5809
+ if( instOpts.store === "cookie" || !window.localStorage ) {
5810
+ local.localStorage = null;
5811
+ } else {
5812
+ local.localStorage = (instOpts.store === "local") ? window.localStorage : window.sessionStorage;
5813
+ }
5790
5814
 
5791
5815
  // Bind init-handler to apply cookie state
5792
5816
  tree.$div.bind("fancytreeinit", function(event){
5793
5817
  var cookie, dfd, i, keyList, node,
5794
- prevFocus = $.cookie(instData.cookiePrefix + FOCUS); // record this before node.setActive() overrides it;
5818
+ prevFocus = $.cookie(local.cookiePrefix + FOCUS); // record this before node.setActive() overrides it;
5795
5819
 
5796
5820
  tree.debug("COOKIE " + document.cookie);
5797
5821
 
5798
- cookie = $.cookie(instData.cookiePrefix + EXPANDED);
5822
+ cookie = local._data(local.cookiePrefix + EXPANDED);
5799
5823
  keyList = cookie && cookie.split(instOpts.cookieDelimiter);
5800
5824
 
5801
- if( instData.storeExpanded ) {
5825
+ if( local.storeExpanded ) {
5802
5826
  // Recursively load nested lazy nodes if expandLazy is 'expand' or 'load'
5803
5827
  // Also remove expand-cookies for unmatched nodes
5804
- dfd = _loadLazyNodes(tree, instData, keyList, instOpts.expandLazy ? "expand" : false , null);
5828
+ dfd = _loadLazyNodes(tree, local, keyList, instOpts.expandLazy ? "expand" : false , null);
5805
5829
  } else {
5806
5830
  // nothing to do
5807
5831
  dfd = new $.Deferred().resolve();
5808
5832
  }
5809
5833
 
5810
5834
  dfd.done(function(){
5811
- // alert("persistent expand done");
5812
- // if(instData.storeExpanded){
5813
- // cookie = $.cookie(instData.cookiePrefix + EXPANDED);
5814
- // if(cookie){
5815
- // keyList = cookie.split(instOpts.cookieDelimiter);
5816
- // for(i=0; i<keyList.length; i++){
5817
- // node = tree.getNodeByKey(keyList[i]);
5818
- // if(node){
5819
- // if(node.expanded === undefined || instOpts.overrideSource && (node.expanded === false)){
5820
- // // node.setExpanded();
5821
- // node.expanded = true;
5822
- // node.render();
5823
- // }
5824
- // }else{
5825
- // // node is no longer member of the tree: remove from cookie
5826
- // instData._setKey(EXPANDED, keyList[i], false);
5827
- // }
5828
- // }
5829
- // }
5830
- // }
5831
- if(instData.storeSelected){
5832
- cookie = $.cookie(instData.cookiePrefix + SELECTED);
5835
+ if(local.storeSelected){
5836
+ cookie = local._data(local.cookiePrefix + SELECTED);
5833
5837
  if(cookie){
5834
5838
  keyList = cookie.split(instOpts.cookieDelimiter);
5835
5839
  for(i=0; i<keyList.length; i++){
@@ -5842,13 +5846,13 @@ $.ui.fancytree.registerExtension({
5842
5846
  }
5843
5847
  }else{
5844
5848
  // node is no longer member of the tree: remove from cookie also
5845
- instData._setKey(SELECTED, keyList[i], false);
5849
+ local._appendKey(SELECTED, keyList[i], false);
5846
5850
  }
5847
5851
  }
5848
5852
  }
5849
5853
  }
5850
- if(instData.storeActive){
5851
- cookie = $.cookie(instData.cookiePrefix + ACTIVE);
5854
+ if(local.storeActive){
5855
+ cookie = local._data(local.cookiePrefix + ACTIVE);
5852
5856
  if(cookie && (opts.persist.overrideSource || !tree.activeNode)){
5853
5857
  node = tree.getNodeByKey(cookie);
5854
5858
  if(node){
@@ -5856,7 +5860,7 @@ $.ui.fancytree.registerExtension({
5856
5860
  }
5857
5861
  }
5858
5862
  }
5859
- if(instData.storeFocus && prevFocus){
5863
+ if(local.storeFocus && prevFocus){
5860
5864
  node = tree.getNodeByKey(prevFocus);
5861
5865
  if(node){
5862
5866
  node.setFocus();
@@ -5865,59 +5869,57 @@ $.ui.fancytree.registerExtension({
5865
5869
  });
5866
5870
  });
5867
5871
  // Init the tree
5868
- this._super(ctx);
5872
+ return this._super(ctx);
5869
5873
  },
5870
- // treeDestroy: function(ctx){
5871
- // this._super(ctx);
5872
- // },
5873
5874
  nodeSetActive: function(ctx, flag, opts) {
5874
- var instData = this._local,
5875
- instOpts = this.options.persist;
5875
+ var res,
5876
+ local = this._local;
5876
5877
 
5877
- flag = flag !== false;
5878
- this._super(ctx, flag, opts);
5878
+ flag = (flag !== false);
5879
+ res = this._super(ctx, flag, opts);
5879
5880
 
5880
- if(instData.storeActive){
5881
- $.cookie(instData.cookiePrefix + ACTIVE,
5882
- this.activeNode ? this.activeNode.key : null,
5883
- instOpts.cookie);
5881
+ if(local.storeActive){
5882
+ local._data(local.cookiePrefix + ACTIVE, this.activeNode ? this.activeNode.key : null);
5884
5883
  }
5884
+ return res;
5885
5885
  },
5886
5886
  nodeSetExpanded: function(ctx, flag, opts) {
5887
5887
  var res,
5888
5888
  node = ctx.node,
5889
- instData = this._local;
5889
+ local = this._local;
5890
5890
 
5891
- flag = flag !== false;
5891
+ flag = (flag !== false);
5892
5892
  res = this._super(ctx, flag, opts);
5893
5893
 
5894
- if(instData.storeExpanded){
5895
- instData._setKey(EXPANDED, node.key, flag);
5894
+ if(local.storeExpanded){
5895
+ local._appendKey(EXPANDED, node.key, flag);
5896
5896
  }
5897
5897
  return res;
5898
5898
  },
5899
- nodeSetFocus: function(ctx) {
5900
- var instData = this._local,
5901
- instOpts = this.options.persist;
5899
+ nodeSetFocus: function(ctx, flag) {
5900
+ var res,
5901
+ local = this._local;
5902
5902
 
5903
- this._super(ctx);
5903
+ flag = (flag !== false);
5904
+ res = this._super(ctx, flag);
5904
5905
 
5905
- if(instData.storeFocus){
5906
- $.cookie(instData.cookiePrefix + FOCUS,
5907
- this.focusNode ? this.focusNode.key : null,
5908
- instOpts.cookie);
5906
+ if(flag && local.storeFocus){
5907
+ local._data(local.cookiePrefix + FOCUS, this.focusNode ? this.focusNode.key : null);
5909
5908
  }
5909
+ return res;
5910
5910
  },
5911
5911
  nodeSetSelected: function(ctx, flag) {
5912
- var node = ctx.node,
5913
- instData = this._local;
5912
+ var res,
5913
+ node = ctx.node,
5914
+ local = this._local;
5914
5915
 
5915
- flag = flag !== false;
5916
- this._super(ctx, flag);
5916
+ flag = (flag !== false);
5917
+ res = this._super(ctx, flag);
5917
5918
 
5918
- if(instData.storeSelected){
5919
- instData._setKey(SELECTED, node.key, flag);
5919
+ if(local.storeSelected){
5920
+ local._appendKey(SELECTED, node.key, flag);
5920
5921
  }
5922
+ return res;
5921
5923
  }
5922
5924
  });
5923
5925
  }(jQuery, window, document));
@@ -5933,8 +5935,8 @@ $.ui.fancytree.registerExtension({
5933
5935
  * Released under the MIT license
5934
5936
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
5935
5937
  *
5936
- * @version 2.0.0-11
5937
- * @date 2014-04-27T22:28
5938
+ * @version 2.1.0
5939
+ * @date 2014-05-29T16:44
5938
5940
  */
5939
5941
 
5940
5942
  ;(function($, window, document, undefined) {
@@ -6222,23 +6224,37 @@ $.ui.fancytree.registerExtension({
6222
6224
  /* Expand node, return Deferred.promise. */
6223
6225
  nodeSetExpanded: function(ctx, flag, opts) {
6224
6226
  var dfd = new $.Deferred(),
6225
- prevOpts = opts || {};
6227
+ subOpts = $.extend({}, opts, {noEvents: true, noAnimation: true});
6226
6228
 
6227
- opts = $.extend({}, opts, {noEvents: true, noAnimation: true});
6229
+ opts = opts || {};
6228
6230
 
6229
6231
  function _afterExpand(ok) {
6230
6232
  flag = (flag !== false);
6231
6233
  setChildRowVisibility(ctx.node, flag);
6232
- if( !prevOpts.noEvents ) {
6233
- ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
6234
- }
6235
6234
  if( ok ) {
6236
- dfd.resolveWith(ctx.node);
6235
+ if( flag && ctx.options.autoScroll && !opts.noAnimation && ctx.node.hasChildren() ) {
6236
+ // Scroll down to last child, but keep current node visible
6237
+ ctx.node.getLastChild().scrollIntoView(true, {topNode: ctx.node}).always(function(){
6238
+ if( !opts.noEvents ) {
6239
+ ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
6240
+ }
6241
+ dfd.resolveWith(ctx.node);
6242
+ });
6243
+ } else {
6244
+ if( !opts.noEvents ) {
6245
+ ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
6246
+ }
6247
+ dfd.resolveWith(ctx.node);
6248
+ }
6237
6249
  } else {
6250
+ if( !opts.noEvents ) {
6251
+ ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
6252
+ }
6238
6253
  dfd.rejectWith(ctx.node);
6239
6254
  }
6240
6255
  }
6241
- this._super(ctx, flag, opts).done(function () {
6256
+ // Call base-expand with disabled events and animation
6257
+ this._super(ctx, flag, subOpts).done(function () {
6242
6258
  _afterExpand(true);
6243
6259
  }).fail(function () {
6244
6260
  _afterExpand(false);
@@ -6281,8 +6297,8 @@ $.ui.fancytree.registerExtension({
6281
6297
  * Released under the MIT license
6282
6298
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
6283
6299
  *
6284
- * @version 2.0.0-11
6285
- * @date 2014-04-27T22:28
6300
+ * @version 2.1.0
6301
+ * @date 2014-05-29T16:44
6286
6302
  */
6287
6303
 
6288
6304
  ;(function($, window, document, undefined) {
@@ -6302,10 +6318,7 @@ $.ui.fancytree.registerExtension({
6302
6318
  hoverClass: "ui-state-hover",
6303
6319
  selectedClass: "ui-state-highlight"
6304
6320
  },
6305
- // Overide virtual methods for this extension.
6306
- // `this` : is this extension object
6307
- // `this._base` : the Fancytree instance
6308
- // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
6321
+
6309
6322
  treeInit: function(ctx){
6310
6323
  this._super(ctx);
6311
6324
  var $el = ctx.widget.element;