WhatsNew - mar10/fancytree GitHub Wiki
Design goals, new and changed features, compared to Dynatree 1.x.
While DynaTree 1.x seems to work well for many users, bug-fixing and implementation of new features became increasingly difficult without breaking compatibility.
A new project name was chosen, so we can re-think and change the API, attribute names, events, default behavior, etc. - without confusing users that see references to 'DynaTree' on forums or stackoverflow.
Still most concepts and implementations are based on DynaTree, so we start off with release 2.0.
- More robust on (parallel) asynchronous operations (using deferreds/promises)
- Better maintainability using an extension-module pattern
The final design was inspired by jsTree, which features a pretty cool plugin concept:
credits to Ivan Bozhanov! - More flexible initialization (unified
source
option) - More consistent API, using naming conventions and best practice from jQuery UI widgets.
- Table tree support (example)
- Inline editsupport (example)
- The tree now behaves more like a form control, i.e. it is 'tabbable' (example)
- Filter support (example)
- HTML markup changed (not using
<a>
tags anymore) - New skins (Windows 7, 8, [OS X] Lion, bootstrap, ...)
- The tool chain was changed to use node, grunt, and QUnit.
- Using a DVCS (i.e. Git) instead of Subversion
- Moved from Google Code to GitHub.
- The code uses strict mode and passes JS Hint.
- API documentation now based on JSDoc 3 (browse the API docs).
- Test coverage was improved (run unit tests).
- Use LESS for CSS
- Required minimum versions for jQuery have been lifted to jQuery 1.7+ and jQuery UI 1.8.6+
Please help to improve this document: send suggestions or edit this Wiki, to clarify things.
- Most attribute names, event names and method signatures have changed.
// Fancytree 2.x | DynaTree 1.x
// -------------------------+------------------------------
// Requirements
jQuery 3 jQuery 1.4+
jQuery UI 1.12 jQuery UI 1.7+
// Class names
Fancytree DynaTree
FancytreeNode DynaTreeNode
// Attributes
node.expanded node.bExpanded
node.selected node.bSelected
node.children node.childList
node.key node.data.key
node.title node.data.title
node.extraClasses node.data.addClass
node.lazy node.data.isLazy
node.folder node.data.isFolder
...
tree.root tree.tnToot
...
// Note: it is reccomended to use access methods instead:
node.isFolder()
tree.getRootNode()
...
// Methods
tree = $.ui.fancytree.getTree("#tree");
tree = $("#tree").dynatree("getTree");
node.toggleSelected() node.toggleSelect()
node.setSelected() node.select()
node.setActive() node.activate()
...
// Events
beforeExpand(event, data) onQueryExpand(flag, node)
select(event, data) onSelect(flag, node)
...
// Options
source initAjax, init
...
// <ul>/<li> initialization
<li class='expanded'> <li class='expand'>
See the API Reference.
- Some functionality is now implemented as extension and has to be enabled like this:
$("#tree").fancytree({
extensions: ["persist", "dnd"],
[...]
});
See the details.
- New
source
option for generalized initialization:
$("#tree").fancytree({
// source may be Ajax options, a pointer to a <ul> element, a callback, ...
source: {
url: "/getTopLevelNodesAsJson"
},
lazyLoad: function(event, data){
// return a source in 'data.result'
data.result = {
url: "/getChildrenAsJson",
data: {key: data.node.key}
};
},
[...]
});
See the details.
- All events have been renamed according to common jQuery widget style.
Event arguments have been unified to
data
.
activate: function(event, data) {
var node = data.node;
alert("activated #" + node.key);
},
beforeSelect: function(event, data) {
logEvent(event, data, "current state=" + data.node.isSelected());
// return false to prevent default behavior (i.e. selecting or deselecting)
if( data.node.isFolder() ){
return false;
}
},
select: function(event, data) {
logEvent(event, data, "current state=" + data.node.isSelected());
var s = data.tree.getSelectedNodes().join(", ");
$("#echoSelected").text(s);
},
See the details.
-
Most asynchronous methods now return
$.promise
so handling deferred responses is easy:node.setExpanded().done(function(){ alert("expand animation has finished"); });
-
The generated markup has changed (structure and class names).
Check your custom CSS.
More Examples | |
---|---|
Fancytree 2.x | DynaTree 1.x |
node.setActive(true, {noEvents: true}) |
node.activateSilently(); |
$("#tree").fancytree("disable"); | tree.disable(); |
tree.reload().done(function(){ // Root node was reloaded }).fail(function(){ // Reload failed }); | tree.reload(function(status){ // Root node was reloaded }); |
node.addChildren({ title: "n.a.", checkbox: false, icon: false, selected: true, nodeStatus: "empty", key: "_empty" }); | rootNode.addChild({ title: "n.a.", hideCheckbox: true, icon: false, select: true, nodeStatus: "empty", key: "_empty" }); |
$("#tree").fancytree({ extensions: ["clones", "edit"], autoCollapse: true, // Pass an array of nodes (and child nodes) source: [ {title: "Node 1", folder: true, lazy: true, treeMode: "variant", keyType:"root", key: "_famtree_", refKey: "_famtree_", extraClasses: "scioFamilyTree" }, {title: "Node 2", folder: true, lazy: true, treeMode: "struct", keyType: "root", key: "_structtree_", refKey: "_structtree_", extraClasses: "scioStructureTree" } ], init: function(event, data){ }, beforeActivate: function(event, data) { }, click: function(event, data) { }, activate: function(event, data) { var node = data.node, isUserEvent = event.originalEvent && event.originalEvent.type === "click"; if( !node.data.isFolder ){ node.setExpanded(true); } }, deactivate: function(event, data) { }, expand: function(event, data) { }, lazyLoad: function(event, data){ var node = data.node; data.result = $.getJSON("tree/getChildren", { mode: node.data.treeMode, keyType: node.data.keyType, key: node.refKey }); }, render: function(event, data) { var node = data.node; }, }); | $("#tree").dynatree({ fx: { height: "toggle", duration: 200 }, autoCollapse: true, noLink: true, // Pass an array of nodes (and child nodes) children: [ {title: "Node 1", isFolder: true, isLazy: true, mode: "variants", keyType:"root", key: "_famtree_", addClass: "scioFamilyTree" }, {title: "Node 2", isFolder: true, isLazy: true, mode: "struct", keyType: "root", key: "_structtree_", addClass: "scioStructureTree" } ], onQueryActivate: function(dtnode) { return broadcastEvent("queryModelDeactivate") !== false; }, onClick: function(dtnode, event) { }, onActivate: function(dtnode) { }, onDeactivate: function(dtnode) { }, onExpand: function(flag, dtnode) { }, onLazyRead: function(dtnode){ dtnode.appendAjax({ url: "tree/getChildren", data: {mode: dtnode.data.mode, keyType: dtnode.data.keyType, key: dtnode.data.key } }); }, onRender: function(node, span) { }, }); |