first commit

This commit is contained in:
2024-10-23 12:55:46 +02:00
commit 85c92aa932
8453 changed files with 1186172 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
Copyright 2006-2014 Martin Wendt,
http://wwWendt.de/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1 @@
[ {"title": "Sub item", "lazy": true }, {"title": "Sub folder", "folder": true, "lazy": true } ]

View File

@@ -0,0 +1,27 @@
[
{"title": "/", "expanded": true, "folder": true, "children": [
{"title": "dev", "folder": true},
{"title": "etc", "folder": true, "children": [
{"title": "cups"},
{"title": "httpd"},
{"title": "init.d"}
]},
{"title": "sbin", "folder": true},
{"title": "tmp", "folder": true},
{"title": "Users", "expanded": true, "folder": true, "children": [
{"title": "jdoe", "folder": true},
{"title": "jmiller", "folder": true},
{"title": "mysql", "folder": true}
]},
{"title": "usr", "expanded": true, "folder": true, "children": [
{"title": "bin", "folder": true},
{"title": "lib", "folder": true},
{"title": "local", "folder": true}
]},
{"title": "var", "expanded": true, "folder": true, "children": [
{"title": "log", "folder": true},
{"title": "spool", "folder": true},
{"title": "yp", "folder": true}
]}
]}
]

View File

@@ -0,0 +1,28 @@
[
{"title": "simple node (no explicit id, so a default key is generated)" },
{"key": "2", "title": "item1 with key and tooltip", "tooltip": "Look, a tool tip!" },
{"key": "3", "title": "<span>item2 with <b>html</b> inside a span tag</span>" },
{"key": "4", "title": "node 4" },
{"key": "5", "title": "using href", "href": "http://www.wwWendt.de/" },
{"key": "6", "title": "node with some extra classes (will be added to the generated markup)", "extraClasses": "my-extra-class" },
{"key": "10", "title": "Folder 1", "folder": true, "children": [
{"key": "10_1", "title": "Sub-item 1.1", "children": [
{"key": "10_1_1", "title": "Sub-item 1.1.1"},
{"key": "10_1_2", "title": "Sub-item 1.1.2"}
]},
{"key": "10_2", "title": "Sub-item 1.2", "children": [
{"key": "10_2_1", "title": "Sub-item 1.2.1"},
{"key": "10_2_2", "title": "Sub-item 1.2.2"}
]}
]},
{"key": "20", "title": "Simple node with active children (expand)", "expanded": true, "children": [
{"key": "20_1", "title": "Sub-item 2.1", "children": [
{"key": "20_1_1", "title": "Sub-item 2.1.1"},
{"key": "20_1_2", "title": "Sub-item 2.1.2"}
]},
{"key": "20_2", "title": "Sub-item 2.2", "children": [
{"key": "20_2_1", "title": "Sub-item 2.2.1"},
{"key": "20_2_2", "title": "Sub-item 2.2.2"}
]}
]}
]

View File

@@ -0,0 +1,33 @@
[
{"title": "simple node (no explicit id, so a default key is generated)" },
{"key": "2", "title": "item1 with key and tooltip", "tooltip": "Look, a tool tip!" },
{"key": "3", "title": "<span>item2 with <b>html</b> inside a span tag</span>" },
{"key": "4", "title": "node 4" },
{"key": "5", "title": "using href", "href": "http://www.wwWendt.de/" },
{"key": "6", "title": "node with some extra classes (will be added to the generated markup)", "extraClasses": "my-extra-class" },
{"key": "10", "title": "Folder 1", "folder": true, "children": [
{"key": "10_1", "title": "Sub-item 1.1", "children": [
{"key": "10_1_1", "title": "Sub-item 1.1.1"},
{"key": "10_1_2", "title": "Sub-item 1.1.2"}
]},
{"key": "10_2", "title": "Sub-item 1.2", "children": [
{"key": "10_2_1", "title": "Sub-item 1.2.1"},
{"key": "10_2_2", "title": "Sub-item 1.2.2"}
]}
]},
{"key": "20", "title": "Simple node with active children (expand)", "expanded": true, "children": [
{"key": "20_1", "title": "Sub-item 2.1", "children": [
{"key": "20_1_1", "title": "Sub-item 2.1.1", "children": [
{"key": "20_1_1_1", "title": "Sub-item 2.1.1.1"}
]},
{"key": "20_1_2", "title": "Sub-item 2.1.2"}
]},
{"key": "20_2", "title": "Sub-item 2.2", "children": [
{"key": "20_2_1", "title": "Sub-item 2.2.1"},
{"key": "20_2_2", "title": "Sub-item 2.2.2"}
]}
]},
{"key": "30", "title": "Lazy folder", "folder": true, "lazy": true },
{"key": "31", "title": "Lazy folder 2", "folder": true, "lazy": true },
{"key": "32", "title": "Lazy folder 3", "folder": true, "lazy": true }
]

View File

@@ -0,0 +1,33 @@
[
{"title": "simple node (no explicit id, so a default key is generated)" },
{"key": "2", "title": "item1 with key and tooltip", "tooltip": "Look, a tool tip!" },
{"key": "3", "title": "<span>item2 with <b>html</b> inside a span tag</span>" },
{"key": "4", "title": "node 4" },
{"key": "5", "title": "using href", "href": "http://www.wwWendt.de/" },
{"key": "6", "title": "node with some extra classes (will be added to the generated markup)", "extraClasses": "my-extra-class" },
{"key": "10", "title": "Folder 1", "folder": true, "children": [
{"key": "10_1", "title": "Sub-item 1.1", "children": [
{"key": "10_1_1", "title": "Sub-item 1.1.1"},
{"key": "10_1_2", "title": "Sub-item 1.1.2"}
]},
{"key": "10_2", "title": "Sub-item 1.2", "children": [
{"key": "10_2_1", "title": "Sub-item 1.2.1"},
{"key": "10_2_2", "title": "Sub-item 1.2.2"}
]}
]},
{"key": "20", "title": "Simple node with active children (expand)", "expanded": true, "children": [
{"key": "20_1", "title": "Sub-item 2.1", "expanded": true, "selected": true, "children": [
{"key": "20_1_1", "title": "Sub-item 2.1.1", "children": [
{"key": "20_1_1_1", "title": "Sub-item 2.1.1.1"}
]},
{"key": "20_1_2", "title": "Sub-item 2.1.2"}
]},
{"key": "20_2", "title": "Sub-item 2.2", "children": [
{"key": "20_2_1", "title": "Sub-item 2.2.1"},
{"key": "20_2_2", "title": "Sub-item 2.2.2"}
]}
]},
{"key": "30", "title": "Lazy folder", "folder": true, "lazy": true },
{"key": "31", "title": "Lazy folder 2", "folder": true, "lazy": true },
{"key": "32", "title": "Lazy folder 3", "folder": true, "lazy": true }
]

View File

@@ -0,0 +1,22 @@
[
{"title": "Animalia", "expanded": true, "folder": true, "children": [
{"title": "Chordate", "folder": true, "children": [
{"title": "Mammal", "children": [
{"title": "Primate", "children": [
{"title": "Primate", "children": [
]},
{"title": "Carnivora", "children": [
]}
]},
{"title": "Carnivora", "children": [
{"title": "Felidae", "lazy": true}
]}
]}
]},
{"title": "Arthropoda", "expanded": true, "folder": true, "children": [
{"title": "Insect", "children": [
{"title": "Diptera", "lazy": true}
]}
]}
]}
]

View File

@@ -0,0 +1,185 @@
// Extending Fancytree
// ===================
//
// See also the [live demo](http://wwwendt.de/tech/fancytree/demo/sample-ext-childcounter.html) of this code.
//
// Every extension should have a comment header containing some information
// about the author, copyright and licensing. Also a pointer to the latest
// source code.
// Prefix with `/*!` so the comment is not removed by the minifier.
/*!
* jquery.fancytree.childcounter.js
*
* Add a child counter bubble to tree nodes.
* (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.6.0
* @date 2014-11-29T08:33
*/
// To keep the global namespace clean, we wrap everything in a closure
;(function($, undefined) {
// Consider to use [strict mode](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)
"use strict";
// The [coding guidelines](http://contribute.jquery.org/style-guide/js/)
// require jshint compliance.
// But for this sample, we want to allow unused variables for demonstration purpose.
/*jshint unused:false */
// Adding methods
// --------------
// New member functions can be added to the `Fancytree` class.
// This function will be available for every tree instance.
//
// var tree = $("#tree").fancytree("getTree");
// tree.countSelected(false);
$.ui.fancytree._FancytreeClass.prototype.countSelected = function(topOnly){
var tree = this,
treeOptions = tree.options;
return tree.getSelectedNodes(topOnly).length;
};
// The `FancytreeNode` class can also be easily extended. This would be called
// like
//
// node.toUpper();
$.ui.fancytree._FancytreeNodeClass.prototype.toUpper = function(){
var node = this;
return node.setTitle(node.title.toUpperCase());
};
// Finally, we can extend the widget API and create functions that are called
// like so:
//
// $("#tree").fancytree("widgetMethod1", "abc");
$.ui.fancytree.prototype.widgetMethod1 = function(arg1){
var tree = this.tree;
return arg1;
};
// Register a Fancytree extension
// ------------------------------
// A full blown extension, extension is available for all trees and can be
// enabled like so (see also the [live demo](http://wwwendt.de/tech/fancytree/demo/sample-ext-childcounter.html)):
//
// <script src="../src/jquery.fancytree.js" type="text/javascript"></script>
// <script src="../src/jquery.fancytree.childcounter.js" type="text/javascript"></script>
// ...
//
// $("#tree").fancytree({
// extensions: ["childcounter"],
// childcounter: {
// hideExpanded: true
// },
// ...
// });
//
/* 'childcounter' extension */
$.ui.fancytree.registerExtension({
// Every extension must be registered by a unique name.
name: "childcounter",
// Version information should be compliant with [semver](http://semver.org)
version: "1.0.0",
// Extension specific options and their defaults.
// This options will be available as `tree.options.childcounter.hideExpanded`
options: {
deep: true,
hideZeros: true,
hideExpanded: false
},
// Attributes other than `options` (or functions) can be defined here, and
// will be added to the tree.ext.EXTNAME namespace, in this case `tree.ext.childcounter.foo`.
// They can also be accessed as `this._local.foo` from within the extension
// methods.
foo: 42,
// Local functions are prefixed with an underscore '_'.
// Callable as `this._local._appendCounter()`.
_appendCounter: function(bar){
var tree = this;
},
// **Override virtual methods for this extension.**
//
// Fancytree implements a number of 'hook methods', prefixed by 'node...' or 'tree...'.
// with a `ctx` argument (see [EventData](http://www.wwwendt.de/tech/fancytree/doc/jsdoc/global.html#EventData)
// for details) and an extended calling context:<br>
// `this` : the Fancytree instance<br>
// `this._local`: the namespace that contains extension attributes and private methods (same as this.ext.EXTNAME)<br>
// `this._super`: the virtual function that was overridden (member of previous extension or Fancytree)
//
// See also the [complete list of available hook functions](http://www.wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Hooks.html).
/* Init */
// `treeInit` is triggered when a tree is initalized. We can set up classes or
// bind event handlers here...
treeInit: function(ctx){
var tree = this, // same as ctx.tree,
opts = ctx.options,
extOpts = ctx.options.childcounter;
// Optionally check for dependencies with other extensions
/* this._requireExtension("glyph", false, false); */
// Call the base implementation
this._super(ctx);
// Add a class to the tree container
this.$container.addClass("fancytree-ext-childcounter");
},
// Destroy this tree instance (we only call the default implementation, so
// this method could as well be omitted).
treeDestroy: function(ctx){
this._super(ctx);
},
// Overload the `renderTitle` hook, to append a counter badge
nodeRenderTitle: function(ctx, title) {
var node = ctx.node,
extOpts = ctx.options.childcounter,
count = (node.data.childCounter == null) ? node.countChildren(extOpts.deep) : +node.data.childCounter;
// Let the base implementation render the title
this._super(ctx, title);
// Append a counter badge
if( (count || ! extOpts.hideZeros) && (!node.isExpanded() || !extOpts.hideExpanded) ){
$("span.fancytree-icon", node.span).append($("<span class='fancytree-childcounter'/>").text(count));
}
},
// Overload the `setExpanded` hook, so the counters are updated
nodeSetExpanded: function(ctx, flag, opts) {
var tree = ctx.tree,
node = ctx.node;
// Let the base implementation expand/collapse the node, then redraw the title
// after the animation has finished
return this._super(ctx, flag, opts).always(function(){
tree.nodeRenderTitle(ctx);
});
}
// End of extension definition
});
// End of namespace closure
}(jQuery));

View File

@@ -0,0 +1,149 @@
/*!
* jquery.fancytree.columnview.js
*
* Render tree like a Mac Finder's column view.
* (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.6.0
* @date 2014-11-29T08:33
*/
;(function($, window, document, undefined) {
"use strict";
// prevent duplicate loading
// if ( $.ui.fancytree && $.ui.fancytree.version ) {
// $.ui.fancytree.warn("Fancytree: duplicate include");
// return;
// }
/*******************************************************************************
* Private functions and variables
*/
/*
function _assert(cond, msg){
msg = msg || "";
if(!cond){
$.error("Assertion failed " + msg);
}
}
*/
/*******************************************************************************
* Private functions and variables
*/
$.ui.fancytree.registerExtension({
name: "columnview",
version: "0.0.1",
// Default options for this extension.
options: {
},
// Overide virtual methods for this extension.
// `this` : is this extension object
// `this._base` : the Fancytree instance
// `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
treeInit: function(ctx){
var $tdFirst, $ul,
tree = ctx.tree,
$table = tree.widget.element;
tree.tr = $("tbody tr", $table)[0];
tree.columnCount = $(">td", tree.tr).length;
// Perform default behavior
this._super(ctx);
// Standard Fancytree created a root <ul>. Now move this into first table cell
$ul = $(tree.rootNode.ul);
$tdFirst = $(">td", tree.tr).eq(0);
$ul.removeClass("fancytree-container");
$ul.removeAttr("tabindex");
tree.$container = $table;
$table.addClass("fancytree-container fancytree-ext-columnview");
$table.attr("tabindex", "0");
$tdFirst.empty();
$ul.detach().appendTo($tdFirst);
// Force some required options
tree.widget.options.autoCollapse = true;
// tree.widget.options.autoActivate = true;
tree.widget.options.fx = false;
tree.widget.options.clickFolderMode = 1;
// Make sure that only active path is expanded when a node is activated:
$table.bind("fancytreeactivate", function(event, data){
var i, tdList,
node = data.node,
tree = data.tree,
level = node.getLevel();
tree._callHook("nodeCollapseSiblings", node);
// Clear right neighbours
if(level <= tree.columnCount){
tdList = $(">td", tree.tr);
for(i=level; i<tree.columnCount; i++){
tdList.eq(i).empty();
}
}
// Expand nodes on activate, so we populate the right neighbor cell
if(!node.expanded && (node.children || node.lazy)) {
node.setExpanded();
}
// Adjust keyboard behaviour:
}).bind("fancytreekeydown", function(event, data){
var next = null;
switch(event.which){
case $.ui.keyCode.DOWN:
next = data.node.getNextSibling();
if( next ){
next.setFocus();
}
return false;
case $.ui.keyCode.LEFT:
next = data.node.getParent();
if( next ){
next.setFocus();
}
return false;
case $.ui.keyCode.UP:
next = data.node.getPrevSibling();
if( next ){
next.setFocus();
}
return false;
}
});
},
nodeRender: function(ctx, force, deep, collapsed, _recursive) {
// Render standard nested <ul> - <li> hierarchy
this._super(ctx, force, deep, collapsed, _recursive);
// Remove expander and add a trailing triangle instead
var level, $tdChild, $ul,
tree = ctx.tree,
node = ctx.node,
$span = $(node.span);
$span.find("span.fancytree-expander").remove();
if(node.hasChildren() !== false && !$span.find("span.fancytree-cv-right").length){
$span.append($("<span class='fancytree-icon fancytree-cv-right'>"));
}
// Move <ul> with children into the appropriate <td>
if(node.ul){
node.ul.style.display = ""; // might be hidden if RIGHT was pressed
level = node.getLevel();
if(level < tree.columnCount){
$tdChild = $(">td", tree.tr).eq(level);
$ul = $(node.ul).detach();
$tdChild.empty().append($ul);
}
}
}
});
}(jQuery, window, document));

View File

@@ -0,0 +1,142 @@
/*!
* jquery.fancytree.debug.js
*
* Miscellaneous debug extensions.
* (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.6.0
* @date 2014-11-29T08:33
*/
;(function($, window, document, undefined) {
"use strict";
// prevent duplicate loading
// if ( $.ui.fancytree && $.ui.fancytree.version ) {
// $.ui.fancytree.warn("Fancytree: duplicate include");
// return;
// }
/* *****************************************************************************
* Private functions and variables
*/
var i,
HOOK_NAMES = "nodeClick nodeCollapseSiblings".split(" "),
EVENT_NAMES = "activate beforeActivate".split(" "),
HOOK_NAME_MAP = {},
EVENT_NAME_MAP = {};
for(i=0; i<HOOK_NAMES.length; i++){ HOOK_NAME_MAP[HOOK_NAMES[i]] = true; }
for(i=0; i<EVENT_NAMES.length; i++){ EVENT_NAME_MAP[EVENT_NAMES[i]] = true; }
/* *****************************************************************************
* Extension code
*/
$.ui.fancytree.registerExtension({
name: "tracecalls",
version: "0.0.1",
// Default options for this extension.
options: {
logTarget: null, // optional redirect logging to this <div> tag
traceEvents: false, // `true`or list of hook names
traceHooks: false // `true`or list of event names
},
// Overide virtual methods for this extension.
// `this` : is this Fancytree object
// `this._super`: the virtual function that was overridden (member of prev. extension or Fancytree)
treeInit: function(ctx){
var tree = ctx.tree;
// Bind init-handler to apply cookie state
tree.$div.bind("fancytreeinit", function(event){
tree.debug("COOKIE " + document.cookie);
});
// Init the tree
this._super(ctx);
},
nodeClick: function(ctx) {
if(this.options.tracecalls.traceHooks){
this.debug();
}
},
nodeCollapseSiblings: function(ctx) {
},
nodeDblclick: function(ctx) {
},
nodeKeydown: function(ctx) {
},
nodeLoadChildren: function(ctx, source) {
},
nodeOnFocusInOut: function(ctx) {
},
nodeRemoveChildMarkup: function(ctx) {
},
nodeRemoveMarkup: function(ctx) {
},
nodeRender: function(ctx, force, deep, collapsed, _recursive) {
},
nodeRenderStatus: function(ctx) {
},
nodeRenderTitle: function(ctx, title) {
},
nodeSetActive: function(ctx, flag, opts) {
},
nodeSetExpanded: function(ctx, flag, opts) {
},
nodeSetFocus: function(ctx) {
},
nodeSetSelected: function(ctx, flag) {
},
nodeSetStatus: function(ctx, status, message, details) {
},
nodeToggleExpanded: function(ctx) {
},
nodeToggleSelected: function(ctx) {
},
treeClear: function(ctx) {
},
treeCreate: function(ctx) {
},
treeDestroy: function(ctx) {
},
// treeInit: function(ctx) {
// },
treeLoad: function(ctx, source) {
},
treeSetFocus: function(ctx, flag) {
}
});
}(jQuery, window, document));
/* *****************************************************************************
* Fancytree extension: profiler
*/
;(function($, window, document, undefined) {
$.ui.fancytree.registerExtension({
name: "profiler",
version: "0.0.1",
// Default options for this extension
options: {
prefix: ""
},
// Overide virtual methods for this extension
nodeRender: function(ctx, force, deep, collapsed){
// ctx.tree.debug("**** PROFILER nodeRender");
var s = this.options.prefix + "render '" + ctx.node + "'";
/*jshint expr:true */
window.console && window.console.time && window.console.time(s);
this._super(ctx, force, deep, collapsed);
window.console && window.console.timeEnd && window.console.timeEnd(s);
}
});
}(jQuery, window, document));

View File

@@ -0,0 +1,563 @@
/*!
* 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.6.0
* @date 2014-11-29T08:33
*/
;(function($, window, document, undefined) {
"use strict";
/* *****************************************************************************
* Private functions and variables
*/
var didRegisterDnd = false;
/* Convert number to string and prepend +/-; return empty string for 0.*/
function offsetString(n){
return n === 0 ? "" : (( n > 0 ) ? ("+" + n) : ("" + n));
}
/* *****************************************************************************
* Drag and drop support
*/
function _initDragAndDrop(tree) {
var dnd = tree.options.dnd || null;
// Register 'connectToFancytree' option with ui.draggable
if( dnd ) {
_registerDnd();
}
// Attach ui.draggable to this Fancytree instance
if(dnd && dnd.dragStart ) {
tree.widget.element.draggable($.extend({
addClasses: false,
// DT issue 244: helper should be child of scrollParent:
appendTo: tree.$container,
// appendTo: "body",
containment: false,
delay: 0,
distance: 4,
revert: false,
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
helper: function(event) {
var $helper,
sourceNode = $.ui.fancytree.getNode(event.target),
$nodeTag = $(sourceNode.span);
if(!sourceNode){
// DT issue 211: might happen, if dragging a table *header*
return "<div>ERROR?: helper requested but sourceNode not found</div>";
}
// Only event and node argument is available
$helper = $("<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>")
.css({zIndex: 3, position: "relative"}) // so it appears above ext-wide selection bar
.append($nodeTag.find("span.fancytree-title").clone());
// Attach node reference to helper object
$helper.data("ftSourceNode", sourceNode);
// we return an unconnected element, so `draggable` will add this
// to the parent specified as `appendTo` option
return $helper;
},
start: function(event, ui) {
var sourceNode = ui.helper.data("ftSourceNode");
return !!sourceNode; // Abort dragging if no node could be found
}
}, tree.options.dnd.draggable));
}
// Attach ui.droppable to this Fancytree instance
if(dnd && dnd.dragDrop) {
tree.widget.element.droppable($.extend({
addClasses: false,
tolerance: "intersect",
greedy: false
/*
activate: function(event, ui) {
tree.debug("droppable - activate", event, ui, this);
},
create: function(event, ui) {
tree.debug("droppable - create", event, ui);
},
deactivate: function(event, ui) {
tree.debug("droppable - deactivate", event, ui);
},
drop: function(event, ui) {
tree.debug("droppable - drop", event, ui);
},
out: function(event, ui) {
tree.debug("droppable - out", event, ui);
},
over: function(event, ui) {
tree.debug("droppable - over", event, ui);
}
*/
}, tree.options.dnd.droppable));
}
}
//--- Extend ui.draggable event handling --------------------------------------
function _registerDnd() {
if(didRegisterDnd){
return;
}
// Register proxy-functions for draggable.start/drag/stop
$.ui.plugin.add("draggable", "connectToFancytree", {
start: function(event, ui) {
// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
var draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
sourceNode = ui.helper.data("ftSourceNode") || null;
if(sourceNode) {
// Adjust helper offset, so cursor is slightly outside top/left corner
draggable.offset.click.top = -2;
draggable.offset.click.left = + 16;
// Trigger dragStart event
// TODO: when called as connectTo..., the return value is ignored(?)
return sourceNode.tree.ext.dnd._onDragEvent("start", sourceNode, null, event, ui, draggable);
}
},
drag: function(event, ui) {
var isHelper, logObject,
// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
sourceNode = ui.helper.data("ftSourceNode") || null,
prevTargetNode = ui.helper.data("ftTargetNode") || null,
targetNode = $.ui.fancytree.getNode(event.target);
if(event.target && !targetNode){
// We got a drag event, but the targetNode could not be found
// at the event location. This may happen,
// 1. if the mouse jumped over the drag helper,
// 2. or if a non-fancytree element is dragged
// We ignore it:
isHelper = $(event.target).closest("div.fancytree-drag-helper,#fancytree-drop-marker").length > 0;
if(isHelper){
logObject = sourceNode || prevTargetNode || $.ui.fancytree;
logObject.debug("Drag event over helper: ignored.");
return;
}
}
ui.helper.data("ftTargetNode", targetNode);
// Leaving a tree node
if(prevTargetNode && prevTargetNode !== targetNode ) {
prevTargetNode.tree.ext.dnd._onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
}
if(targetNode){
if(!targetNode.tree.options.dnd.dragDrop) {
// not enabled as drop target
} else if(targetNode === prevTargetNode) {
// Moving over same node
targetNode.tree.ext.dnd._onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
}else{
// Entering this node first time
targetNode.tree.ext.dnd._onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
}
}
// else go ahead with standard event handling
},
stop: function(event, ui) {
// 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10
var logObject,
draggable = $(this).data("ui-draggable") || $(this).data("draggable"),
sourceNode = ui.helper.data("ftSourceNode") || null,
targetNode = ui.helper.data("ftTargetNode") || null,
// mouseDownEvent = draggable._mouseDownEvent,
eventType = event.type,
dropped = (eventType === "mouseup" && event.which === 1);
if(!dropped){
logObject = sourceNode || targetNode || $.ui.fancytree;
logObject.debug("Drag was cancelled");
}
if(targetNode) {
if(dropped){
targetNode.tree.ext.dnd._onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
}
targetNode.tree.ext.dnd._onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
}
if(sourceNode){
sourceNode.tree.ext.dnd._onDragEvent("stop", sourceNode, null, event, ui, draggable);
}
}
});
didRegisterDnd = true;
}
/* *****************************************************************************
*
*/
$.ui.fancytree.registerExtension({
name: "dnd",
version: "0.1.0",
// Default options for this extension.
options: {
// Make tree nodes accept draggables
autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering.
draggable: null, // Additional options passed to jQuery draggable
droppable: null, // Additional options passed to jQuery droppable
focusOnClick: false, // Focus, although draggable cancels mousedown event (#270)
// helper: null, // Callback
// helperParent: null, // jQuery object (defaults to Fancytree container)
preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
// Events (drag support)
dragStart: null, // Callback(sourceNode, data), return true, to enable dnd
dragStop: null, // Callback(sourceNode, data)
// Events (drop support)
dragEnter: null, // Callback(targetNode, data)
dragOver: null, // Callback(targetNode, data)
dragDrop: null, // Callback(targetNode, data)
dragLeave: null // Callback(targetNode, data)
},
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");
setTimeout(function() { // #300
$(event.target).closest(":tabbable").focus();
}, 10);
}
});
}
_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",
instData = this._local,
$source = sourceNode ? $(sourceNode.span) : null,
$target = $(targetNode.span);
if( !instData.$dropMarker ) {
instData.$dropMarker = $("<div id='fancytree-drop-marker'></div>")
.hide()
.css({"z-index": 1000})
.prependTo($(this.$div).parent());
// .prependTo("body");
}
// this.$dropMarker.attr("class", hitMode);
if(hitMode === "after" || hitMode === "before" || hitMode === "over"){
// $source && $source.addClass("fancytree-drag-source");
// $target.addClass("fancytree-drop-target");
switch(hitMode){
case "before":
instData
.$dropMarker.removeClass("fancytree-drop-after fancytree-drop-over")
.addClass("fancytree-drop-before");
markerAt = "top";
break;
case "after":
instData.$dropMarker.removeClass("fancytree-drop-before fancytree-drop-over")
.addClass("fancytree-drop-after");
markerAt = "bottom";
break;
default:
instData.$dropMarker.removeClass("fancytree-drop-after fancytree-drop-before")
.addClass("fancytree-drop-over");
$target.addClass("fancytree-drop-target");
markerOffsetX = 8;
}
if( $.ui.fancytree.jquerySupports.positionMyOfs ){
posOpts = {
my: "left" + offsetString(markerOffsetX) + " center",
at: "left " + markerAt,
of: $target
};
} else {
posOpts = {
my: "left center",
at: "left " + markerAt,
of: $target,
offset: "" + markerOffsetX + " 0"
};
}
instData.$dropMarker
.show()
.position(posOpts);
// helper.addClass("fancytree-drop-hover");
} else {
// $source && $source.removeClass("fancytree-drag-source");
$target.removeClass("fancytree-drop-target");
instData.$dropMarker.hide();
// helper.removeClass("fancytree-drop-hover");
}
if(hitMode === "after"){
$target.addClass("fancytree-drop-after");
} else {
$target.removeClass("fancytree-drop-after");
}
if(hitMode === "before"){
$target.addClass("fancytree-drop-before");
} else {
$target.removeClass("fancytree-drop-before");
}
if(accept === true){
if($source){
$source.addClass("fancytree-drop-accept");
}
$target.addClass("fancytree-drop-accept");
helper.addClass("fancytree-drop-accept");
}else{
if($source){
$source.removeClass("fancytree-drop-accept");
}
$target.removeClass("fancytree-drop-accept");
helper.removeClass("fancytree-drop-accept");
}
if(accept === false){
if($source){
$source.addClass("fancytree-drop-reject");
}
$target.addClass("fancytree-drop-reject");
helper.addClass("fancytree-drop-reject");
}else{
if($source){
$source.removeClass("fancytree-drop-reject");
}
$target.removeClass("fancytree-drop-reject");
helper.removeClass("fancytree-drop-reject");
}
},
/*
* Handles drag'n'drop functionality.
*
* A standard jQuery drag-and-drop process may generate these calls:
*
* draggable helper():
* _onDragEvent("helper", sourceNode, null, event, null, null);
* start:
* _onDragEvent("start", sourceNode, null, event, ui, draggable);
* drag:
* _onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable);
* _onDragEvent("over", targetNode, sourceNode, event, ui, draggable);
* _onDragEvent("enter", targetNode, sourceNode, event, ui, draggable);
* stop:
* _onDragEvent("drop", targetNode, sourceNode, event, ui, draggable);
* _onDragEvent("leave", targetNode, sourceNode, event, ui, draggable);
* _onDragEvent("stop", sourceNode, null, event, ui, draggable);
*/
_onDragEvent: function(eventName, node, otherNode, event, ui, draggable) {
if(eventName !== "over"){
this.debug("tree.ext.dnd._onDragEvent(%s, %o, %o) - %o", eventName, node, otherNode, this);
}
var /*$helper, $helperParent,*/ nodeOfs, relPos, relPos2,
enterResponse, hitMode, r,
opts = this.options,
dnd = opts.dnd,
ctx = this._makeHookContext(node, event, {otherNode: otherNode, ui: ui, draggable: draggable}),
res = null,
$nodeTag = $(node.span);
switch (eventName) {
// case "helper":
// // Only event and node argument is available
// $helper = $("<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>")
// .css({zIndex: 3, position: "relative"}) // so it appears above ext-wide selection bar
// .append($nodeTag.find("span.fancytree-title").clone());
// // #345: helper parent is now set using draggable.appendTo
// // $helperParent = dnd.helperParent || $("ul.fancytree-container", node.tree.$div);
// // DT issue 244: helper should be child of scrollParent
// // $helperParent.append($helper);
// // Attach node reference to helper object
// $helper.data("ftSourceNode", node);
// // this.debug("helper=%o", $helper);
// // this.debug("helper.sourceNode=%o", $helper.data("ftSourceNode"));
// res = $helper;
// break;
case "start":
if( node.isStatusNode() ) {
res = false;
} else if(dnd.dragStart) {
res = dnd.dragStart(node, ctx);
}
if(res === false) {
this.debug("tree.dragStart() cancelled");
//draggable._clear();
// NOTE: the return value seems to be ignored (drag is not canceled, when false is returned)
// TODO: call this._cancelDrag()?
ui.helper.trigger("mouseup")
.hide();
} else {
$nodeTag.addClass("fancytree-drag-source");
}
break;
case "enter":
if(dnd.preventRecursiveMoves && node.isDescendantOf(otherNode)){
r = false;
}else{
r = dnd.dragEnter ? dnd.dragEnter(node, ctx) : null;
}
if(!r){
// convert null, undefined, false to false
res = false;
}else if ( $.isArray(r) ) {
// TODO: also accept passing an object of this format directly
res = {
over: ($.inArray("over", r) >= 0),
before: ($.inArray("before", r) >= 0),
after: ($.inArray("after", r) >= 0)
};
}else{
res = {
over: ((r === true) || (r === "over")),
before: ((r === true) || (r === "before")),
after: ((r === true) || (r === "after"))
};
}
ui.helper.data("enterResponse", res);
this.debug("helper.enterResponse: %o", res);
break;
case "over":
enterResponse = ui.helper.data("enterResponse");
hitMode = null;
if(enterResponse === false){
// Don't call dragOver if onEnter returned false.
// break;
} else if(typeof enterResponse === "string") {
// Use hitMode from onEnter if provided.
hitMode = enterResponse;
} else {
// Calculate hitMode from relative cursor position.
nodeOfs = $nodeTag.offset();
relPos = { x: event.pageX - nodeOfs.left,
y: event.pageY - nodeOfs.top };
relPos2 = { x: relPos.x / $nodeTag.width(),
y: relPos.y / $nodeTag.height() };
if( enterResponse.after && relPos2.y > 0.75 ){
hitMode = "after";
} else if(!enterResponse.over && enterResponse.after && relPos2.y > 0.5 ){
hitMode = "after";
} else if(enterResponse.before && relPos2.y <= 0.25) {
hitMode = "before";
} else if(!enterResponse.over && enterResponse.before && relPos2.y <= 0.5) {
hitMode = "before";
} else if(enterResponse.over) {
hitMode = "over";
}
// Prevent no-ops like 'before source node'
// TODO: these are no-ops when moving nodes, but not in copy mode
if( dnd.preventVoidMoves ){
if(node === otherNode){
this.debug(" drop over source node prevented");
hitMode = null;
}else if(hitMode === "before" && otherNode && node === otherNode.getNextSibling()){
this.debug(" drop after source node prevented");
hitMode = null;
}else if(hitMode === "after" && otherNode && node === otherNode.getPrevSibling()){
this.debug(" drop before source node prevented");
hitMode = null;
}else if(hitMode === "over" && otherNode && otherNode.parent === node && otherNode.isLastSibling() ){
this.debug(" drop last child over own parent prevented");
hitMode = null;
}
}
// this.debug("hitMode: %s - %s - %s", hitMode, (node.parent === otherNode), node.isLastSibling());
ui.helper.data("hitMode", hitMode);
}
// Auto-expand node (only when 'over' the node, not 'before', or 'after')
if(hitMode === "over" && dnd.autoExpandMS && node.hasChildren() !== false && !node.expanded) {
node.scheduleAction("expand", dnd.autoExpandMS);
}
if(hitMode && dnd.dragOver){
// TODO: http://code.google.com/p/dynatree/source/detail?r=625
ctx.hitMode = hitMode;
res = dnd.dragOver(node, ctx);
}
// DT issue 332
// this._setDndStatus(otherNode, node, ui.helper, hitMode, res!==false);
this._local._setDndStatus(otherNode, node, ui.helper, hitMode, res!==false && hitMode !== null);
break;
case "drop":
hitMode = ui.helper.data("hitMode");
if(hitMode && dnd.dragDrop){
ctx.hitMode = hitMode;
dnd.dragDrop(node, ctx);
}
break;
case "leave":
// Cancel pending expand request
node.scheduleAction("cancel");
ui.helper.data("enterResponse", null);
ui.helper.data("hitMode", null);
this._local._setDndStatus(otherNode, node, ui.helper, "out", undefined);
if(dnd.dragLeave){
dnd.dragLeave(node, ctx);
}
break;
case "stop":
$nodeTag.removeClass("fancytree-drag-source");
if(dnd.dragStop){
dnd.dragStop(node, ctx);
}
break;
default:
$.error("Unsupported drag event: " + eventName);
}
return res;
},
_cancelDrag: function() {
var dd = $.ui.ddmanager.current;
if(dd){
dd.cancel();
}
}
});
}(jQuery, window, document));

View File

@@ -0,0 +1,346 @@
/*!
* jquery.fancytree.edit.js
*
* Make node titles editable.
* (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.6.0
* @date 2014-11-29T08:33
*/
;(function($, window, document, undefined) {
"use strict";
/*******************************************************************************
* Private functions and variables
*/
var isMac = /Mac/.test(navigator.platform),
escapeHtml = $.ui.fancytree.escapeHtml,
unescapeHtml = $.ui.fancytree.unescapeHtml;
// modifiers = {shift: "shiftKey", ctrl: "ctrlKey", alt: "altKey", meta: "metaKey"},
// specialKeys = {
// 8: "backspace", 9: "tab", 10: "return", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
// 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
// 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del",
// 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
// 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
// 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
// 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 186: ";", 191: "/",
// 220: "\\", 222: "'", 224: "meta"
// },
// shiftNums = {
// "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
// "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
// ".": ">", "/": "?", "\\": "|"
// };
// $.ui.fancytree.isKeydownEvent = function(e, code){
// var i, part, partmap, partlist = code.split("+"), len = parts.length;
// var c = String.fromCharCode(e.which).toLowerCase();
// for( i = 0; i < len; i++ ) {
// }
// alert (parts.unshift());
// alert (parts.unshift());
// alert (parts.unshift());
// };
/**
* [ext-edit] Start inline editing of current node title.
*
* @alias FancytreeNode#editStart
* @requires Fancytree
*/
$.ui.fancytree._FancytreeNodeClass.prototype.editStart = function(){
var $input,
node = this,
tree = this.tree,
local = tree.ext.edit,
instOpts = tree.options.edit,
$title = $(".fancytree-title", node.span),
eventData = {
node: node,
tree: tree,
options: tree.options,
isNew: $(node.span).hasClass("fancytree-edit-new"),
orgTitle: node.title,
input: null,
dirty: false
};
// beforeEdit may want to modify the title before editing
if( instOpts.beforeEdit.call(node, {type: "beforeEdit"}, eventData) === false ) {
return false;
}
$.ui.fancytree.assert(!local.currentNode, "recursive edit");
local.currentNode = this;
local.eventData = eventData;
// Disable standard Fancytree mouse- and key handling
tree.widget._unbind();
// #116: ext-dnd prevents the blur event, so we have to catch outer clicks
$(document).on("mousedown.fancytree-edit", function(event){
if( ! $(event.target).hasClass("fancytree-edit-input") ){
node.editEnd(true, event);
}
});
// Replace node with <input>
$input = $("<input />", {
"class": "fancytree-edit-input",
type: "text",
value: unescapeHtml(eventData.orgTitle)
});
local.eventData.input = $input;
if ( instOpts.adjustWidthOfs != null ) {
$input.width($title.width() + instOpts.adjustWidthOfs);
}
if ( instOpts.inputCss != null ) {
$input.css(instOpts.inputCss);
}
$title.html($input);
// Focus <input> and bind keyboard handler
$input
.focus()
.change(function(event){
$input.addClass("fancytree-edit-dirty");
}).keydown(function(event){
switch( event.which ) {
case $.ui.keyCode.ESCAPE:
node.editEnd(false, event);
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);
};
/**
* [ext-edit] Stop inline editing.
* @param {Boolean} [applyChanges=false] false: cancel edit, true: save (if modified)
* @alias FancytreeNode#editEnd
* @requires jquery.fancytree.edit.js
*/
$.ui.fancytree._FancytreeNodeClass.prototype.editEnd = function(applyChanges, _event){
var newVal,
node = this,
tree = this.tree,
local = tree.ext.edit,
eventData = local.eventData,
instOpts = tree.options.edit,
$title = $(".fancytree-title", node.span),
$input = $title.find("input.fancytree-edit-input");
// eventData.isNew = $(node.span).hasClass("fancytree-edit-new");
if( instOpts.trim ) {
$input.val($.trim($input.val()));
}
newVal = $input.val();
// eventData.dirty = $input.hasClass("fancytree-edit-dirty") || ;
eventData.dirty = ( newVal !== node.title );
// Find out, if saving is required
if( applyChanges === false ) {
// If true/false was passed, honor this (except in rename mode, if unchanged)
eventData.save = false;
} else if( eventData.isNew ) {
// In create mode, we save everyting, except for empty text
eventData.save = (newVal !== "");
} else {
// In rename mode, we save everyting, except for empty or unchanged text
eventData.save = eventData.dirty && (newVal !== "");
}
// Allow to break (keep editor open), modify input, or re-define data.save
if( instOpts.beforeClose.call(node, {type: "beforeClose"}, eventData) === false){
return false;
}
if( eventData.save && instOpts.save.call(node, {type: "save"}, eventData) === false){
return false;
}
$input
.removeClass("fancytree-edit-dirty")
.unbind();
// Unbind outer-click handler
$(document).off(".fancytree-edit");
if( eventData.save ) {
node.setTitle( escapeHtml(newVal) );
// $(node.span).removeClass("fancytree-edit-new");
node.setFocus();
}else{
if( eventData.isNew ) {
node.remove();
node = eventData.node = null;
local.relatedNode.setFocus();
} else {
node.renderTitle();
node.setFocus();
}
}
local.eventData = null;
local.currentNode = null;
local.relatedNode = null;
// Re-enable mouse and keyboard handling
tree.widget._bind();
// Set keyboard focus, even if setFocus() claims 'nothing to do'
$(tree.$container).focus();
eventData.input = null;
instOpts.close.call(node, {type: "close"}, eventData);
return true;
};
// $.ui.fancytree._FancytreeNodeClass.prototype.startEdit = function(){
// this.warn("FancytreeNode.startEdit() is deprecated since 2014-01-04. Use .editStart() instead.");
// return this.editStart.apply(this, arguments);
// };
// $.ui.fancytree._FancytreeNodeClass.prototype.endEdit = function(){
// this.warn("FancytreeNode.endEdit() is deprecated since 2014-01-04. Use .editEnd() instead.");
// return this.editEnd.apply(this, arguments);
// };
/**
* [ext-edit] Create a new child or sibling node and start edit mode.
*
* @param {String} [mode='child'] 'before', 'after', or 'child'
* @param {Object} [init] NodeData (or simple title string)
* @alias FancytreeNode#editCreateNode
* @requires jquery.fancytree.edit.js
*/
$.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode = function(mode, init){
var newNode,
that = this;
mode = mode || "child";
if( init == null ) {
init = { title: "" };
} else if( typeof init === "string" ) {
init = { title: init };
} else {
$.ui.fancytree.assert($.isPlainObject(init));
}
// Make sure node is expanded (and loaded) in 'child' mode
if( mode === "child" && !this.isExpanded() && this.hasChildren() !== false ) {
this.setExpanded().done(function(){
that.editCreateNode(mode, init);
});
return;
}
newNode = this.addNode(init, mode);
newNode.makeVisible();
$(newNode.span).addClass("fancytree-edit-new");
this.tree.ext.edit.relatedNode = this;
newNode.editStart();
};
/**
* [ext-edit] Check if any node in this tree in edit mode.
*
* @returns {FancytreeNode | null}
* @alias Fancytree#isEditing
* @requires jquery.fancytree.edit.js
*/
$.ui.fancytree._FancytreeClass.prototype.isEditing = function(){
return this.ext.edit.currentNode;
};
/**
* [ext-edit] Check if this node is in edit mode.
* @returns {Boolean} true if node is currently beeing edited
* @alias FancytreeNode#isEditing
* @requires jquery.fancytree.edit.js
*/
$.ui.fancytree._FancytreeNodeClass.prototype.isEditing = function(){
return this.tree.ext.edit.currentNode === this;
};
/*******************************************************************************
* Extension code
*/
$.ui.fancytree.registerExtension({
name: "edit",
version: "0.2.0",
// Default options for this extension.
options: {
adjustWidthOfs: 4, // null: don't adjust input size to content
allowEmpty: false, // Prevent empty input
inputCss: {minWidth: "3em"},
triggerCancel: ["esc", "tab", "click"],
// triggerStart: ["f2", "dblclick", "shift+click", "mac+enter"],
triggerStart: ["f2", "shift+click", "mac+enter"],
trim: true, // Trim whitespace before save
// Events:
beforeClose: $.noop, // Return false to prevent cancel/save (data.input is available)
beforeEdit: $.noop, // Return false to prevent edit mode
close: $.noop, // Editor was removed
edit: $.noop, // Editor was opened (available as data.input)
// keypress: $.noop, // Not yet implemented
save: $.noop // Save data.input.val() or return false to keep editor open
},
// Local attributes
currentNode: null,
treeInit: function(ctx){
this._super(ctx);
this.$container.addClass("fancytree-ext-edit");
},
nodeClick: function(ctx) {
if( $.inArray("shift+click", ctx.options.edit.triggerStart) >= 0 ){
if( ctx.originalEvent.shiftKey ){
ctx.node.editStart();
return false;
}
}
return this._super(ctx);
},
nodeDblclick: function(ctx) {
if( $.inArray("dblclick", ctx.options.edit.triggerStart) >= 0 ){
ctx.node.editStart();
return false;
}
return this._super(ctx);
},
nodeKeydown: function(ctx) {
switch( ctx.originalEvent.which ) {
case 113: // [F2]
if( $.inArray("f2", ctx.options.edit.triggerStart) >= 0 ){
ctx.node.editStart();
return false;
}
break;
case $.ui.keyCode.ENTER:
if( $.inArray("mac+enter", ctx.options.edit.triggerStart) >= 0 && isMac ){
ctx.node.editStart();
return false;
}
break;
}
return this._super(ctx);
}
});
}(jQuery, window, document));

View File

@@ -0,0 +1,174 @@
/*!
* jquery.fancytree.filter.js
*
* Remove or highlight tree nodes, based on a filter.
* (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.6.0
* @date 2014-11-29T08:33
*/
;(function($, window, document, undefined) {
"use strict";
/*******************************************************************************
* Private functions and variables
*/
function _escapeRegex(str){
/*jshint regexdash:true */
return (str + "").replace(/([.?*+\^\$\[\]\\(){}|-])/g, "\\$1");
}
$.ui.fancytree._FancytreeClass.prototype._applyFilterImpl = function(filter, branchMode, leavesOnly){
var match, re,
count = 0,
hideMode = this.options.filter.mode === "hide";
// leavesOnly = !branchMode && this.options.filter.leavesOnly;
leavesOnly = !!leavesOnly && !branchMode;
// Default to 'match title substring (not case sensitive)'
if(typeof filter === "string"){
match = _escapeRegex(filter); // make sure a '.' is treated literally
re = new RegExp(".*" + match + ".*", "i");
filter = function(node){
return !!re.exec(node.title);
};
}
this.enableFilter = true;
this.lastFilterArgs = arguments;
this.$div.addClass("fancytree-ext-filter");
if( hideMode ){
this.$div.addClass("fancytree-ext-filter-hide");
} else {
this.$div.addClass("fancytree-ext-filter-dimm");
}
// Reset current filter
this.visit(function(node){
delete node.match;
delete node.subMatch;
});
// Adjust node.hide, .match, .subMatch flags
this.visit(function(node){
if ((!leavesOnly || node.children == null) && filter(node)) {
count++;
node.match = true;
node.visitParents(function(p){
p.subMatch = true;
});
if( branchMode ) {
node.visit(function(p){
p.match = true;
});
return "skip";
}
}
});
// Redraw
this.render();
return count;
};
/**
* [ext-filter] Dimm or hide nodes.
*
* @param {function | string} filter
* @param {boolean} [leavesOnly=false]
* @returns {integer} count
* @alias Fancytree#filterNodes
* @requires jquery.fancytree.filter.js
*/
$.ui.fancytree._FancytreeClass.prototype.filterNodes = function(filter, leavesOnly){
return this._applyFilterImpl(filter, false, leavesOnly);
};
/**
* @deprecated
*/
$.ui.fancytree._FancytreeClass.prototype.applyFilter = function(filter){
this.warn("Fancytree.applyFilter() is deprecated since 2014-05-10. Use .filterNodes() instead.");
return this.filterNodes.apply(this, arguments);
};
/**
* [ext-filter] Dimm or hide whole branches.
*
* @param {function | string} filter
* @returns {integer} count
* @alias Fancytree#filterBranches
* @requires jquery.fancytree.filter.js
*/
$.ui.fancytree._FancytreeClass.prototype.filterBranches = function(filter){
return this._applyFilterImpl(filter, true, null);
};
/**
* [ext-filter] Reset the filter.
*
* @alias Fancytree#clearFilter
* @requires jquery.fancytree.filter.js
*/
$.ui.fancytree._FancytreeClass.prototype.clearFilter = function(){
this.visit(function(node){
delete node.match;
delete node.subMatch;
});
this.enableFilter = false;
this.lastFilterArgs = null;
this.$div.removeClass("fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide");
this.render();
};
/*******************************************************************************
* Extension code
*/
$.ui.fancytree.registerExtension({
name: "filter",
version: "0.3.0",
// Default options for this extension.
options: {
autoApply: true, // re-apply last filter if lazy data is loaded
mode: "dimm"
},
treeInit: function(ctx){
this._super(ctx);
},
nodeLoadChildren: function(ctx, source) {
return this._super(ctx, source).done(function() {
if( ctx.tree.enableFilter && ctx.tree.lastFilterArgs && ctx.options.filter.autoApply ) {
ctx.tree._applyFilterImpl.apply(ctx.tree, ctx.tree.lastFilterArgs);
}
});
},
nodeRenderStatus: function(ctx) {
// Set classes for current status
var res,
node = ctx.node,
tree = ctx.tree,
$span = $(node[tree.statusClassPropName]);
res = this._super(ctx);
// nothing to do, if node was not yet rendered
if( !$span.length || !tree.enableFilter ) {
return res;
}
$span
.toggleClass("fancytree-match", !!node.match)
.toggleClass("fancytree-submatch", !!node.subMatch)
.toggleClass("fancytree-hide", !(node.match || node.subMatch));
return res;
}
});
}(jQuery, window, document));

View File

@@ -0,0 +1,155 @@
/*!
* jquery.fancytree.menu.js
*
* Enable jQuery UI Menu as context menu for tree nodes.
* (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
*
* @see http://api.jqueryui.com/menu/
*
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.6.0
* @date 2014-11-29T08:33
*/
;(function($, window, document, undefined) {
"use strict";
// prevent duplicate loading
// if ( $.ui.fancytree && $.ui.fancytree.version ) {
// $.ui.fancytree.warn("Fancytree: duplicate include");
// return;
// }
$.ui.fancytree.registerExtension({
name: "menu",
version: "0.0.1",
// Default options for this extension.
options: {
enable: true,
selector: null, //
position: {}, //
// Events:
create: $.noop, //
beforeOpen: $.noop, //
open: $.noop, //
focus: $.noop, //
select: $.noop, //
close: $.noop //
},
// Override virtual methods for this extension.
// `this` : is this extension object
// `this._base` : the Fancytree instance
// `this._super`: the virtual function that was overridden (member of prev. extension or Fancytree)
treeInit: function(ctx){
var opts = ctx.options,
tree = ctx.tree;
this._super(ctx);
// Prepare an object that will be passed with menu events
tree.ext.menu.data = {
tree: tree,
node: null,
$menu: null,
menuId: null
};
// tree.$container[0].oncontextmenu = function() {return false;};
// Replace the standard browser context menu with out own
tree.$container.delegate("span.fancytree-node", "contextmenu", function(event) {
var node = $.ui.fancytree.getNode(event),
ctx = {node: node, tree: node.tree, originalEvent: event, options: tree.options};
tree.ext.menu._openMenu(ctx);
return false;
});
// Use jquery.ui.menu
$(opts.menu.selector).menu({
create: function(event, ui){
tree.ext.menu.data.$menu = $(this).menu("widget");
var data = $.extend({}, tree.ext.menu.data);
opts.menu.create.call(tree, event, data);
},
focus: function(event, ui){
var data = $.extend({}, tree.ext.menu.data, {
menuItem: ui.item,
menuId: ui.item.find(">a").attr("href")
});
opts.menu.focus.call(tree, event, data);
},
select: function(event, ui){
var data = $.extend({}, tree.ext.menu.data, {
menuItem: ui.item,
menuId: ui.item.find(">a").attr("href")
});
if( opts.menu.select.call(tree, event, data) !== false){
tree.ext.menu._closeMenu(ctx);
}
}
}).hide();
},
treeDestroy: function(ctx){
this._super(ctx);
},
_openMenu: function(ctx){
var data,
tree = ctx.tree,
opts = ctx.options,
$menu = $(opts.menu.selector);
tree.ext.menu.data.node = ctx.node;
data = $.extend({}, tree.ext.menu.data);
if( opts.menu.beforeOpen.call(tree, ctx.originalEvent, data) === false){
return;
}
$(document).bind("keydown.fancytree", function(event){
if( event.which === $.ui.keyCode.ESCAPE ){
tree.ext.menu._closeMenu(ctx);
}
}).bind("mousedown.fancytree", function(event){
// Close menu when clicked outside menu
if( $(event.target).closest(".ui-menu-item").length === 0 ){
tree.ext.menu._closeMenu(ctx);
}
});
// $menu.position($.extend({my: "left top", at: "left bottom", of: event}, opts.menu.position));
$menu
.css("position", "absolute")
.show()
.position({my: "left top", at: "right top", of: ctx.originalEvent, collision: "fit"})
.focus();
opts.menu.open.call(tree, ctx.originalEvent, data);
},
_closeMenu: function(ctx){
var $menu,
tree = ctx.tree,
opts = ctx.options,
data = $.extend({}, tree.ext.menu.data);
if( opts.menu.close.call(tree, ctx.originalEvent, data) === false){
return;
}
$menu = $(opts.menu.selector);
$(document).unbind("keydown.fancytree, mousedown.fancytree");
$menu.hide();
tree.ext.menu.data.node = null;
}
// ,
// nodeClick: function(ctx) {
// var event = ctx.originalEvent;
// if(event.which === 2 || (event.which === 1 && event.ctrlKey)){
// event.preventDefault();
// ctx.tree.ext.menu._openMenu(ctx);
// return false;
// }
// this._super(ctx);
// }
});
}(jQuery, window, document));

View File

@@ -0,0 +1,356 @@
/*!
* jquery.fancytree.persist.js
*
* Persist tree status in cookiesRemove or highlight tree nodes, based on a filter.
* (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
*
* @depends: jquery.cookie.js
*
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.6.0
* @date 2014-11-29T08:33
*/
;(function($, window, document, undefined) {
"use strict";
/*******************************************************************************
* Private functions and variables
*/
var _assert = $.ui.fancytree.assert,
ACTIVE = "active",
EXPANDED = "expanded",
FOCUS = "focus",
SELECTED = "selected";
/* Recursively load lazy nodes
* @param {string} mode 'load', 'expand', false
*/
function _loadLazyNodes(tree, local, keyList, mode, dfd) {
var i, key, l, node,
foundOne = false,
deferredList = [],
missingKeyList = [];
keyList = keyList || [];
dfd = dfd || $.Deferred();
for( i=0, l=keyList.length; i<l; i++ ) {
key = keyList[i];
node = tree.getNodeByKey(key);
if( node ) {
if( mode && node.isUndefined() ) {
foundOne = true;
tree.debug("_loadLazyNodes: " + node + " is lazy: loading...");
if( mode === "expand" ) {
deferredList.push(node.setExpanded());
} else {
deferredList.push(node.load());
}
} else {
tree.debug("_loadLazyNodes: " + node + " already loaded.");
node.setExpanded();
}
} else {
missingKeyList.push(key);
tree.debug("_loadLazyNodes: " + node + " was not yet found.");
}
}
$.when.apply($, deferredList).always(function(){
// All lazy-expands have finished
if( foundOne && missingKeyList.length > 0 ) {
// If we read new nodes from server, try to resolve yet-missing keys
_loadLazyNodes(tree, local, missingKeyList, mode, dfd);
} else {
if( missingKeyList.length ) {
tree.warn("_loadLazyNodes: could not load those keys: ", missingKeyList);
for( i=0, l=missingKeyList.length; i<l; i++ ) {
key = keyList[i];
local._appendKey(EXPANDED, keyList[i], false);
}
}
dfd.resolve();
}
});
return dfd;
}
/**
* [ext-persist] Remove persistence cookies of the given type(s).
* Called like
* $("#tree").fancytree("getTree").clearCookies("active expanded focus selected");
*
* @alias Fancytree#clearCookies
* @requires jquery.fancytree.persist.js
*/
$.ui.fancytree._FancytreeClass.prototype.clearCookies = function(types){
var local = this.ext.persist,
prefix = local.cookiePrefix;
types = types || "active expanded focus selected";
if(types.indexOf(ACTIVE) >= 0){
local._data(prefix + ACTIVE, null);
}
if(types.indexOf(EXPANDED) >= 0){
local._data(prefix + EXPANDED, null);
}
if(types.indexOf(FOCUS) >= 0){
local._data(prefix + FOCUS, null);
}
if(types.indexOf(SELECTED) >= 0){
local._data(prefix + SELECTED, null);
}
};
/**
* [ext-persist] Return persistence information from cookies
*
* Called like
* $("#tree").fancytree("getTree").getPersistData();
*
* @alias Fancytree#getPersistData
* @requires jquery.fancytree.persist.js
*/
$.ui.fancytree._FancytreeClass.prototype.getPersistData = function(){
var local = this.ext.persist,
prefix = local.cookiePrefix,
delim = local.cookieDelimiter,
res = {};
res[ACTIVE] = local._data(prefix + ACTIVE);
res[EXPANDED] = (local._data(prefix + EXPANDED) || "").split(delim);
res[SELECTED] = (local._data(prefix + SELECTED) || "").split(delim);
res[FOCUS] = local._data(prefix + FOCUS);
return res;
};
/* *****************************************************************************
* Extension code
*/
$.ui.fancytree.registerExtension({
name: "persist",
version: "0.3.0",
// Default options for this extension.
options: {
cookieDelimiter: "~",
cookiePrefix: undefined, // 'fancytree-<treeId>-' by default
cookie: {
raw: false,
expires: "",
path: "",
domain: "",
secure: false
},
expandLazy: false, // true: recursively expand and load lazy nodes
overrideSource: true, // true: cookie takes precedence over `source` data attributes.
store: "auto", // 'cookie': force cookie, 'local': force localStore, 'session': force sessionStore
types: "active expanded focus selected"
},
/* Generic read/write string data to cookie, sessionStorage or localStorage. */
_data: function(key, value){
var ls = this._local.localStorage; // null, sessionStorage, or localStorage
if( value === undefined ) {
return ls ? ls.getItem(key) : $.cookie(key);
} else if ( value === null ) {
if( ls ) {
ls.removeItem(key);
} else {
$.removeCookie(key);
}
} else {
if( ls ) {
ls.setItem(key, value);
} else {
$.cookie(key, value, this.options.persist.cookie);
}
}
},
/* Append `key` to a cookie. */
_appendKey: function(type, key, flag){
key = "" + key; // #90
var local = this._local,
instOpts = this.options.persist,
delim = instOpts.cookieDelimiter,
cookieName = local.cookiePrefix + type,
data = local._data(cookieName),
keyList = data ? data.split(delim) : [],
idx = $.inArray(key, keyList);
// Remove, even if we add a key, so the key is always the last entry
if(idx >= 0){
keyList.splice(idx, 1);
}
// Append key to cookie
if(flag){
keyList.push(key);
}
local._data(cookieName, keyList.join(delim));
},
treeInit: function(ctx){
var tree = ctx.tree,
opts = ctx.options,
local = this._local,
instOpts = this.options.persist;
// For 'auto' or 'cookie' mode, the cookie plugin must be available
_assert(instOpts.store === "localStore" || $.cookie, "Missing required plugin for 'persist' extension: jquery.cookie.js");
local.cookiePrefix = instOpts.cookiePrefix || ("fancytree-" + tree._id + "-");
local.storeActive = instOpts.types.indexOf(ACTIVE) >= 0;
local.storeExpanded = instOpts.types.indexOf(EXPANDED) >= 0;
local.storeSelected = instOpts.types.indexOf(SELECTED) >= 0;
local.storeFocus = instOpts.types.indexOf(FOCUS) >= 0;
if( instOpts.store === "cookie" || !window.localStorage ) {
local.localStorage = null;
} else {
local.localStorage = (instOpts.store === "local") ? window.localStorage : window.sessionStorage;
}
// Bind init-handler to apply cookie state
tree.$div.bind("fancytreeinit", function(event){
var cookie, dfd, i, keyList, node,
prevFocus = $.cookie(local.cookiePrefix + FOCUS); // record this before node.setActive() overrides it;
// tree.debug("document.cookie:", document.cookie);
cookie = local._data(local.cookiePrefix + EXPANDED);
keyList = cookie && cookie.split(instOpts.cookieDelimiter);
if( local.storeExpanded ) {
// Recursively load nested lazy nodes if expandLazy is 'expand' or 'load'
// Also remove expand-cookies for unmatched nodes
dfd = _loadLazyNodes(tree, local, keyList, instOpts.expandLazy ? "expand" : false , null);
} else {
// nothing to do
dfd = new $.Deferred().resolve();
}
dfd.done(function(){
if(local.storeSelected){
cookie = local._data(local.cookiePrefix + SELECTED);
if(cookie){
keyList = cookie.split(instOpts.cookieDelimiter);
for(i=0; i<keyList.length; i++){
node = tree.getNodeByKey(keyList[i]);
if(node){
if(node.selected === undefined || instOpts.overrideSource && (node.selected === false)){
// node.setSelected();
node.selected = true;
node.renderStatus();
}
}else{
// node is no longer member of the tree: remove from cookie also
local._appendKey(SELECTED, keyList[i], false);
}
}
}
// In selectMode 3 we have to fix the child nodes, since we
// only stored the selected *top* nodes
if( tree.options.selectMode === 3 ){
tree.visit(function(n){
if( n.selected ) {
n.fixSelection3AfterClick();
return "skip";
}
});
}
}
if(local.storeActive){
cookie = local._data(local.cookiePrefix + ACTIVE);
if(cookie && (opts.persist.overrideSource || !tree.activeNode)){
node = tree.getNodeByKey(cookie);
if(node){
node.setActive();
}
}
}
if(local.storeFocus && prevFocus){
node = tree.getNodeByKey(prevFocus);
if(node){
node.setFocus();
}
}
tree._triggerTreeEvent("restore", null, {});
});
});
// Init the tree
return this._super(ctx);
},
nodeSetActive: function(ctx, flag, opts) {
var res,
local = this._local;
flag = (flag !== false);
res = this._super(ctx, flag, opts);
if(local.storeActive){
local._data(local.cookiePrefix + ACTIVE, this.activeNode ? this.activeNode.key : null);
}
return res;
},
nodeSetExpanded: function(ctx, flag, opts) {
var res,
node = ctx.node,
local = this._local;
flag = (flag !== false);
res = this._super(ctx, flag, opts);
if(local.storeExpanded){
local._appendKey(EXPANDED, node.key, flag);
}
return res;
},
nodeSetFocus: function(ctx, flag) {
var res,
local = this._local;
flag = (flag !== false);
res = this._super(ctx, flag);
if(flag && local.storeFocus){
local._data(local.cookiePrefix + FOCUS, this.focusNode ? this.focusNode.key : null);
}
return res;
},
nodeSetSelected: function(ctx, flag) {
var res, selNodes,
tree = ctx.tree,
node = ctx.node,
local = this._local;
flag = (flag !== false);
res = this._super(ctx, flag);
if(local.storeSelected){
if( tree.options.selectMode === 3 ){
// In selectMode 3 we only store the the selected *top* nodes.
// De-selecting a node may also de-select some parents, so we
// calculate the current status again
selNodes = $.map(tree.getSelectedNodes(true), function(n){
return n.key;
});
selNodes = selNodes.join(ctx.options.persist.cookieDelimiter);
local._data(local.cookiePrefix + SELECTED, selNodes);
} else {
local._appendKey(SELECTED, node.key, flag);
}
}
return res;
}
});
}(jQuery, window, document));

View File

@@ -0,0 +1,359 @@
/*!
* jquery.fancytree.table.js
*
* Render tree as table (aka 'treegrid', 'tabletree').
* (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.6.0
* @date 2014-11-29T08:33
*/
;(function($, window, document, undefined) {
"use strict";
/* *****************************************************************************
* Private functions and variables
*/
function _assert(cond, msg){
msg = msg || "";
if(!cond){
$.error("Assertion failed " + msg);
}
}
function insertSiblingAfter(referenceNode, newNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
/* Show/hide all rows that are structural descendants of `parent`. */
function setChildRowVisibility(parent, flag) {
parent.visit(function(node){
var tr = node.tr;
// currentFlag = node.hide ? false : flag; // fix for ext-filter
if(tr){
tr.style.display = (node.hide || !flag) ? "none" : "";
}
if(!node.expanded){
return "skip";
}
});
}
/* Find node that is rendered in previous row. */
function findPrevRowNode(node){
var i, last, prev,
parent = node.parent,
siblings = parent ? parent.children : null;
if(siblings && siblings.length > 1 && siblings[0] !== node){
// use the lowest descendant of the preceeding sibling
i = $.inArray(node, siblings);
prev = siblings[i - 1];
_assert(prev.tr);
// descend to lowest child (with a <tr> tag)
while(prev.children){
last = prev.children[prev.children.length - 1];
if(!last.tr){
break;
}
prev = last;
}
}else{
// if there is no preceding sibling, use the direct parent
prev = parent;
}
return prev;
}
$.ui.fancytree.registerExtension({
name: "table",
version: "0.2.0",
// Default options for this extension.
options: {
checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx)
customStatus: false, // true: generate renderColumns events for status nodes
indentation: 16, // indent every node level by 16px
nodeColumnIdx: 0 // render node expander, icon, and title to this column (default: #0)
},
// Overide virtual methods for this extension.
// `this` : is this extension object
// `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree)
treeInit: function(ctx){
var i, $row, tdRole,
tree = ctx.tree,
$table = tree.widget.element;
$table.addClass("fancytree-container fancytree-ext-table");
tree.tbody = $table.find("> tbody")[0];
tree.columnCount = $("thead >tr >th", $table).length;
$(tree.tbody).empty();
tree.rowFragment = document.createDocumentFragment();
$row = $("<tr />");
tdRole = "";
if(ctx.options.aria){
$row.attr("role", "row");
tdRole = " role='gridcell'";
}
for(i=0; i<tree.columnCount; i++) {
if(ctx.options.table.nodeColumnIdx === i){
$row.append("<td" + tdRole + "><span class='fancytree-node' /></td>");
}else{
$row.append("<td" + tdRole + " />");
}
}
tree.rowFragment.appendChild($row.get(0));
// Make sure that status classes are set on the node's <tr> elements
tree.statusClassPropName = "tr";
tree.ariaPropName = "tr";
this.nodeContainerAttrName = "tr";
this._super(ctx);
// standard Fancytree created a root UL
$(tree.rootNode.ul).remove();
tree.rootNode.ul = null;
tree.$container = $table;
// Add container to the TAB chain
this.$container.attr("tabindex", this.options.tabbable ? "0" : "-1");
if(this.options.aria){
tree.$container
.attr("role", "treegrid")
.attr("aria-readonly", true);
}
},
/* Called by nodeRender to sync node order with tag order.*/
// nodeFixOrder: function(ctx) {
// },
nodeRemoveChildMarkup: function(ctx) {
var node = ctx.node;
// node.debug("nodeRemoveChildMarkup()");
node.visit(function(n){
if(n.tr){
$(n.tr).remove();
n.tr = null;
}
});
},
nodeRemoveMarkup: function(ctx) {
var node = ctx.node;
// node.debug("nodeRemoveMarkup()");
if(node.tr){
$(node.tr).remove();
node.tr = null;
}
this.nodeRemoveChildMarkup(ctx);
},
/* Override standard render. */
nodeRender: function(ctx, force, deep, collapsed, _recursive) {
var children, firstTr, i, l, newRow, prevNode, prevTr, subCtx,
tree = ctx.tree,
node = ctx.node,
opts = ctx.options,
isRootNode = !node.parent;
if( !_recursive ){
ctx.hasCollapsedParents = node.parent && !node.parent.expanded;
}
// $.ui.fancytree.debug("*** nodeRender " + node + ", isRoot=" + isRootNode, "tr=" + node.tr, "hcp=" + ctx.hasCollapsedParents, "parent.tr=" + (node.parent && node.parent.tr));
if( !isRootNode ){
if(!node.tr){
if( ctx.hasCollapsedParents /*&& !node.parent.tr*/ ) {
// #166: we assume that the parent will be (recursively) rendered
// later anyway.
node.debug("nodeRender ignored due to unrendered parent");
return;
}
// Create new <tr> after previous row
newRow = tree.rowFragment.firstChild.cloneNode(true);
prevNode = findPrevRowNode(node);
// $.ui.fancytree.debug("*** nodeRender " + node + ": prev: " + prevNode.key);
_assert(prevNode);
if(collapsed === true && _recursive){
// hide all child rows, so we can use an animation to show it later
newRow.style.display = "none";
}else if(deep && ctx.hasCollapsedParents){
// also hide this row if deep === true but any parent is collapsed
newRow.style.display = "none";
// newRow.style.color = "red";
}
if(!prevNode.tr){
_assert(!prevNode.parent, "prev. row must have a tr, or is system root");
tree.tbody.appendChild(newRow);
}else{
insertSiblingAfter(prevNode.tr, newRow);
}
node.tr = newRow;
if( node.key && opts.generateIds ){
node.tr.id = opts.idPrefix + node.key;
}
node.tr.ftnode = node;
if(opts.aria){
// TODO: why doesn't this work:
// node.li.role = "treeitem";
$(node.tr).attr("aria-labelledby", "ftal_" + node.key);
}
node.span = $("span.fancytree-node", node.tr).get(0);
// Set icon, link, and title (normally this is only required on initial render)
this.nodeRenderTitle(ctx);
// Allow tweaking, binding, after node was created for the first time
// tree._triggerNodeEvent("createNode", ctx);
if ( opts.createNode ){
opts.createNode.call(tree, {type: "createNode"}, ctx);
}
} else {
if( force ) {
// Set icon, link, and title (normally this is only required on initial render)
this.nodeRenderTitle(ctx); // triggers renderColumns()
} else {
// Update element classes according to node state
this.nodeRenderStatus(ctx);
}
}
}
// Allow tweaking after node state was rendered
// tree._triggerNodeEvent("renderNode", ctx);
if ( opts.renderNode ){
opts.renderNode.call(tree, {type: "renderNode"}, ctx);
}
// Visit child nodes
// Add child markup
children = node.children;
if(children && (isRootNode || deep || node.expanded)){
for(i=0, l=children.length; i<l; i++) {
subCtx = $.extend({}, ctx, {node: children[i]});
subCtx.hasCollapsedParents = subCtx.hasCollapsedParents || !node.expanded;
this.nodeRender(subCtx, force, deep, collapsed, true);
}
}
// Make sure, that <tr> order matches node.children order.
if(children && !_recursive){ // we only have to do it once, for the root branch
prevTr = node.tr || null;
firstTr = tree.tbody.firstChild;
// Iterate over all descendants
node.visit(function(n){
if(n.tr){
if(!n.parent.expanded && n.tr.style.display !== "none"){
// fix after a node was dropped over a collapsed
n.tr.style.display = "none";
setChildRowVisibility(n, false);
}
if(n.tr.previousSibling !== prevTr){
node.debug("_fixOrder: mismatch at node: " + n);
var nextTr = prevTr ? prevTr.nextSibling : firstTr;
tree.tbody.insertBefore(n.tr, nextTr);
}
prevTr = n.tr;
}
});
}
// Update element classes according to node state
// if(!isRootNode){
// this.nodeRenderStatus(ctx);
// }
},
nodeRenderTitle: function(ctx, title) {
var $cb,
node = ctx.node,
opts = ctx.options;
this._super(ctx);
// Move checkbox to custom column
if(opts.checkbox && opts.table.checkboxColumnIdx != null ){
$cb = $("span.fancytree-checkbox", node.span).detach();
$(node.tr).find("td:first").html($cb);
}
// Let user code write column content
// ctx.tree._triggerNodeEvent("renderColumns", node);
// Update element classes according to node state
if( ! node.isRoot() ){
this.nodeRenderStatus(ctx);
}
if( !opts.table.customStatus && node.isStatusNode() ) {
// default rendering for status node: leave other cells empty
} else if ( opts.renderColumns ) {
opts.renderColumns.call(ctx.tree, {type: "renderColumns"}, ctx);
}
},
nodeRenderStatus: function(ctx) {
var indent,
node = ctx.node,
opts = ctx.options;
this._super(ctx);
$(node.tr).removeClass("fancytree-node");
// indent
indent = (node.getLevel() - 1) * opts.table.indentation;
$(node.span).css({marginLeft: indent + "px"});
},
/* Expand node, return Deferred.promise. */
nodeSetExpanded: function(ctx, flag, opts) {
var dfd = new $.Deferred(),
subOpts = $.extend({}, opts, {noEvents: true, noAnimation: true});
opts = opts || {};
function _afterExpand(ok) {
flag = (flag !== false);
setChildRowVisibility(ctx.node, flag);
if( ok ) {
if( flag && ctx.options.autoScroll && !opts.noAnimation && ctx.node.hasChildren() ) {
// Scroll down to last child, but keep current node visible
ctx.node.getLastChild().scrollIntoView(true, {topNode: ctx.node}).always(function(){
if( !opts.noEvents ) {
ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
}
dfd.resolveWith(ctx.node);
});
} else {
if( !opts.noEvents ) {
ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
}
dfd.resolveWith(ctx.node);
}
} else {
if( !opts.noEvents ) {
ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx);
}
dfd.rejectWith(ctx.node);
}
}
// Call base-expand with disabled events and animation
this._super(ctx, flag, subOpts).done(function () {
_afterExpand(true);
}).fail(function () {
_afterExpand(false);
});
return dfd.promise();
},
nodeSetStatus: function(ctx, status, message, details) {
if(status === "ok"){
var node = ctx.node,
firstChild = ( node.children ? node.children[0] : null );
if ( firstChild && firstChild.isStatusNode() ) {
$(firstChild.tr).remove();
}
}
this._super(ctx, status, message, details);
},
treeClear: function(ctx) {
this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode));
return this._super(ctx);
}
/*,
treeSetFocus: function(ctx, flag) {
// alert("treeSetFocus" + ctx.tree.$container);
ctx.tree.$container.focus();
$.ui.fancytree.focusTree = ctx.tree;
}*/
});
}(jQuery, window, document));

View File

@@ -0,0 +1,79 @@
/*!
* jquery.fancytree.themeroller.js
*
* Enable jQuery UI ThemeRoller styles.
* (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)
*
* @see http://jqueryui.com/themeroller/
*
* Copyright (c) 2014, Martin Wendt (http://wwWendt.de)
*
* Released under the MIT license
* https://github.com/mar10/fancytree/wiki/LicenseInfo
*
* @version 2.6.0
* @date 2014-11-29T08:33
*/
;(function($, window, document, undefined) {
"use strict";
/*******************************************************************************
* Extension code
*/
$.ui.fancytree.registerExtension({
name: "themeroller",
version: "0.0.1",
// Default options for this extension.
options: {
activeClass: "ui-state-active",
foccusClass: "ui-state-focus",
hoverClass: "ui-state-hover",
selectedClass: "ui-state-highlight"
},
treeInit: function(ctx){
this._super(ctx);
var $el = ctx.widget.element;
if($el[0].nodeName === "TABLE"){
$el.addClass("ui-widget ui-corner-all");
$el.find(">thead tr").addClass("ui-widget-header");
$el.find(">tbody").addClass("ui-widget-conent");
}else{
$el.addClass("ui-widget ui-widget-content ui-corner-all");
}
$el.delegate(".fancytree-node", "mouseenter mouseleave", function(event){
var node = $.ui.fancytree.getNode(event.target),
flag = (event.type === "mouseenter");
node.debug("hover: " + flag);
$(node.span).toggleClass("ui-state-hover ui-corner-all", flag);
});
},
treeDestroy: function(ctx){
this._super(ctx);
ctx.widget.element.removeClass("ui-widget ui-widget-content ui-corner-all");
},
nodeRenderStatus: function(ctx){
var node = ctx.node,
$el = $(node.span);
this._super(ctx);
/*
.ui-state-highlight: Class to be applied to highlighted or selected elements. Applies "highlight" container styles to an element and its child text, links, and icons.
.ui-state-error: Class to be applied to error messaging container elements. Applies "error" container styles to an element and its child text, links, and icons.
.ui-state-error-text: An additional class that applies just the error text color without background. Can be used on form labels for instance. Also applies error icon color to child icons.
.ui-state-default: Class to be applied to clickable button-like elements. Applies "clickable default" container styles to an element and its child text, links, and icons.
.ui-state-hover: Class to be applied on mouseover to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
.ui-state-focus: Class to be applied on keyboard focus to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons.
.ui-state-active: Class to be applied on mousedown to clickable button-like elements. Applies "clickable active" container styles to an element and its child text, links, and icons.
*/
$el.toggleClass("ui-state-active", node.isActive());
$el.toggleClass("ui-state-focus", node.hasFocus());
$el.toggleClass("ui-state-highlight", node.isSelected());
// node.debug("ext-themeroller.nodeRenderStatus: ", node.span.className);
}
});
}(jQuery, window, document));

View File

@@ -0,0 +1,124 @@
/*!
*
* jquery.fancytree.wide.js
* Support for 100% wide selection bars.
* (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.6.0
* @date 2014-11-29T08:33
*/
;(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);
// }
// }
/* Calculate inner width without scrollbar */
function realInnerWidth($el) {
// http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/
// inst.contWidth = parseFloat(this.$container.css("width"), 10);
// 'Client width without scrollbar' - 'padding'
return $el[0].clientWidth - ($el.innerWidth() - parseFloat($el.css("width"), 10));
}
/**
* [ext-wide] Recalculate the width of the selection bar after the tree container
* was resized.<br>
* May be called explicitly on container resize, since there is no resize event
* for DIV tags.
*
* @alias Fancytree#wideUpdate
* @requires jquery.fancytree.wide.js
*/
$.ui.fancytree._FancytreeClass.prototype.wideUpdate = function(){
var inst = this.ext.wide,
prevCw = inst.contWidth,
prevLo = inst.lineOfs;
// http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/
// inst.contWidth = parseFloat(this.$container.css("width"), 10);
inst.contWidth = realInnerWidth(this.$container);
// Each title is precceeded by 2 or 3 icons (16px + 3 margin)
// + 1px title border and 3px title padding
inst.lineOfs = (this.options.checkbox ? 3 : 2) * 19;
if( prevCw !== inst.contWidth || prevLo !== inst.lineOfs ) {
this.debug("wideUpdate: " + inst.contWidth);
this.visit(function(node){
node.tree._callHook("nodeRenderTitle", node);
});
}
};
/*******************************************************************************
* Extension code
*/
$.ui.fancytree.registerExtension({
name: "wide",
version: "0.0.2",
// Default options for this extension.
options: {
autoResize: true, // call wideUpdate() on window.resize events
cheap: false, // true: use static css only
margin: {left: 3, right: 3} // free margins near the selection bar
},
treeCreate: function(ctx){
this.$container.addClass("fancytree-ext-wide");
this._super(ctx);
// http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/
// this._local.contWidth = parseFloat(ctx.tree.$container.css("width"), 10);
this._local.contWidth = realInnerWidth(ctx.tree.$container);
// Every nested UL is indented by 16px
// Each title is precceeded by 2 or 3 icons (16px + 3 margin)
// + 1px title border and 3px title padding
this._local.lineOfs = (ctx.options.checkbox ? 3 : 2) * 19;
this._local.levelOfs = 16;
this._local.titlePadding = 3;
$(window).on("resize" + ctx.widget.eventNamespace, $.ui.fancytree.debounce(200, function(event){
if( ctx.options.wide.autoResize && !ctx.options.wide.cheap ) {
ctx.tree.wideUpdate();
}
}));
},
treeDestroy: function(ctx){
$(window).off("resize" + ctx.widget.eventNamespace);
this._super(ctx);
},
nodeRenderTitle: function(ctx) {
var ofs, res, margin,
instOpts = ctx.options.wide,
inst = this._local,
cw = inst.contWidth,
node = ctx.node;
res = this._super(ctx);
if( !instOpts.cheap ) {
margin = instOpts.margin;
ofs = (node.getLevel() - 1) * inst.levelOfs + inst.lineOfs;
$(node.span).find(".fancytree-title").css({
width: cw - margin.left - margin.right - ofs,
marginLeft: -ofs + margin.left,
paddingLeft: +ofs - margin.left + inst.titlePadding,
paddingRight: inst.titlePadding
});
}
return res;
}
});
}(jQuery, window, document));

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,529 @@
/*!
* Fancytree "win8" skin (highlighting the node span instead of title-only).
*
* DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from
* the LESS templates.
*/
/*******************************************************************************
* Common Styles for Fancytree Skins.
*
* This section is automatically generated from the `skin-common.less` template.
******************************************************************************/
/*------------------------------------------------------------------------------
* Helpers
*----------------------------------------------------------------------------*/
.ui-helper-hidden {
display: none;
}
/*------------------------------------------------------------------------------
* Container and UL / LI
*----------------------------------------------------------------------------*/
ul.fancytree-container {
font-family: tahoma, arial, helvetica;
font-size: 10pt;
white-space: nowrap;
padding: 3px;
margin: 0;
background-color: white;
border: 1px dotted gray;
overflow: auto;
min-height: 0%;
position: relative;
}
ul.fancytree-container ul {
padding: 0 0 0 16px;
margin: 0;
}
ul.fancytree-container li {
list-style-image: none;
list-style-position: outside;
list-style-type: none;
-moz-background-clip: border;
-moz-background-inline-policy: continuous;
-moz-background-origin: padding;
background-attachment: scroll;
background-color: transparent;
background-position: 0px 0px;
background-repeat: repeat-y;
background-image: none;
margin: 0;
padding: 1px 0 0 0;
}
ul.fancytree-container li.fancytree-lastsib {
background-image: none;
}
ul.fancytree-no-connector > li {
background-image: none;
}
.ui-fancytree-disabled ul.fancytree-container {
opacity: 0.5;
background-color: silver;
}
/*------------------------------------------------------------------------------
* Common icon definitions
*----------------------------------------------------------------------------*/
span.fancytree-empty,
span.fancytree-vline,
span.fancytree-expander,
span.fancytree-icon,
span.fancytree-checkbox,
span.fancytree-radio,
span.fancytree-drag-helper-img,
#fancytree-drop-marker {
width: 16px;
height: 16px;
display: inline-block;
vertical-align: top;
background-repeat: no-repeat;
background-position: left;
background-image: url("icons.gif");
background-position: 0px 0px;
}
span.fancytree-icon,
span.fancytree-checkbox,
span.fancytree-radio,
span.fancytree-custom-icon {
margin-top: 1px;
}
/* Used by iconclass option */
span.fancytree-custom-icon {
display: inline-block;
}
/* Used by 'icon' node option: */
img.fancytree-icon {
width: 16px;
height: 16px;
margin-left: 3px;
margin-top: 1px;
vertical-align: top;
border-style: none;
}
/*------------------------------------------------------------------------------
* Expander icon
*
* Note: IE6 doesn't correctly evaluate multiples class names,
* so we create combined class names that can be used in the CSS.
*
* Prefix: fancytree-exp-
* 1st character: 'e': expanded, 'c': collapsed, 'n': no children
* 2nd character (optional): 'd': lazy (Delayed)
* 3rd character (optional): 'l': Last sibling
*----------------------------------------------------------------------------*/
span.fancytree-expander {
cursor: pointer;
}
.fancytree-exp-n span.fancytree-expander,
.fancytree-exp-nl span.fancytree-expander {
background-image: none;
cursor: default;
}
.fancytree-exp-n span.fancytree-expander,
.fancytree-exp-n span.fancytree-expander:hover {
background-position: 0px -64px;
}
.fancytree-exp-nl span.fancytree-expander,
.fancytree-exp-nl span.fancytree-expander:hover {
background-position: -16px -64px;
}
.fancytree-exp-c span.fancytree-expander {
background-position: 0px -80px;
}
.fancytree-exp-c span.fancytree-expander:hover {
background-position: -16px -80px;
}
.fancytree-exp-cl span.fancytree-expander {
background-position: 0px -96px;
}
.fancytree-exp-cl span.fancytree-expander:hover {
background-position: -16px -96px;
}
.fancytree-exp-cd span.fancytree-expander {
background-position: -64px -80px;
}
.fancytree-exp-cd span.fancytree-expander:hover {
background-position: -80px -80px;
}
.fancytree-exp-cdl span.fancytree-expander {
background-position: -64px -96px;
}
.fancytree-exp-cdl span.fancytree-expander:hover {
background-position: -80px -96px;
}
.fancytree-exp-e span.fancytree-expander,
.fancytree-exp-ed span.fancytree-expander {
background-position: -32px -80px;
}
.fancytree-exp-e span.fancytree-expander:hover,
.fancytree-exp-ed span.fancytree-expander:hover {
background-position: -48px -80px;
}
.fancytree-exp-el span.fancytree-expander,
.fancytree-exp-edl span.fancytree-expander {
background-position: -32px -96px;
}
.fancytree-exp-el span.fancytree-expander:hover,
.fancytree-exp-edl span.fancytree-expander:hover {
background-position: -48px -96px;
}
/*------------------------------------------------------------------------------
* Checkbox icon
*----------------------------------------------------------------------------*/
span.fancytree-checkbox {
margin-left: 3px;
background-position: 0px -32px;
}
span.fancytree-checkbox:hover {
background-position: -16px -32px;
}
.fancytree-partsel span.fancytree-checkbox {
background-position: -64px -32px;
}
.fancytree-partsel span.fancytree-checkbox:hover {
background-position: -80px -32px;
}
.fancytree-selected span.fancytree-checkbox {
background-position: -32px -32px;
}
.fancytree-selected span.fancytree-checkbox:hover {
background-position: -48px -32px;
}
.fancytree-unselectable span.fancytree-checkbox,
.fancytree-unselectable span.fancytree-checkbox:hover {
opacity: 0.4;
filter: alpha(opacity=40);
background-position: 0px -32px;
}
/*------------------------------------------------------------------------------
* Radiobutton icon
* This is a customization, that may be activated by overriding the 'checkbox'
* class name as 'fancytree-radio' in the tree options.
*----------------------------------------------------------------------------*/
.fancytree-radio span.fancytree-checkbox {
background-position: 0px -48px;
}
.fancytree-radio span.fancytree-checkbox:hover {
background-position: -16px -48px;
}
.fancytree-radio .fancytree-partsel span.fancytree-checkbox {
background-position: -64px -48px;
}
.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover {
background-position: -80px -48px;
}
.fancytree-radio .fancytree-selected span.fancytree-checkbox {
background-position: -32px -48px;
}
.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover {
background-position: -48px -48px;
}
.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,
.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover {
background-position: 0px -48px;
}
/*------------------------------------------------------------------------------
* Node type icon
* Note: IE6 doesn't correctly evaluate multiples class names,
* so we create combined class names that can be used in the CSS.
*
* Prefix: fancytree-ico-
* 1st character: 'e': expanded, 'c': collapsed
* 2nd character (optional): 'f': folder
*----------------------------------------------------------------------------*/
span.fancytree-icon {
margin-left: 3px;
background-position: 0px 0px;
}
/* Documents */
.fancytree-ico-c span.fancytree-icon:hover {
background-position: -16px 0px;
}
.fancytree-has-children.fancytree-ico-c span.fancytree-icon {
background-position: -32px 0px;
}
.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {
background-position: -48px 0px;
}
.fancytree-ico-e span.fancytree-icon {
background-position: -64px 0px;
}
.fancytree-ico-e span.fancytree-icon:hover {
background-position: -80px 0px;
}
/* Folders */
.fancytree-ico-cf span.fancytree-icon {
background-position: 0px -16px;
}
.fancytree-ico-cf span.fancytree-icon:hover {
background-position: -16px -16px;
}
.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {
background-position: -32px -16px;
}
.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {
background-position: -48px -16px;
}
.fancytree-ico-ef span.fancytree-icon {
background-position: -64px -16px;
}
.fancytree-ico-ef span.fancytree-icon:hover {
background-position: -80px -16px;
}
.fancytree-loading span.fancytree-expander,
.fancytree-loading span.fancytree-expander:hover,
.fancytree-statusnode-wait span.fancytree-icon,
.fancytree-statusnode-wait span.fancytree-icon:hover {
background-image: url('data:image/gif;base64,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');
background-position: 0px 0px;
}
/* Status node icons */
.fancytree-statusnode-error span.fancytree-icon,
.fancytree-statusnode-error span.fancytree-icon:hover {
background-position: 0px -112px;
}
/*------------------------------------------------------------------------------
* Node titles and highlighting
*----------------------------------------------------------------------------*/
span.fancytree-node {
/* See #117 */
display: inherit;
width: 100%;
}
span.fancytree-title {
display: inline-block;
padding-left: 3px;
padding-right: 3px;
color: black;
vertical-align: top;
margin: 0px;
margin-left: 3px;
cursor: pointer;
}
span.fancytree-node.fancytree-error span.fancytree-title {
color: red;
}
/*------------------------------------------------------------------------------
* Drag'n'drop support
*----------------------------------------------------------------------------*/
div.fancytree-drag-helper a {
border: 1px solid gray;
background-color: white;
padding-left: 5px;
padding-right: 5px;
opacity: 0.8;
}
div.fancytree-drag-helper.fancytree-drop-reject {
border-color: red;
}
div.fancytree-drop-accept span.fancytree-drag-helper-img {
background-position: -32px -112px;
}
div.fancytree-drop-reject span.fancytree-drag-helper-img {
background-position: -16px -112px;
}
/*** Drop marker icon *********************************************************/
#fancytree-drop-marker {
width: 32px;
position: absolute;
background-position: 0px -128px;
margin: 0;
}
#fancytree-drop-marker.fancytree-drop-after,
#fancytree-drop-marker.fancytree-drop-before {
width: 64px;
background-position: 0px -144px;
}
#fancytree-drop-marker.fancytree-drop-copy {
background-position: -64px -128px;
}
#fancytree-drop-marker.fancytree-drop-move {
background-position: -32px -128px;
}
/*** Source node while dragging ***********************************************/
span.fancytree-drag-source {
background-color: #e0e0e0;
}
span.fancytree-drag-source span.fancytree.title {
color: gray;
}
/*** Target node while dragging cursor is over it *****************************/
span.fancytree-drop-target.fancytree-drop-accept a {
background-color: #3169C6 !important;
color: white !important;
/* @ IE6 */
text-decoration: none;
}
/*------------------------------------------------------------------------------
* 'table' extension
*----------------------------------------------------------------------------*/
table.fancytree-ext-table {
border-collapse: collapse;
}
table.fancytree-ext-table span.fancytree-node {
display: inline-block;
}
/*------------------------------------------------------------------------------
* 'columnview' extension
*----------------------------------------------------------------------------*/
table.fancytree-ext-columnview tbody tr td {
position: relative;
border: 1px solid gray;
vertical-align: top;
overflow: auto;
}
table.fancytree-ext-columnview tbody tr td > ul {
padding: 0;
}
table.fancytree-ext-columnview tbody tr td > ul li {
list-style-image: none;
list-style-position: outside;
list-style-type: none;
-moz-background-clip: border;
-moz-background-inline-policy: continuous;
-moz-background-origin: padding;
background-attachment: scroll;
background-color: transparent;
background-position: 0px 0px;
background-repeat: repeat-y;
background-image: none;
/* no v-lines */
margin: 0;
padding: 1px 0 0 0;
}
table.fancytree-ext-columnview span.fancytree-node {
position: relative;
/* allow positioning of embedded spans */
display: inline-block;
}
table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {
background-color: #CBE8F6;
}
table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {
position: absolute;
right: 3px;
background-position: 0px -80px;
}
table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {
background-position: -16px -80px;
}
/*------------------------------------------------------------------------------
* 'filter' extension
*----------------------------------------------------------------------------*/
.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
color: silver;
font-weight: lighter;
}
.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {
color: black;
font-weight: normal;
}
.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,
.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {
color: black;
font-weight: bold;
}
.fancytree-ext-filter-hide tr.fancytree-hide,
.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {
display: none;
}
.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
color: silver;
font-weight: lighter;
}
.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,
.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {
color: black;
font-weight: normal;
}
/*------------------------------------------------------------------------------
* 'wide' extension
*----------------------------------------------------------------------------*/
ul.fancytree-ext-wide span.fancytree-node > span {
position: relative;
z-index: 2;
}
ul.fancytree-ext-wide span.fancytree-node span.fancytree-title {
position: relative;
z-index: 1;
width: 100%;
padding-left: 503px;
margin-left: -500px;
}
/*******************************************************************************
* Styles specific to this skin.
*
* This section is automatically generated from the `ui-fancytree.less` template.
******************************************************************************/
/*******************************************************************************
* Node titles
*/
span.fancytree-node {
border: 1px solid transparent;
}
span.fancytree-node:hover {
background-color: #E5F3FB;
border-color: #70C0E7;
}
.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-focused {
border-color: #3399FF;
}
span.fancytree-node.fancytree-active,
span.fancytree-node.fancytree-selected {
background-color: #F7F7F7;
border-color: #DEDEDE;
}
.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-active,
.fancytree-container.fancytree-treefocus span.fancytree-node.fancytree-selected,
span.fancytree-node.fancytree-active:hover,
span.fancytree-node.fancytree-selected:hover {
background-color: #CBE8F6;
border-color: #26A0DA;
}
.fancytree-node.fancytree-selected {
font-style: italic;
}
/*******************************************************************************
* 'table' extension
*/
table.fancytree-ext-table tbody tr td {
border: 1px solid #EDEDED;
}
table.fancytree-ext-table tbody span.fancytree-node,
table.fancytree-ext-table tbody span.fancytree-node:hover {
border: none;
background: none;
}
table.fancytree-ext-table tbody span.fancytree-title:hover {
border: none;
background: inherit;
background: transparent;
background: none;
filter: none;
}
table.fancytree-ext-table tbody tr:hover {
background-color: #E5F3FB;
outline: 1px solid #70C0E7;
}
table.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title {
outline: 1px dotted black;
}
table.fancytree-ext-table tbody tr.fancytree-active:hover,
table.fancytree-ext-table tbody tr.fancytree-selected:hover {
background-color: #CBE8F6;
outline: 1px solid #26A0DA;
}
table.fancytree-ext-table tbody tr.fancytree-active {
background-color: #F7F7F7;
outline: 1px solid #DEDEDE;
}
table.fancytree-ext-table tbody tr.fancytree-selected {
background-color: #F7F7F7;
}
table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active {
background-color: #CBE8F6;
outline: 1px solid #26A0DA;
}
table.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected {
background-color: #CBE8F6;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
[
{"key": "1", "title": "Tier 1 - Single Item", "extraClasses": "custom-class" },
{"key": "2", "title": "Folder 1", "folder": true, "children": [
{"key": "2_1", "title": "Sub-item 1.1", "children": [
{"key": "2_1_1", "title": "Sub-item 2.1.1"},
{"key": "2_1_2", "title": "Sub-item 2.1.2"}
]},
{"key": "2_2", "title": "Sub-item 2.2", "children": [
{"key": "2_2_1", "title": "Sub-item 2.2.1"},
{"key": "2_2_2", "title": "Sub-item 2.2.2"}
]}
]},
]