fancytree-rails 2.1.0.pre.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +1 -1
  4. data/Rakefile +3 -4
  5. data/app/assets/javascripts/fancytree/jquery.fancytree-all.js +568 -51
  6. data/app/assets/javascripts/fancytree/jquery.fancytree-custom.min.js +9 -6
  7. data/app/assets/javascripts/fancytree/jquery.fancytree.js +63 -27
  8. data/app/assets/javascripts/fancytree/jquery.fancytree.min.js +4 -4
  9. data/app/assets/javascripts/fancytree/src/jquery.fancytree.childcounter.js +2 -2
  10. data/app/assets/javascripts/fancytree/src/jquery.fancytree.clones.js +7 -3
  11. data/app/assets/javascripts/fancytree/src/jquery.fancytree.columnview.js +2 -2
  12. data/app/assets/javascripts/fancytree/src/jquery.fancytree.debug.js +2 -2
  13. data/app/assets/javascripts/fancytree/src/jquery.fancytree.dnd.js +24 -4
  14. data/app/assets/javascripts/fancytree/src/jquery.fancytree.edit.js +3 -2
  15. data/app/assets/javascripts/fancytree/src/jquery.fancytree.filter.js +2 -2
  16. data/app/assets/javascripts/fancytree/src/jquery.fancytree.glyph.js +14 -6
  17. data/app/assets/javascripts/fancytree/src/jquery.fancytree.gridnav.js +2 -2
  18. data/app/assets/javascripts/fancytree/src/jquery.fancytree.js +63 -27
  19. data/app/assets/javascripts/fancytree/src/jquery.fancytree.menu.js +2 -2
  20. data/app/assets/javascripts/fancytree/src/jquery.fancytree.persist.js +2 -2
  21. data/app/assets/javascripts/fancytree/src/jquery.fancytree.table.js +2 -2
  22. data/app/assets/javascripts/fancytree/src/jquery.fancytree.themeroller.js +2 -2
  23. data/app/assets/javascripts/fancytree/src/jquery.fancytree.wide.js +124 -0
  24. data/app/assets/stylesheets/fancytree/skin-lion/ui.fancytree.css.erb +5 -0
  25. data/app/assets/stylesheets/fancytree/skin-vista/ui.fancytree.css.erb +5 -0
  26. data/app/assets/stylesheets/fancytree/skin-win7/ui.fancytree.css.erb +5 -0
  27. data/app/assets/stylesheets/fancytree/skin-win8-xxl/ui.fancytree.css.erb +5 -0
  28. data/app/assets/stylesheets/fancytree/skin-win8/ui.fancytree.css.erb +5 -0
  29. data/app/assets/stylesheets/fancytree/skin-xp/ui.fancytree.css.erb +5 -0
  30. data/lib/fancytree/rails/version.rb +2 -2
  31. metadata +5 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a8617873a677ecca45f5f10e1878b044e209a57
4
- data.tar.gz: d48c2f46d24a79dace0daf77f3e395f0d797ebcf
3
+ metadata.gz: 9763566a5cf99627c6cda44c2570cff3f980333e
4
+ data.tar.gz: 4e79a94a6e0332683b61baf961e5c779045c35a1
5
5
  SHA512:
6
- metadata.gz: 958f86489eb8b3742f11b524c80a513fa64343820821c40ec4ff3bd9bc4b0e7f0da21746980a1ea45cf2ea07b03d8ead4341f531dd10e20313f819797b003016
7
- data.tar.gz: 6651dc979969d811827f7f1aaa95774600ee234087d73ec82dcf5239c484943f8e81f3b6731e1728ecd84167068d3845c1a2959912016c3bac6a5f599f08ef2b
6
+ metadata.gz: 6bb9216bdaad12e45fe5ef4ed0fca43b4e5ccd6eddf54efc6a5c993bb7f6a1637468400c3f3d22cff06d887a510da800b2c58e67659dfa30a5b434164487d038
7
+ data.tar.gz: 60d3f5b403758d2b47e4469eaed31605122448cc043ee6a1c605d61f0e6e6e209e3a59ce7e8171620f5d00e340586fd662b8ecb890b712230c146b57d1c10618
@@ -1,3 +1,7 @@
1
+ ## v2.3.0
2
+
3
+ * use fancytree v. 2.3.0
4
+
1
5
  ## v2.0.0-11-1
2
6
 
3
7
  * use fancytree v. 2.0.0-11
data/README.md CHANGED
@@ -55,7 +55,7 @@ Note that for awesome style (extension) to work you to:
55
55
 
56
56
  ## Credits
57
57
 
58
- Pice of code of Raikefile copied form joliss/jquery-ui-rails. See
58
+ Piece of code of Rakefile copied from joliss/jquery-ui-rails. See
59
59
  3th-party for its license.
60
60
 
61
61
  ## Contributing
data/Rakefile CHANGED
@@ -3,9 +3,9 @@ require 'fileutils'
3
3
  require 'fancytree/rails/version'
4
4
 
5
5
  def build_image_dependencies(source_code)
6
- image_dependencies = Set.new source_code.scan(/url\("?images\/([-_.a-zA-Z0-9]+)"?\)/).map(&:first)
6
+ image_dependencies = Set.new source_code.scan(/url\("(icons.gif)"?\)/).map(&:first)
7
7
  code = image_dependencies.inject("") do |acc, img|
8
- acc += " *= depend_on_asset \"jquery-ui/#{img}\"\n"
8
+ acc += " *= depend_on_asset \"fancytree/#{img}\"\n"
9
9
  end
10
10
  end
11
11
 
@@ -22,9 +22,8 @@ namespace :fancytree do
22
22
  css_files = Dir.glob("skin*/*.css")
23
23
  css_files.each do |file|
24
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
25
  source_code.gsub!(/\A(\/\*!.+?\*\/\s)/m, "\\1\n/*\n#{build_image_dependencies(source_code)} */\n\n") unless build_image_dependencies(source_code).empty?
26
+ source_code.gsub!(/url\("icons.gif"\)/, 'url(<%= image_path("fancytree/icons.gif") %>)')
28
27
 
29
28
  output_path = "../../../app/assets/stylesheets/fancytree/#{file}.erb"
30
29
  mkdir_p File.dirname(output_path)
@@ -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.1.0
11
- * @date 2014-05-29T16:44
10
+ * @version 2.3.0
11
+ * @date 2014-08-17T10:39
12
12
  */
13
13
 
14
14
  /** Core Fancytree module.
@@ -614,7 +614,7 @@ FancytreeNode.prototype = /** @lends FancytreeNode# */{
614
614
  var i, l, child, s, state, allSelected,someSelected,
615
615
  children = node.children;
616
616
 
617
- if( children ){
617
+ if( children && children.length ){
618
618
  // check all children recursively
619
619
  allSelected = true;
620
620
  someSelected = false;
@@ -852,6 +852,16 @@ FancytreeNode.prototype = /** @lends FancytreeNode# */{
852
852
  hasFocus: function() {
853
853
  return (this.tree.hasFocus() && this.tree.focusNode === this);
854
854
  },
855
+ /** Write to browser console if debugLevel >= 1 (prepending node info)
856
+ *
857
+ * @param {*} msg string or object or array of such
858
+ */
859
+ info: function(msg){
860
+ if( this.tree.options.debugLevel >= 1 ) {
861
+ Array.prototype.unshift.call(arguments, this.toString());
862
+ consoleApply("info", arguments);
863
+ }
864
+ },
855
865
  /** Return true if node is active (see also FancytreeNode#isSelected).
856
866
  * @returns {boolean}
857
867
  */
@@ -1063,6 +1073,9 @@ FancytreeNode.prototype = /** @lends FancytreeNode# */{
1063
1073
  }
1064
1074
  // Unlink this node from current parent
1065
1075
  if( this.parent.children.length === 1 ) {
1076
+ if( this.parent === targetParent ){
1077
+ return; // #258
1078
+ }
1066
1079
  this.parent.children = this.parent.lazy ? [] : null;
1067
1080
  this.parent.expanded = false;
1068
1081
  } else {
@@ -1196,7 +1209,7 @@ FancytreeNode.prototype = /** @lends FancytreeNode# */{
1196
1209
  // Navigate to node
1197
1210
  function _goto(n){
1198
1211
  if( n ){
1199
- n.makeVisible();
1212
+ try { n.makeVisible(); } catch(e) {} // #272
1200
1213
  // Node may still be hidden by a filter
1201
1214
  if( ! $(n.span).is(":visible") ) {
1202
1215
  n.debug("Navigate: skipping hidden node");
@@ -1467,13 +1480,20 @@ FancytreeNode.prototype = /** @lends FancytreeNode# */{
1467
1480
  setFocus: function(flag){
1468
1481
  return this.tree._callHook("nodeSetFocus", this, flag);
1469
1482
  },
1470
- // TODO: setLazyNodeStatus
1471
1483
  /**Select this node, i.e. check the checkbox.
1472
1484
  * @param {boolean} [flag=true] pass false to deselect
1473
1485
  */
1474
1486
  setSelected: function(flag){
1475
1487
  return this.tree._callHook("nodeSetSelected", this, flag);
1476
1488
  },
1489
+ /**Mark a lazy node as 'error', 'loading', or 'ok'.
1490
+ * @param {string} status 'error', 'ok'
1491
+ * @param {string} [message]
1492
+ * @param {string} [details]
1493
+ */
1494
+ setStatus: function(status, message, details){
1495
+ return this.tree._callHook("nodeSetStatus", this, status, message, details);
1496
+ },
1477
1497
  /**Rename this node.
1478
1498
  * @param {string} title
1479
1499
  */
@@ -1666,6 +1686,9 @@ function Fancytree(widget) {
1666
1686
  };
1667
1687
  }
1668
1688
  }
1689
+ if( this.options && $.isFunction(this.options.loaderror) ) {
1690
+ $.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead.");
1691
+ }
1669
1692
  this.ext = {}; // Active extension instances
1670
1693
  // allow to init tree.data.foo from <div data-foo=''>
1671
1694
  this.data = _getElementDataAsDict(this.$div);
@@ -1883,17 +1906,17 @@ Fancytree.prototype = /** @lends Fancytree# */{
1883
1906
  generateFormElements: function(selected, active) {
1884
1907
  // TODO: test case
1885
1908
  var nodeList,
1886
- selectedName = (selected !== false) ? "ft_" + this._id : selected,
1909
+ selectedName = (selected !== false) ? "ft_" + this._id + "[]" : selected,
1887
1910
  activeName = (active !== false) ? "ft_" + this._id + "_active" : active,
1888
1911
  id = "fancytree_result_" + this._id,
1889
- $result = this.$container.find("div#" + id);
1912
+ $result = $("#" + id);
1890
1913
 
1891
1914
  if($result.length){
1892
1915
  $result.empty();
1893
1916
  }else{
1894
1917
  $result = $("<div>", {
1895
1918
  id: id
1896
- }).hide().appendTo(this.$container);
1919
+ }).hide().insertAfter(this.$container);
1897
1920
  }
1898
1921
  if(selectedName){
1899
1922
  nodeList = this.getSelectedNodes( this.options.selectMode === 3 );
@@ -1967,7 +1990,12 @@ Fancytree.prototype = /** @lends Fancytree# */{
1967
1990
  }, true);
1968
1991
  return match;
1969
1992
  },
1970
- // TODO: getRoot()
1993
+ /** Return the invisible system root node.
1994
+ * @returns {FancytreeNode}
1995
+ */
1996
+ getRootNode: function() {
1997
+ return this.rootNode;
1998
+ },
1971
1999
  /**
1972
2000
  * Return an array of selected nodes.
1973
2001
  * @param {boolean} [stopOnParents=false] only return the topmost selected
@@ -2373,7 +2401,7 @@ $.extend(Fancytree.prototype,
2373
2401
  * data was rendered.
2374
2402
  */
2375
2403
  nodeLoadChildren: function(ctx, source) {
2376
- var ajax, delay,
2404
+ var ajax, delay, dfd,
2377
2405
  tree = ctx.tree,
2378
2406
  node = ctx.node;
2379
2407
 
@@ -2393,7 +2421,7 @@ $.extend(Fancytree.prototype,
2393
2421
 
2394
2422
  node.debug("nodeLoadChildren waiting debug delay " + Math.round(delay) + "ms");
2395
2423
  ajax.debugDelay = false;
2396
- source = $.Deferred(function (dfd) {
2424
+ dfd = $.Deferred(function (dfd) {
2397
2425
  setTimeout(function () {
2398
2426
  $.ajax(ajax)
2399
2427
  .done(function () { dfd.resolveWith(this, arguments); })
@@ -2401,33 +2429,42 @@ $.extend(Fancytree.prototype,
2401
2429
  }, delay);
2402
2430
  });
2403
2431
  }else{
2404
- source = $.ajax(ajax);
2432
+ dfd = $.ajax(ajax);
2405
2433
  }
2406
2434
 
2407
- // TODO: change 'pipe' to 'then' for jQuery 1.8
2408
- // $.pipe returns a new Promise with filtered results
2409
- source = source.pipe(function (data, textStatus, jqXHR) {
2410
- var res;
2435
+ // Defer the deferred: we want to be able to reject, even if ajax
2436
+ // resolved ok.
2437
+ source = new $.Deferred();
2438
+ dfd.done(function (data, textStatus, jqXHR) {
2439
+ var errorObj, res;
2411
2440
  if(typeof data === "string"){
2412
2441
  $.error("Ajax request returned a string (did you get the JSON dataType wrong?).");
2413
2442
  }
2414
- // postProcess is similar to the standard dataFilter hook,
2443
+ // postProcess is similar to the standard ajax dataFilter hook,
2415
2444
  // but it is also called for JSONP
2416
2445
  if( ctx.options.postProcess ){
2417
- res = tree._triggerNodeEvent("postProcess", ctx, ctx.originalEvent, {response: data, dataType: this.dataType});
2446
+ res = tree._triggerNodeEvent("postProcess", ctx, ctx.originalEvent, {response: data, error: null, dataType: this.dataType});
2447
+ if( res.error ) {
2448
+ errorObj = $.isPlainObject(res.error) ? res.error : {message: res.error};
2449
+ errorObj = tree._makeHookContext(node, null, errorObj);
2450
+ source.rejectWith(this, [errorObj]);
2451
+ return;
2452
+ }
2418
2453
  data = $.isArray(res) ? res : data;
2454
+
2419
2455
  } else if (data && data.hasOwnProperty("d") && ctx.options.enableAspx ) {
2420
2456
  // Process ASPX WebMethod JSON object inside "d" property
2421
2457
  data = (typeof data.d === "string") ? $.parseJSON(data.d) : data.d;
2422
2458
  }
2423
- return data;
2424
- }, function (jqXHR, textStatus, errorThrown) {
2425
- return tree._makeHookContext(node, null, {
2459
+ source.resolveWith(this, [data]);
2460
+ }).fail(function (jqXHR, textStatus, errorThrown) {
2461
+ var errorObj = tree._makeHookContext(node, null, {
2426
2462
  error: jqXHR,
2427
2463
  args: Array.prototype.slice.call(arguments),
2428
2464
  message: errorThrown,
2429
2465
  details: jqXHR.status + ": " + errorThrown
2430
2466
  });
2467
+ source.rejectWith(this, [errorObj]);
2431
2468
  });
2432
2469
  }
2433
2470
 
@@ -2437,7 +2474,7 @@ $.extend(Fancytree.prototype,
2437
2474
  // node._isLoading = true;
2438
2475
  tree.nodeSetStatus(ctx, "loading");
2439
2476
 
2440
- source.done(function () {
2477
+ source.done(function (children) {
2441
2478
  tree.nodeSetStatus(ctx, "ok");
2442
2479
  }).fail(function(error){
2443
2480
  var ctxErr;
@@ -2451,8 +2488,9 @@ $.extend(Fancytree.prototype,
2451
2488
  message: error ? (error.message || error.toString()) : ""
2452
2489
  });
2453
2490
  }
2454
- tree._triggerNodeEvent("loaderror", ctxErr, null);
2455
- tree.nodeSetStatus(ctx, "error", ctxErr.message, ctxErr.details);
2491
+ if( tree._triggerNodeEvent("loadError", ctxErr, null) !== false ) {
2492
+ tree.nodeSetStatus(ctx, "error", ctxErr.message, ctxErr.details);
2493
+ }
2456
2494
  });
2457
2495
  }
2458
2496
  // $.when(source) resolves also for non-deferreds
@@ -2472,9 +2510,7 @@ $.extend(Fancytree.prototype,
2472
2510
  _assert($.isArray(children), "expected array of children");
2473
2511
  node._setChildren(children);
2474
2512
  // trigger fancytreeloadchildren
2475
- // if( node.parent ) {
2476
2513
  tree._triggerNodeEvent("loadChildren", node);
2477
- // }
2478
2514
  // }).always(function(){
2479
2515
  // node._isLoading = false;
2480
2516
  });
@@ -3791,7 +3827,7 @@ $.extend($.ui.fancytree,
3791
3827
  /** @lends Fancytree_Static# */
3792
3828
  {
3793
3829
  /** @type {string} */
3794
- version: "2.1.0", // Set to semver by 'grunt release'
3830
+ version: "2.3.0", // Set to semver by 'grunt release'
3795
3831
  /** @type {string} */
3796
3832
  buildType: "production", // Set to 'production' by 'grunt build'
3797
3833
  /** @type {int} */
@@ -4090,8 +4126,8 @@ $.extend($.ui.fancytree,
4090
4126
  * Released under the MIT license
4091
4127
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
4092
4128
  *
4093
- * @version 2.1.0
4094
- * @date 2014-05-29T16:44
4129
+ * @version 2.3.0
4130
+ * @date 2014-08-17T10:39
4095
4131
  */
4096
4132
 
4097
4133
  // To keep the global namespace clean, we wrap everything in a closure
@@ -4255,6 +4291,458 @@ $.ui.fancytree.registerExtension({
4255
4291
  // End of namespace closure
4256
4292
  }(jQuery));
4257
4293
 
4294
+ /*!
4295
+ *
4296
+ * jquery.fancytree.clones.js
4297
+ * Support faster lookup of nodes by key and shared ref-ids.
4298
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
4299
+ *
4300
+ * Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
4301
+ *
4302
+ * Released under the MIT license
4303
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
4304
+ *
4305
+ * @version 2.3.0
4306
+ * @date 2014-08-17T10:39
4307
+ */
4308
+
4309
+ ;(function($, window, document, undefined) {
4310
+
4311
+ "use strict";
4312
+
4313
+ /*******************************************************************************
4314
+ * Private functions and variables
4315
+ */
4316
+ function _assert(cond, msg){
4317
+ // TODO: see qunit.js extractStacktrace()
4318
+ if(!cond){
4319
+ msg = msg ? ": " + msg : "";
4320
+ $.error("Assertion failed" + msg);
4321
+ }
4322
+ }
4323
+
4324
+
4325
+ /* Return first occurrence of member from array. */
4326
+ function _removeArrayMember(arr, elem) {
4327
+ // TODO: use Array.indexOf for IE >= 9
4328
+ var i;
4329
+ for (i = arr.length - 1; i >= 0; i--) {
4330
+ if (arr[i] === elem) {
4331
+ arr.splice(i, 1);
4332
+ return true;
4333
+ }
4334
+ }
4335
+ return false;
4336
+ }
4337
+
4338
+
4339
+ // /**
4340
+ // * Calculate a 32 bit FNV-1a hash
4341
+ // * Found here: https://gist.github.com/vaiorabbit/5657561
4342
+ // * Ref.: http://isthe.com/chongo/tech/comp/fnv/
4343
+ // *
4344
+ // * @param {string} str the input value
4345
+ // * @param {boolean} [asString=false] set to true to return the hash value as
4346
+ // * 8-digit hex string instead of an integer
4347
+ // * @param {integer} [seed] optionally pass the hash of the previous chunk
4348
+ // * @returns {integer | string}
4349
+ // */
4350
+ // function hashFnv32a(str, asString, seed) {
4351
+ // /*jshint bitwise:false */
4352
+ // var i, l,
4353
+ // hval = (seed === undefined) ? 0x811c9dc5 : seed;
4354
+
4355
+ // for (i = 0, l = str.length; i < l; i++) {
4356
+ // hval ^= str.charCodeAt(i);
4357
+ // hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
4358
+ // }
4359
+ // if( asString ){
4360
+ // // Convert to 8 digit hex string
4361
+ // return ("0000000" + (hval >>> 0).toString(16)).substr(-8);
4362
+ // }
4363
+ // return hval >>> 0;
4364
+ // }
4365
+
4366
+
4367
+ /**
4368
+ * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
4369
+ *
4370
+ * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
4371
+ * @see http://github.com/garycourt/murmurhash-js
4372
+ * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
4373
+ * @see http://sites.google.com/site/murmurhash/
4374
+ *
4375
+ * @param {string} key ASCII only
4376
+ * @param {boolean} [asString=false]
4377
+ * @param {number} seed Positive integer only
4378
+ * @return {number} 32-bit positive integer hash
4379
+ */
4380
+ function hashMurmur3(key, asString, seed) {
4381
+ /*jshint bitwise:false */
4382
+ var h1b, k1,
4383
+ remainder = key.length & 3,
4384
+ bytes = key.length - remainder,
4385
+ h1 = seed,
4386
+ c1 = 0xcc9e2d51,
4387
+ c2 = 0x1b873593,
4388
+ i = 0;
4389
+
4390
+ while (i < bytes) {
4391
+ k1 =
4392
+ ((key.charCodeAt(i) & 0xff)) |
4393
+ ((key.charCodeAt(++i) & 0xff) << 8) |
4394
+ ((key.charCodeAt(++i) & 0xff) << 16) |
4395
+ ((key.charCodeAt(++i) & 0xff) << 24);
4396
+ ++i;
4397
+
4398
+ k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
4399
+ k1 = (k1 << 15) | (k1 >>> 17);
4400
+ k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
4401
+
4402
+ h1 ^= k1;
4403
+ h1 = (h1 << 13) | (h1 >>> 19);
4404
+ h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
4405
+ h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
4406
+ }
4407
+
4408
+ k1 = 0;
4409
+
4410
+ switch (remainder) {
4411
+ /*jshint -W086:true */
4412
+ case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
4413
+ case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
4414
+ case 1: k1 ^= (key.charCodeAt(i) & 0xff);
4415
+
4416
+ k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
4417
+ k1 = (k1 << 15) | (k1 >>> 17);
4418
+ k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
4419
+ h1 ^= k1;
4420
+ }
4421
+
4422
+ h1 ^= key.length;
4423
+
4424
+ h1 ^= h1 >>> 16;
4425
+ h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
4426
+ h1 ^= h1 >>> 13;
4427
+ h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
4428
+ h1 ^= h1 >>> 16;
4429
+
4430
+ if( asString ){
4431
+ // Convert to 8 digit hex string
4432
+ return ("0000000" + (h1 >>> 0).toString(16)).substr(-8);
4433
+ }
4434
+ return h1 >>> 0;
4435
+ }
4436
+
4437
+ // console.info(hashMurmur3("costarring"));
4438
+ // console.info(hashMurmur3("costarring", true));
4439
+ // console.info(hashMurmur3("liquid"));
4440
+ // console.info(hashMurmur3("liquid", true));
4441
+
4442
+
4443
+ /*
4444
+ * Return a unique key for node by calculationg the hash of the parents refKey-list
4445
+ */
4446
+ function calcUniqueKey(node) {
4447
+ var key,
4448
+ path = $.map(node.getParentList(false, true), function(e){ return e.refKey || e.key; });
4449
+ path = path.join("/");
4450
+ key = "id_" + hashMurmur3(path, true);
4451
+ node.debug(path + " -> " + key);
4452
+ return key;
4453
+ }
4454
+
4455
+
4456
+ /**
4457
+ * [ext-clones] Return a list of clone-nodes or null.
4458
+ * @param {boolean} [includeSelf=false]
4459
+ * @returns {FancytreeNode[] | null}
4460
+ *
4461
+ * @alias FancytreeNode#getCloneList
4462
+ * @requires jquery.fancytree.clones.js
4463
+ */
4464
+ $.ui.fancytree._FancytreeNodeClass.prototype.getCloneList = function(includeSelf){
4465
+ var key,
4466
+ tree = this.tree,
4467
+ refList = tree.refMap[this.refKey] || null,
4468
+ keyMap = tree.keyMap;
4469
+
4470
+ if( refList ) {
4471
+ key = this.key;
4472
+ // Convert key list to node list
4473
+ if( includeSelf ) {
4474
+ refList = $.map(refList, function(val){ return keyMap[val]; });
4475
+ } else {
4476
+ refList = $.map(refList, function(val){ return val === key ? null : keyMap[val]; });
4477
+ if( refList.length < 1 ) {
4478
+ refList = null;
4479
+ }
4480
+ }
4481
+ }
4482
+ return refList;
4483
+ };
4484
+
4485
+
4486
+ /**
4487
+ * [ext-clones] Return true if this node has at least another clone with same refKey.
4488
+ * @returns {boolean}
4489
+ *
4490
+ * @alias FancytreeNode#isClone
4491
+ * @requires jquery.fancytree.clones.js
4492
+ */
4493
+ $.ui.fancytree._FancytreeNodeClass.prototype.isClone = function(){
4494
+ var refKey = this.refKey || null,
4495
+ refList = refKey && this.tree.refMap[refKey] || null;
4496
+ return !!(refList && refList.length > 1);
4497
+ };
4498
+
4499
+
4500
+ /**
4501
+ * [ext-clones] Update key and/or refKey for an existing node.
4502
+ * @param {string} key
4503
+ * @param {string} refKey
4504
+ * @returns {boolean}
4505
+ *
4506
+ * @alias FancytreeNode#reRegister
4507
+ * @requires jquery.fancytree.clones.js
4508
+ */
4509
+ $.ui.fancytree._FancytreeNodeClass.prototype.reRegister = function(key, refKey){
4510
+ key = (key == null) ? null : "" + key;
4511
+ refKey = (refKey == null) ? null : "" + refKey;
4512
+ this.debug("reRegister", key, refKey);
4513
+
4514
+ var tree = this.tree,
4515
+ prevKey = this.key,
4516
+ prevRefKey = this.refKey,
4517
+ keyMap = tree.keyMap,
4518
+ refMap = tree.refMap,
4519
+ refList = refMap[prevRefKey] || null,
4520
+ // curCloneKeys = refList ? node.getCloneList(true),
4521
+ modified = false;
4522
+
4523
+ // Key has changed: update all references
4524
+ if( key != null && key !== this.key ) {
4525
+ if( keyMap[key] ) {
4526
+ $.error("[ext-clones] reRegister(" + key + "): already exists.");
4527
+ }
4528
+ // Update keyMap
4529
+ delete keyMap[prevKey];
4530
+ keyMap[key] = this;
4531
+ // Update refMap
4532
+ if( refList ) {
4533
+ refMap[prevRefKey] = $.map(refList, function(e){
4534
+ return e === prevKey ? key : e;
4535
+ });
4536
+ }
4537
+ this.key = key;
4538
+ modified = true;
4539
+ }
4540
+
4541
+ // refKey has changed
4542
+ if( refKey != null && refKey !== this.refKey ) {
4543
+ // Remove previous refKeys
4544
+ if( refList ){
4545
+ if( refList.length === 1 ){
4546
+ delete refMap[prevRefKey];
4547
+ }else{
4548
+ refMap[prevRefKey] = $.map(refList, function(e){
4549
+ return e === prevKey ? null : e;
4550
+ });
4551
+ }
4552
+ }
4553
+ // Add refKey
4554
+ if( refMap[refKey] ) {
4555
+ refMap[refKey].append(key);
4556
+ }else{
4557
+ refMap[refKey] = [ this.key ];
4558
+ }
4559
+ this.refKey = refKey;
4560
+ modified = true;
4561
+ }
4562
+ return modified;
4563
+ };
4564
+
4565
+
4566
+ /**
4567
+ * [ext-clones] Return all nodes with a given refKey (null if not found).
4568
+ * @param {string} refKey
4569
+ * @param {FancytreeNode} [rootNode] optionally restrict results to descendants of this node
4570
+ * @returns {FancytreeNode[] | null}
4571
+ * @alias Fancytree#getNodesByRef
4572
+ * @requires jquery.fancytree.clones.js
4573
+ */
4574
+ $.ui.fancytree._FancytreeClass.prototype.getNodesByRef = function(refKey, rootNode){
4575
+ var keyMap = this.keyMap,
4576
+ refList = this.refMap[refKey] || null;
4577
+
4578
+ if( refList ) {
4579
+ // Convert key list to node list
4580
+ if( rootNode ) {
4581
+ refList = $.map(refList, function(val){
4582
+ var node = keyMap[val];
4583
+ return node.isDescendantOf(rootNode) ? node : null;
4584
+ });
4585
+ }else{
4586
+ refList = $.map(refList, function(val){ return keyMap[val]; });
4587
+ }
4588
+ if( refList.length < 1 ) {
4589
+ refList = null;
4590
+ }
4591
+ }
4592
+ return refList;
4593
+ };
4594
+
4595
+
4596
+ /**
4597
+ * [ext-clones] Replace a refKey with a new one.
4598
+ * @param {string} oldRefKey
4599
+ * @param {string} newRefKey
4600
+ * @alias Fancytree#changeRefKey
4601
+ * @requires jquery.fancytree.clones.js
4602
+ */
4603
+ $.ui.fancytree._FancytreeClass.prototype.changeRefKey = function(oldRefKey, newRefKey) {
4604
+ var i, node,
4605
+ keyMap = this.keyMap,
4606
+ refList = this.refMap[oldRefKey] || null;
4607
+
4608
+ if (refList) {
4609
+ for (i = 0; i < refList.length; i++) {
4610
+ node = keyMap[refList[i]];
4611
+ node.refKey = newRefKey;
4612
+ }
4613
+ delete this.refMap[oldRefKey];
4614
+ this.refMap[newRefKey] = refList;
4615
+ }
4616
+ };
4617
+
4618
+
4619
+ /*******************************************************************************
4620
+ * Extension code
4621
+ */
4622
+ $.ui.fancytree.registerExtension({
4623
+ name: "clones",
4624
+ version: "0.0.3",
4625
+ // Default options for this extension.
4626
+ options: {
4627
+ highlightActiveClones: true, // set 'fancytree-active-clone' on active clones and all peers
4628
+ highlightClones: false // set 'fancytree-clone' class on any node that has at least one clone
4629
+ },
4630
+
4631
+ treeCreate: function(ctx){
4632
+ this._super(ctx);
4633
+ ctx.tree.refMap = {};
4634
+ ctx.tree.keyMap = {};
4635
+ },
4636
+ treeInit: function(ctx){
4637
+ this.$container.addClass("fancytree-ext-clones");
4638
+ _assert(ctx.options.defaultKey == null);
4639
+ // Generate unique / reproducible default keys
4640
+ ctx.options.defaultKey = function(node){
4641
+ return calcUniqueKey(node);
4642
+ };
4643
+ // The default implementation loads initial data
4644
+ this._super(ctx);
4645
+ },
4646
+ treeClear: function(ctx){
4647
+ ctx.tree.refMap = {};
4648
+ ctx.tree.keyMap = {};
4649
+ return this._super(ctx);
4650
+ },
4651
+ treeRegisterNode: function(ctx, add, node) {
4652
+ var refList, len,
4653
+ tree = ctx.tree,
4654
+ keyMap = tree.keyMap,
4655
+ refMap = tree.refMap,
4656
+ key = node.key,
4657
+ refKey = (node && node.refKey != null) ? "" + node.refKey : null;
4658
+
4659
+ // ctx.tree.debug("clones.treeRegisterNode", add, node);
4660
+
4661
+ if( key === "_statusNode" ){
4662
+ return this._super(ctx, add, node);
4663
+ }
4664
+
4665
+ if( add ) {
4666
+ if( keyMap[node.key] != null ) {
4667
+ $.error("clones.treeRegisterNode: node.key already exists: " + node.key);
4668
+ }
4669
+ keyMap[key] = node;
4670
+ if( refKey ) {
4671
+ refList = refMap[refKey];
4672
+ if( refList ) {
4673
+ refList.push(key);
4674
+ if( refList.length === 2 && ctx.options.clones.highlightClones ) {
4675
+ // Mark peer node, if it just became a clone (no need to
4676
+ // mark current node, since it will be rendered later anyway)
4677
+ keyMap[refList[0]].renderStatus();
4678
+ }
4679
+ } else {
4680
+ refMap[refKey] = [key];
4681
+ }
4682
+ node.debug("clones.treeRegisterNode: add clone =>", refMap[refKey]);
4683
+ }
4684
+ }else {
4685
+ if( keyMap[key] == null ) {
4686
+ $.error("clones.treeRegisterNode: node.key not registered: " + node.key);
4687
+ }
4688
+ delete keyMap[key];
4689
+ if( refKey ) {
4690
+ refList = refMap[refKey];
4691
+ node.debug("clones.treeRegisterNode: remove clone BEFORE =>", refMap[refKey]);
4692
+ if( refList ) {
4693
+ len = refList.length;
4694
+ if( len <= 1 ){
4695
+ _assert(len === 1);
4696
+ _assert(refList[0] === key);
4697
+ delete refMap[refKey];
4698
+ }else{
4699
+ _removeArrayMember(refList, key);
4700
+ // Unmark peer node, if this was the only clone
4701
+ if( len === 2 && ctx.options.clones.highlightClones ) {
4702
+ // node.debug("clones.treeRegisterNode: last =>", node.getCloneList());
4703
+ keyMap[refList[0]].renderStatus();
4704
+ }
4705
+ }
4706
+ node.debug("clones.treeRegisterNode: remove clone =>", refMap[refKey]);
4707
+ }
4708
+ }
4709
+ }
4710
+ return this._super(ctx, add, node);
4711
+ },
4712
+ nodeRenderStatus: function(ctx) {
4713
+ var $span, res,
4714
+ node = ctx.node;
4715
+
4716
+ res = this._super(ctx);
4717
+
4718
+ if( ctx.options.clones.highlightClones ) {
4719
+ $span = $(node[ctx.tree.statusClassPropName]);
4720
+ // Only if span already exists
4721
+ if( $span.length && node.isClone() ){
4722
+ // node.debug("clones.nodeRenderStatus: ", ctx.options.clones.highlightClones);
4723
+ $span.addClass("fancytree-clone");
4724
+ }
4725
+ }
4726
+ return res;
4727
+ },
4728
+ nodeSetActive: function(ctx, flag) {
4729
+ var res,
4730
+ scpn = ctx.tree.statusClassPropName,
4731
+ node = ctx.node;
4732
+
4733
+ res = this._super(ctx, flag);
4734
+
4735
+ if( ctx.options.clones.highlightActiveClones && node.isClone() ) {
4736
+ $.each(node.getCloneList(true), function(idx, n){
4737
+ n.debug("clones.nodeSetActive: ", flag !== false);
4738
+ $(n[scpn]).toggleClass("fancytree-active-clone", flag !== false);
4739
+ });
4740
+ }
4741
+ return res;
4742
+ }
4743
+ });
4744
+ }(jQuery, window, document));
4745
+
4258
4746
  /*!
4259
4747
  * jquery.fancytree.dnd.js
4260
4748
  *
@@ -4266,8 +4754,8 @@ $.ui.fancytree.registerExtension({
4266
4754
  * Released under the MIT license
4267
4755
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
4268
4756
  *
4269
- * @version 2.1.0
4270
- * @date 2014-05-29T16:44
4757
+ * @version 2.3.0
4758
+ * @date 2014-08-17T10:39
4271
4759
  */
4272
4760
 
4273
4761
  ;(function($, window, document, undefined) {
@@ -4302,9 +4790,8 @@ function _initDragAndDrop(tree) {
4302
4790
  containment: false,
4303
4791
  delay: 0,
4304
4792
  distance: 4,
4305
- // TODO: merge Dynatree issue 419
4306
4793
  revert: false,
4307
- scroll: true, // issue 244: enable scrolling (if ul.fancytree-container)
4794
+ scroll: true, // to disable, also set css 'position: inherit' on ul.fancytree-container
4308
4795
  scrollSpeed: 7,
4309
4796
  scrollSensitivity: 10,
4310
4797
  // Delegate draggable.start, drag, and stop events to our handler
@@ -4461,6 +4948,7 @@ $.ui.fancytree.registerExtension({
4461
4948
  autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering.
4462
4949
  preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
4463
4950
  preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
4951
+ focusOnClick: false, // Focus, although draggable cancels mousedown event (#270)
4464
4952
  dragEnter: null, // Callback(targetNode, data)
4465
4953
  dragOver: null, // Callback(targetNode, data)
4466
4954
  dragDrop: null, // Callback(targetNode, data)
@@ -4473,6 +4961,20 @@ $.ui.fancytree.registerExtension({
4473
4961
  treeInit: function(ctx){
4474
4962
  var tree = ctx.tree;
4475
4963
  this._super(ctx);
4964
+ // issue #270: draggable eats mousedown events
4965
+ if( tree.options.dnd.dragStart ){
4966
+ tree.$container.on("mousedown", function(event){
4967
+ if( !tree.hasFocus() && ctx.options.dnd.focusOnClick ) {
4968
+ var node = $.ui.fancytree.getNode(event);
4969
+ node.debug("Re-enable focus that was prevented by jQuery UI draggable.");
4970
+ // node.setFocus();
4971
+ // $(node.span).closest(":tabbable").focus();
4972
+ // $(event.target).trigger("focus");
4973
+ // $(event.target).closest(":tabbable").trigger("focus");
4974
+ $(event.target).closest(":tabbable").focus();
4975
+ }
4976
+ });
4977
+ }
4476
4978
  _initDragAndDrop(tree);
4477
4979
  },
4478
4980
  /* Override key handler in order to cancel dnd on escape.*/
@@ -4483,6 +4985,12 @@ $.ui.fancytree.registerExtension({
4483
4985
  }
4484
4986
  return this._super(ctx);
4485
4987
  },
4988
+ nodeClick: function(ctx) {
4989
+ // if( ctx.options.dnd.dragStart ){
4990
+ // ctx.tree.$container.focus();
4991
+ // }
4992
+ return this._super(ctx);
4993
+ },
4486
4994
  /* Display drop marker according to hitMode ('after', 'before', 'over', 'out', 'start', 'stop'). */
4487
4995
  _setDndStatus: function(sourceNode, targetNode, helper, hitMode, accept) {
4488
4996
  var posOpts,
@@ -4790,8 +5298,8 @@ $.ui.fancytree.registerExtension({
4790
5298
  * Released under the MIT license
4791
5299
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
4792
5300
  *
4793
- * @version 2.1.0
4794
- * @date 2014-05-29T16:44
5301
+ * @version 2.3.0
5302
+ * @date 2014-08-17T10:39
4795
5303
  */
4796
5304
 
4797
5305
  ;(function($, window, document, undefined) {
@@ -4898,6 +5406,7 @@ $.ui.fancytree._FancytreeNodeClass.prototype.editStart = function(){
4898
5406
  node.editEnd(true, event);
4899
5407
  return false; // so we don't start editmode on Mac
4900
5408
  }
5409
+ event.stopPropagation();
4901
5410
  }).blur(function(event){
4902
5411
  return node.editEnd(true, event);
4903
5412
  });
@@ -5105,8 +5614,8 @@ $.ui.fancytree.registerExtension({
5105
5614
  * Released under the MIT license
5106
5615
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
5107
5616
  *
5108
- * @version 2.1.0
5109
- * @date 2014-05-29T16:44
5617
+ * @version 2.3.0
5618
+ * @date 2014-08-17T10:39
5110
5619
  */
5111
5620
 
5112
5621
  ;(function($, window, document, undefined) {
@@ -5267,8 +5776,8 @@ $.ui.fancytree.registerExtension({
5267
5776
  * Released under the MIT license
5268
5777
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
5269
5778
  *
5270
- * @version 2.1.0
5271
- * @date 2014-05-29T16:44
5779
+ * @version 2.3.0
5780
+ * @date 2014-08-17T10:39
5272
5781
  */
5273
5782
 
5274
5783
  ;(function($, window, document, undefined) {
@@ -5316,6 +5825,7 @@ $.ui.fancytree.registerExtension({
5316
5825
  nodeRenderStatus: function(ctx) {
5317
5826
  var icon, span,
5318
5827
  node = ctx.node,
5828
+ $span = $(node.span),
5319
5829
  opts = ctx.options.glyph,
5320
5830
  // callback = opts.icon,
5321
5831
  map = opts.map
@@ -5328,8 +5838,9 @@ $.ui.fancytree.registerExtension({
5328
5838
  if( node.isRoot() ){
5329
5839
  return;
5330
5840
  }
5331
-
5332
- span = $("span.fancytree-expander", node.span).get(0);
5841
+ // #257: only search one level deep:
5842
+ // span = $("span.fancytree-expander", node.span).get(0);
5843
+ span = $span.children("span.fancytree-expander").get(0);
5333
5844
  if( span ){
5334
5845
  if( node.isLoading() ){
5335
5846
  icon = "loading";
@@ -5342,16 +5853,22 @@ $.ui.fancytree.registerExtension({
5342
5853
  }else{
5343
5854
  icon = "noExpander";
5344
5855
  }
5856
+ // node.debug(icon, map[icon], span);
5345
5857
  span.className = "fancytree-expander " + map[icon];
5346
5858
  }
5347
5859
 
5348
- span = $("span.fancytree-checkbox", node.tr || node.span).get(0);
5860
+ if( node.tr ){
5861
+ span = $(node.tr).children("span.fancytree-checkbox").get(0);
5862
+ }else{
5863
+ span = $span.children("span.fancytree-checkbox").get(0);
5864
+ }
5349
5865
  if( span ){
5350
5866
  icon = node.selected ? "checkboxSelected" : (node.partsel ? "checkboxUnknown" : "checkbox");
5351
5867
  span.className = "fancytree-checkbox " + map[icon];
5352
5868
  }
5353
5869
 
5354
- span = $("span.fancytree-icon", node.span).get(0);
5870
+ // span = $("span.fancytree-icon", node.span).get(0);
5871
+ span = $span.children("span.fancytree-icon").get(0);
5355
5872
  if( span ){
5356
5873
  if( node.folder ){
5357
5874
  icon = node.expanded ? _getIcon(opts, "folderOpen") : _getIcon(opts, "folder");
@@ -5395,8 +5912,8 @@ $.ui.fancytree.registerExtension({
5395
5912
  * Released under the MIT license
5396
5913
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
5397
5914
  *
5398
- * @version 2.1.0
5399
- * @date 2014-05-29T16:44
5915
+ * @version 2.3.0
5916
+ * @date 2014-08-17T10:39
5400
5917
  */
5401
5918
 
5402
5919
  ;(function($, window, document, undefined) {
@@ -5597,8 +6114,8 @@ $.ui.fancytree.registerExtension({
5597
6114
  * Released under the MIT license
5598
6115
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
5599
6116
  *
5600
- * @version 2.1.0
5601
- * @date 2014-05-29T16:44
6117
+ * @version 2.3.0
6118
+ * @date 2014-08-17T10:39
5602
6119
  */
5603
6120
 
5604
6121
  ;(function($, window, document, undefined) {
@@ -5935,8 +6452,8 @@ $.ui.fancytree.registerExtension({
5935
6452
  * Released under the MIT license
5936
6453
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
5937
6454
  *
5938
- * @version 2.1.0
5939
- * @date 2014-05-29T16:44
6455
+ * @version 2.3.0
6456
+ * @date 2014-08-17T10:39
5940
6457
  */
5941
6458
 
5942
6459
  ;(function($, window, document, undefined) {
@@ -6297,8 +6814,8 @@ $.ui.fancytree.registerExtension({
6297
6814
  * Released under the MIT license
6298
6815
  * https://github.com/mar10/fancytree/wiki/LicenseInfo
6299
6816
  *
6300
- * @version 2.1.0
6301
- * @date 2014-05-29T16:44
6817
+ * @version 2.3.0
6818
+ * @date 2014-08-17T10:39
6302
6819
  */
6303
6820
 
6304
6821
  ;(function($, window, document, undefined) {