app/assets/javascripts/fancytree/jquery.fancytree-all.js in fancytree-rails-2.1.0.pre.0 vs app/assets/javascripts/fancytree/jquery.fancytree-all.js in fancytree-rails-2.3.0
- old
+ new
@@ -5,12 +5,12 @@
*
* Copyright (c) 2006-2014, Martin Wendt (http://wwWendt.de)
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
- * @version 2.1.0
- * @date 2014-05-29T16:44
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
*/
/** Core Fancytree module.
*/
@@ -612,11 +612,11 @@
// attributes. Return selection state true, false, or undefined.
function _walk(node){
var i, l, child, s, state, allSelected,someSelected,
children = node.children;
- if( children ){
+ if( children && children.length ){
// check all children recursively
allSelected = true;
someSelected = false;
for( i=0, l=children.length; i<l; i++ ){
@@ -850,10 +850,20 @@
* @returns {boolean}
*/
hasFocus: function() {
return (this.tree.hasFocus() && this.tree.focusNode === this);
},
+ /** Write to browser console if debugLevel >= 1 (prepending node info)
+ *
+ * @param {*} msg string or object or array of such
+ */
+ info: function(msg){
+ if( this.tree.options.debugLevel >= 1 ) {
+ Array.prototype.unshift.call(arguments, this.toString());
+ consoleApply("info", arguments);
+ }
+ },
/** Return true if node is active (see also FancytreeNode#isSelected).
* @returns {boolean}
*/
isActive: function() {
return (this.tree.activeNode === this);
@@ -1061,10 +1071,13 @@
}else if( targetParent.isDescendantOf(this) ){
throw "Cannot move a node to its own descendant";
}
// Unlink this node from current parent
if( this.parent.children.length === 1 ) {
+ if( this.parent === targetParent ){
+ return; // #258
+ }
this.parent.children = this.parent.lazy ? [] : null;
this.parent.expanded = false;
} else {
pos = $.inArray(this, this.parent.children);
_assert(pos >= 0);
@@ -1194,11 +1207,11 @@
sib = null;
// Navigate to node
function _goto(n){
if( n ){
- n.makeVisible();
+ try { n.makeVisible(); } catch(e) {} // #272
// Node may still be hidden by a filter
if( ! $(n.span).is(":visible") ) {
n.debug("Navigate: skipping hidden node");
n.navigate(where, activate);
return;
@@ -1465,17 +1478,24 @@
* @see Fancytree#setFocus
*/
setFocus: function(flag){
return this.tree._callHook("nodeSetFocus", this, flag);
},
- // TODO: setLazyNodeStatus
/**Select this node, i.e. check the checkbox.
* @param {boolean} [flag=true] pass false to deselect
*/
setSelected: function(flag){
return this.tree._callHook("nodeSetSelected", this, flag);
},
+ /**Mark a lazy node as 'error', 'loading', or 'ok'.
+ * @param {string} status 'error', 'ok'
+ * @param {string} [message]
+ * @param {string} [details]
+ */
+ setStatus: function(status, message, details){
+ return this.tree._callHook("nodeSetStatus", this, status, message, details);
+ },
/**Rename this node.
* @param {string} title
*/
setTitle: function(title){
this.title = title;
@@ -1664,10 +1684,13 @@
FT.warn("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead.");
widget.options.lazyload.apply(this, arguments);
};
}
}
+ if( this.options && $.isFunction(this.options.loaderror) ) {
+ $.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead.");
+ }
this.ext = {}; // Active extension instances
// allow to init tree.data.foo from <div data-foo=''>
this.data = _getElementDataAsDict(this.$div);
this._id = $.ui.fancytree._nextId++;
this._ns = ".fancytree-" + this._id; // append for namespaced events
@@ -1881,21 +1904,21 @@
* @param {boolean | string} [active=true]
*/
generateFormElements: function(selected, active) {
// TODO: test case
var nodeList,
- selectedName = (selected !== false) ? "ft_" + this._id : selected,
+ selectedName = (selected !== false) ? "ft_" + this._id + "[]" : selected,
activeName = (active !== false) ? "ft_" + this._id + "_active" : active,
id = "fancytree_result_" + this._id,
- $result = this.$container.find("div#" + id);
+ $result = $("#" + id);
if($result.length){
$result.empty();
}else{
$result = $("<div>", {
id: id
- }).hide().appendTo(this.$container);
+ }).hide().insertAfter(this.$container);
}
if(selectedName){
nodeList = this.getSelectedNodes( this.options.selectMode === 3 );
$.each(nodeList, function(idx, node){
$result.append($("<input>", {
@@ -1965,11 +1988,16 @@
return false;
}
}, true);
return match;
},
- // TODO: getRoot()
+ /** Return the invisible system root node.
+ * @returns {FancytreeNode}
+ */
+ getRootNode: function() {
+ return this.rootNode;
+ },
/**
* Return an array of selected nodes.
* @param {boolean} [stopOnParents=false] only return the topmost selected
* node (useful with selectMode 3)
* @returns {FancytreeNode[]}
@@ -2371,11 +2399,11 @@
* @param {object[]|object|string|$.Promise|function} source
* @returns {$.Promise} The deferred will be resolved as soon as the (ajax)
* data was rendered.
*/
nodeLoadChildren: function(ctx, source) {
- var ajax, delay,
+ var ajax, delay, dfd,
tree = ctx.tree,
node = ctx.node;
if($.isFunction(source)){
source = source();
@@ -2391,55 +2419,64 @@
delay = delay[0] + Math.random() * (delay[1] - delay[0]);
}
node.debug("nodeLoadChildren waiting debug delay " + Math.round(delay) + "ms");
ajax.debugDelay = false;
- source = $.Deferred(function (dfd) {
+ dfd = $.Deferred(function (dfd) {
setTimeout(function () {
$.ajax(ajax)
.done(function () { dfd.resolveWith(this, arguments); })
.fail(function () { dfd.rejectWith(this, arguments); });
}, delay);
});
}else{
- source = $.ajax(ajax);
+ dfd = $.ajax(ajax);
}
- // TODO: change 'pipe' to 'then' for jQuery 1.8
- // $.pipe returns a new Promise with filtered results
- source = source.pipe(function (data, textStatus, jqXHR) {
- var res;
+ // Defer the deferred: we want to be able to reject, even if ajax
+ // resolved ok.
+ source = new $.Deferred();
+ dfd.done(function (data, textStatus, jqXHR) {
+ var errorObj, res;
if(typeof data === "string"){
$.error("Ajax request returned a string (did you get the JSON dataType wrong?).");
}
- // postProcess is similar to the standard dataFilter hook,
+ // postProcess is similar to the standard ajax dataFilter hook,
// but it is also called for JSONP
if( ctx.options.postProcess ){
- res = tree._triggerNodeEvent("postProcess", ctx, ctx.originalEvent, {response: data, dataType: this.dataType});
+ res = tree._triggerNodeEvent("postProcess", ctx, ctx.originalEvent, {response: data, error: null, dataType: this.dataType});
+ if( res.error ) {
+ errorObj = $.isPlainObject(res.error) ? res.error : {message: res.error};
+ errorObj = tree._makeHookContext(node, null, errorObj);
+ source.rejectWith(this, [errorObj]);
+ return;
+ }
data = $.isArray(res) ? res : data;
+
} else if (data && data.hasOwnProperty("d") && ctx.options.enableAspx ) {
// Process ASPX WebMethod JSON object inside "d" property
data = (typeof data.d === "string") ? $.parseJSON(data.d) : data.d;
}
- return data;
- }, function (jqXHR, textStatus, errorThrown) {
- return tree._makeHookContext(node, null, {
+ source.resolveWith(this, [data]);
+ }).fail(function (jqXHR, textStatus, errorThrown) {
+ var errorObj = tree._makeHookContext(node, null, {
error: jqXHR,
args: Array.prototype.slice.call(arguments),
message: errorThrown,
details: jqXHR.status + ": " + errorThrown
});
+ source.rejectWith(this, [errorObj]);
});
}
if($.isFunction(source.promise)){
// `source` is a deferred, i.e. ajax request
_assert(!node.isLoading());
// node._isLoading = true;
tree.nodeSetStatus(ctx, "loading");
- source.done(function () {
+ source.done(function (children) {
tree.nodeSetStatus(ctx, "ok");
}).fail(function(error){
var ctxErr;
if (error.node && error.error && error.message) {
// error is already a context object
@@ -2449,12 +2486,13 @@
error: error, // it can be jqXHR or any custom error
args: Array.prototype.slice.call(arguments),
message: error ? (error.message || error.toString()) : ""
});
}
- tree._triggerNodeEvent("loaderror", ctxErr, null);
- tree.nodeSetStatus(ctx, "error", ctxErr.message, ctxErr.details);
+ if( tree._triggerNodeEvent("loadError", ctxErr, null) !== false ) {
+ tree.nodeSetStatus(ctx, "error", ctxErr.message, ctxErr.details);
+ }
});
}
// $.when(source) resolves also for non-deferreds
return $.when(source).done(function(children){
var metaData;
@@ -2470,13 +2508,11 @@
$.extend(tree.data, metaData);
}
_assert($.isArray(children), "expected array of children");
node._setChildren(children);
// trigger fancytreeloadchildren
- // if( node.parent ) {
tree._triggerNodeEvent("loadChildren", node);
- // }
// }).always(function(){
// node._isLoading = false;
});
},
/** [Not Implemented] */
@@ -3789,11 +3825,11 @@
*/
$.extend($.ui.fancytree,
/** @lends Fancytree_Static# */
{
/** @type {string} */
- version: "2.1.0", // Set to semver by 'grunt release'
+ version: "2.3.0", // Set to semver by 'grunt release'
/** @type {string} */
buildType: "production", // Set to 'production' by 'grunt build'
/** @type {int} */
debugLevel: 1, // Set to 1 by 'grunt build'
// Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel
@@ -4088,12 +4124,12 @@
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
- * @version 2.1.0
- * @date 2014-05-29T16:44
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
*/
// To keep the global namespace clean, we wrap everything in a closure
;(function($, undefined) {
@@ -4254,22 +4290,474 @@
});
// End of namespace closure
}(jQuery));
/*!
+ *
+ * jquery.fancytree.clones.js
+ * Support faster lookup of nodes by key and shared ref-ids.
+ * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
+ *
+ * Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
+ *
+ * Released under the MIT license
+ * https://github.com/mar10/fancytree/wiki/LicenseInfo
+ *
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
+ */
+
+;(function($, window, document, undefined) {
+
+"use strict";
+
+/*******************************************************************************
+ * Private functions and variables
+ */
+function _assert(cond, msg){
+ // TODO: see qunit.js extractStacktrace()
+ if(!cond){
+ msg = msg ? ": " + msg : "";
+ $.error("Assertion failed" + msg);
+ }
+}
+
+
+/* Return first occurrence of member from array. */
+function _removeArrayMember(arr, elem) {
+ // TODO: use Array.indexOf for IE >= 9
+ var i;
+ for (i = arr.length - 1; i >= 0; i--) {
+ if (arr[i] === elem) {
+ arr.splice(i, 1);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+// /**
+// * Calculate a 32 bit FNV-1a hash
+// * Found here: https://gist.github.com/vaiorabbit/5657561
+// * Ref.: http://isthe.com/chongo/tech/comp/fnv/
+// *
+// * @param {string} str the input value
+// * @param {boolean} [asString=false] set to true to return the hash value as
+// * 8-digit hex string instead of an integer
+// * @param {integer} [seed] optionally pass the hash of the previous chunk
+// * @returns {integer | string}
+// */
+// function hashFnv32a(str, asString, seed) {
+// /*jshint bitwise:false */
+// var i, l,
+// hval = (seed === undefined) ? 0x811c9dc5 : seed;
+
+// for (i = 0, l = str.length; i < l; i++) {
+// hval ^= str.charCodeAt(i);
+// hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
+// }
+// if( asString ){
+// // Convert to 8 digit hex string
+// return ("0000000" + (hval >>> 0).toString(16)).substr(-8);
+// }
+// return hval >>> 0;
+// }
+
+
+/**
+ * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
+ *
+ * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
+ * @see http://github.com/garycourt/murmurhash-js
+ * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
+ * @see http://sites.google.com/site/murmurhash/
+ *
+ * @param {string} key ASCII only
+ * @param {boolean} [asString=false]
+ * @param {number} seed Positive integer only
+ * @return {number} 32-bit positive integer hash
+ */
+function hashMurmur3(key, asString, seed) {
+ /*jshint bitwise:false */
+ var h1b, k1,
+ remainder = key.length & 3,
+ bytes = key.length - remainder,
+ h1 = seed,
+ c1 = 0xcc9e2d51,
+ c2 = 0x1b873593,
+ i = 0;
+
+ while (i < bytes) {
+ k1 =
+ ((key.charCodeAt(i) & 0xff)) |
+ ((key.charCodeAt(++i) & 0xff) << 8) |
+ ((key.charCodeAt(++i) & 0xff) << 16) |
+ ((key.charCodeAt(++i) & 0xff) << 24);
+ ++i;
+
+ k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
+ k1 = (k1 << 15) | (k1 >>> 17);
+ k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
+
+ h1 ^= k1;
+ h1 = (h1 << 13) | (h1 >>> 19);
+ h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
+ h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
+ }
+
+ k1 = 0;
+
+ switch (remainder) {
+ /*jshint -W086:true */
+ case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
+ case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
+ case 1: k1 ^= (key.charCodeAt(i) & 0xff);
+
+ k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
+ k1 = (k1 << 15) | (k1 >>> 17);
+ k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
+ h1 ^= k1;
+ }
+
+ h1 ^= key.length;
+
+ h1 ^= h1 >>> 16;
+ h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
+ h1 ^= h1 >>> 13;
+ h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
+ h1 ^= h1 >>> 16;
+
+ if( asString ){
+ // Convert to 8 digit hex string
+ return ("0000000" + (h1 >>> 0).toString(16)).substr(-8);
+ }
+ return h1 >>> 0;
+}
+
+// console.info(hashMurmur3("costarring"));
+// console.info(hashMurmur3("costarring", true));
+// console.info(hashMurmur3("liquid"));
+// console.info(hashMurmur3("liquid", true));
+
+
+/*
+ * Return a unique key for node by calculationg the hash of the parents refKey-list
+ */
+function calcUniqueKey(node) {
+ var key,
+ path = $.map(node.getParentList(false, true), function(e){ return e.refKey || e.key; });
+ path = path.join("/");
+ key = "id_" + hashMurmur3(path, true);
+ node.debug(path + " -> " + key);
+ return key;
+}
+
+
+/**
+ * [ext-clones] Return a list of clone-nodes or null.
+ * @param {boolean} [includeSelf=false]
+ * @returns {FancytreeNode[] | null}
+ *
+ * @alias FancytreeNode#getCloneList
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.getCloneList = function(includeSelf){
+ var key,
+ tree = this.tree,
+ refList = tree.refMap[this.refKey] || null,
+ keyMap = tree.keyMap;
+
+ if( refList ) {
+ key = this.key;
+ // Convert key list to node list
+ if( includeSelf ) {
+ refList = $.map(refList, function(val){ return keyMap[val]; });
+ } else {
+ refList = $.map(refList, function(val){ return val === key ? null : keyMap[val]; });
+ if( refList.length < 1 ) {
+ refList = null;
+ }
+ }
+ }
+ return refList;
+};
+
+
+/**
+ * [ext-clones] Return true if this node has at least another clone with same refKey.
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#isClone
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.isClone = function(){
+ var refKey = this.refKey || null,
+ refList = refKey && this.tree.refMap[refKey] || null;
+ return !!(refList && refList.length > 1);
+};
+
+
+/**
+ * [ext-clones] Update key and/or refKey for an existing node.
+ * @param {string} key
+ * @param {string} refKey
+ * @returns {boolean}
+ *
+ * @alias FancytreeNode#reRegister
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeNodeClass.prototype.reRegister = function(key, refKey){
+ key = (key == null) ? null : "" + key;
+ refKey = (refKey == null) ? null : "" + refKey;
+ this.debug("reRegister", key, refKey);
+
+ var tree = this.tree,
+ prevKey = this.key,
+ prevRefKey = this.refKey,
+ keyMap = tree.keyMap,
+ refMap = tree.refMap,
+ refList = refMap[prevRefKey] || null,
+// curCloneKeys = refList ? node.getCloneList(true),
+ modified = false;
+
+ // Key has changed: update all references
+ if( key != null && key !== this.key ) {
+ if( keyMap[key] ) {
+ $.error("[ext-clones] reRegister(" + key + "): already exists.");
+ }
+ // Update keyMap
+ delete keyMap[prevKey];
+ keyMap[key] = this;
+ // Update refMap
+ if( refList ) {
+ refMap[prevRefKey] = $.map(refList, function(e){
+ return e === prevKey ? key : e;
+ });
+ }
+ this.key = key;
+ modified = true;
+ }
+
+ // refKey has changed
+ if( refKey != null && refKey !== this.refKey ) {
+ // Remove previous refKeys
+ if( refList ){
+ if( refList.length === 1 ){
+ delete refMap[prevRefKey];
+ }else{
+ refMap[prevRefKey] = $.map(refList, function(e){
+ return e === prevKey ? null : e;
+ });
+ }
+ }
+ // Add refKey
+ if( refMap[refKey] ) {
+ refMap[refKey].append(key);
+ }else{
+ refMap[refKey] = [ this.key ];
+ }
+ this.refKey = refKey;
+ modified = true;
+ }
+ return modified;
+};
+
+
+/**
+ * [ext-clones] Return all nodes with a given refKey (null if not found).
+ * @param {string} refKey
+ * @param {FancytreeNode} [rootNode] optionally restrict results to descendants of this node
+ * @returns {FancytreeNode[] | null}
+ * @alias Fancytree#getNodesByRef
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.getNodesByRef = function(refKey, rootNode){
+ var keyMap = this.keyMap,
+ refList = this.refMap[refKey] || null;
+
+ if( refList ) {
+ // Convert key list to node list
+ if( rootNode ) {
+ refList = $.map(refList, function(val){
+ var node = keyMap[val];
+ return node.isDescendantOf(rootNode) ? node : null;
+ });
+ }else{
+ refList = $.map(refList, function(val){ return keyMap[val]; });
+ }
+ if( refList.length < 1 ) {
+ refList = null;
+ }
+ }
+ return refList;
+};
+
+
+/**
+ * [ext-clones] Replace a refKey with a new one.
+ * @param {string} oldRefKey
+ * @param {string} newRefKey
+ * @alias Fancytree#changeRefKey
+ * @requires jquery.fancytree.clones.js
+ */
+$.ui.fancytree._FancytreeClass.prototype.changeRefKey = function(oldRefKey, newRefKey) {
+ var i, node,
+ keyMap = this.keyMap,
+ refList = this.refMap[oldRefKey] || null;
+
+ if (refList) {
+ for (i = 0; i < refList.length; i++) {
+ node = keyMap[refList[i]];
+ node.refKey = newRefKey;
+ }
+ delete this.refMap[oldRefKey];
+ this.refMap[newRefKey] = refList;
+ }
+};
+
+
+/*******************************************************************************
+ * Extension code
+ */
+$.ui.fancytree.registerExtension({
+ name: "clones",
+ version: "0.0.3",
+ // Default options for this extension.
+ options: {
+ highlightActiveClones: true, // set 'fancytree-active-clone' on active clones and all peers
+ highlightClones: false // set 'fancytree-clone' class on any node that has at least one clone
+ },
+
+ treeCreate: function(ctx){
+ this._super(ctx);
+ ctx.tree.refMap = {};
+ ctx.tree.keyMap = {};
+ },
+ treeInit: function(ctx){
+ this.$container.addClass("fancytree-ext-clones");
+ _assert(ctx.options.defaultKey == null);
+ // Generate unique / reproducible default keys
+ ctx.options.defaultKey = function(node){
+ return calcUniqueKey(node);
+ };
+ // The default implementation loads initial data
+ this._super(ctx);
+ },
+ treeClear: function(ctx){
+ ctx.tree.refMap = {};
+ ctx.tree.keyMap = {};
+ return this._super(ctx);
+ },
+ treeRegisterNode: function(ctx, add, node) {
+ var refList, len,
+ tree = ctx.tree,
+ keyMap = tree.keyMap,
+ refMap = tree.refMap,
+ key = node.key,
+ refKey = (node && node.refKey != null) ? "" + node.refKey : null;
+
+// ctx.tree.debug("clones.treeRegisterNode", add, node);
+
+ if( key === "_statusNode" ){
+ return this._super(ctx, add, node);
+ }
+
+ if( add ) {
+ if( keyMap[node.key] != null ) {
+ $.error("clones.treeRegisterNode: node.key already exists: " + node.key);
+ }
+ keyMap[key] = node;
+ if( refKey ) {
+ refList = refMap[refKey];
+ if( refList ) {
+ refList.push(key);
+ if( refList.length === 2 && ctx.options.clones.highlightClones ) {
+ // Mark peer node, if it just became a clone (no need to
+ // mark current node, since it will be rendered later anyway)
+ keyMap[refList[0]].renderStatus();
+ }
+ } else {
+ refMap[refKey] = [key];
+ }
+ node.debug("clones.treeRegisterNode: add clone =>", refMap[refKey]);
+ }
+ }else {
+ if( keyMap[key] == null ) {
+ $.error("clones.treeRegisterNode: node.key not registered: " + node.key);
+ }
+ delete keyMap[key];
+ if( refKey ) {
+ refList = refMap[refKey];
+ node.debug("clones.treeRegisterNode: remove clone BEFORE =>", refMap[refKey]);
+ if( refList ) {
+ len = refList.length;
+ if( len <= 1 ){
+ _assert(len === 1);
+ _assert(refList[0] === key);
+ delete refMap[refKey];
+ }else{
+ _removeArrayMember(refList, key);
+ // Unmark peer node, if this was the only clone
+ if( len === 2 && ctx.options.clones.highlightClones ) {
+// node.debug("clones.treeRegisterNode: last =>", node.getCloneList());
+ keyMap[refList[0]].renderStatus();
+ }
+ }
+ node.debug("clones.treeRegisterNode: remove clone =>", refMap[refKey]);
+ }
+ }
+ }
+ return this._super(ctx, add, node);
+ },
+ nodeRenderStatus: function(ctx) {
+ var $span, res,
+ node = ctx.node;
+
+ res = this._super(ctx);
+
+ if( ctx.options.clones.highlightClones ) {
+ $span = $(node[ctx.tree.statusClassPropName]);
+ // Only if span already exists
+ if( $span.length && node.isClone() ){
+// node.debug("clones.nodeRenderStatus: ", ctx.options.clones.highlightClones);
+ $span.addClass("fancytree-clone");
+ }
+ }
+ return res;
+ },
+ nodeSetActive: function(ctx, flag) {
+ var res,
+ scpn = ctx.tree.statusClassPropName,
+ node = ctx.node;
+
+ res = this._super(ctx, flag);
+
+ if( ctx.options.clones.highlightActiveClones && node.isClone() ) {
+ $.each(node.getCloneList(true), function(idx, n){
+ n.debug("clones.nodeSetActive: ", flag !== false);
+ $(n[scpn]).toggleClass("fancytree-active-clone", flag !== false);
+ });
+ }
+ return res;
+ }
+});
+}(jQuery, window, document));
+
+/*!
* jquery.fancytree.dnd.js
*
* Drag-and-drop support.
* (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
*
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
- * @version 2.1.0
- * @date 2014-05-29T16:44
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
*/
;(function($, window, document, undefined) {
"use strict";
@@ -4300,13 +4788,12 @@
addClasses: false,
appendTo: "body",
containment: false,
delay: 0,
distance: 4,
- // TODO: merge Dynatree issue 419
revert: false,
- scroll: true, // issue 244: enable scrolling (if ul.fancytree-container)
+ scroll: true, // to disable, also set css 'position: inherit' on ul.fancytree-container
scrollSpeed: 7,
scrollSensitivity: 10,
// Delegate draggable.start, drag, and stop events to our handler
connectToFancytree: true,
// Let source tree create the helper element
@@ -4459,10 +4946,11 @@
// helper: null,
// Make tree nodes accept draggables
autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering.
preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
+ focusOnClick: false, // Focus, although draggable cancels mousedown event (#270)
dragEnter: null, // Callback(targetNode, data)
dragOver: null, // Callback(targetNode, data)
dragDrop: null, // Callback(targetNode, data)
dragLeave: null, // Callback(targetNode, data)
//
@@ -4471,20 +4959,40 @@
},
treeInit: function(ctx){
var tree = ctx.tree;
this._super(ctx);
+ // issue #270: draggable eats mousedown events
+ if( tree.options.dnd.dragStart ){
+ tree.$container.on("mousedown", function(event){
+ if( !tree.hasFocus() && ctx.options.dnd.focusOnClick ) {
+ var node = $.ui.fancytree.getNode(event);
+ node.debug("Re-enable focus that was prevented by jQuery UI draggable.");
+ // node.setFocus();
+ // $(node.span).closest(":tabbable").focus();
+ // $(event.target).trigger("focus");
+ // $(event.target).closest(":tabbable").trigger("focus");
+ $(event.target).closest(":tabbable").focus();
+ }
+ });
+ }
_initDragAndDrop(tree);
},
/* Override key handler in order to cancel dnd on escape.*/
nodeKeydown: function(ctx) {
var event = ctx.originalEvent;
if( event.which === $.ui.keyCode.ESCAPE) {
this._local._cancelDrag();
}
return this._super(ctx);
},
+ nodeClick: function(ctx) {
+ // if( ctx.options.dnd.dragStart ){
+ // ctx.tree.$container.focus();
+ // }
+ return this._super(ctx);
+ },
/* Display drop marker according to hitMode ('after', 'before', 'over', 'out', 'start', 'stop'). */
_setDndStatus: function(sourceNode, targetNode, helper, hitMode, accept) {
var posOpts,
markerOffsetX = 0,
markerAt = "center",
@@ -4788,12 +5296,12 @@
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
- * @version 2.1.0
- * @date 2014-05-29T16:44
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
*/
;(function($, window, document, undefined) {
"use strict";
@@ -4896,10 +5404,11 @@
break;
case $.ui.keyCode.ENTER:
node.editEnd(true, event);
return false; // so we don't start editmode on Mac
}
+ event.stopPropagation();
}).blur(function(event){
return node.editEnd(true, event);
});
instOpts.edit.call(node, {type: "edit"}, eventData);
@@ -5103,12 +5612,12 @@
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
- * @version 2.1.0
- * @date 2014-05-29T16:44
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
*/
;(function($, window, document, undefined) {
"use strict";
@@ -5265,12 +5774,12 @@
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
- * @version 2.1.0
- * @date 2014-05-29T16:44
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
*/
;(function($, window, document, undefined) {
"use strict";
@@ -5314,10 +5823,11 @@
tree.$container.addClass("fancytree-ext-glyph");
},
nodeRenderStatus: function(ctx) {
var icon, span,
node = ctx.node,
+ $span = $(node.span),
opts = ctx.options.glyph,
// callback = opts.icon,
map = opts.map
// prefix = opts.prefix
// $span = $(node.span)
@@ -5326,12 +5836,13 @@
this._super(ctx);
if( node.isRoot() ){
return;
}
-
- span = $("span.fancytree-expander", node.span).get(0);
+ // #257: only search one level deep:
+ // span = $("span.fancytree-expander", node.span).get(0);
+ span = $span.children("span.fancytree-expander").get(0);
if( span ){
if( node.isLoading() ){
icon = "loading";
}else if( node.expanded ){
icon = "expanderOpen";
@@ -5340,20 +5851,26 @@
}else if( node.hasChildren() ){
icon = "expanderClosed";
}else{
icon = "noExpander";
}
+ // node.debug(icon, map[icon], span);
span.className = "fancytree-expander " + map[icon];
}
- span = $("span.fancytree-checkbox", node.tr || node.span).get(0);
+ if( node.tr ){
+ span = $(node.tr).children("span.fancytree-checkbox").get(0);
+ }else{
+ span = $span.children("span.fancytree-checkbox").get(0);
+ }
if( span ){
icon = node.selected ? "checkboxSelected" : (node.partsel ? "checkboxUnknown" : "checkbox");
span.className = "fancytree-checkbox " + map[icon];
}
- span = $("span.fancytree-icon", node.span).get(0);
+ // span = $("span.fancytree-icon", node.span).get(0);
+ span = $span.children("span.fancytree-icon").get(0);
if( span ){
if( node.folder ){
icon = node.expanded ? _getIcon(opts, "folderOpen") : _getIcon(opts, "folder");
}else{
icon = node.expanded ? _getIcon(opts, "docOpen") : _getIcon(opts, "doc");
@@ -5393,12 +5910,12 @@
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
- * @version 2.1.0
- * @date 2014-05-29T16:44
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
*/
;(function($, window, document, undefined) {
"use strict";
@@ -5595,12 +6112,12 @@
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
- * @version 2.1.0
- * @date 2014-05-29T16:44
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
*/
;(function($, window, document, undefined) {
"use strict";
@@ -5933,12 +6450,12 @@
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
- * @version 2.1.0
- * @date 2014-05-29T16:44
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
*/
;(function($, window, document, undefined) {
"use strict";
@@ -6295,11 +6812,11 @@
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
- * @version 2.1.0
- * @date 2014-05-29T16:44
+ * @version 2.3.0
+ * @date 2014-08-17T10:39
*/
;(function($, window, document, undefined) {
"use strict";