TutorialNodeTypes - mar10/fancytree GitHub Wiki
How to handle nodes by type.
Assume a large tree of products that is organized by type:
Books
+- Little Prince
+- The Hobbit
Computers
+- PC
+- Mac
All book nodes should have a book-icon, while all computer nodes should have a computer icon. All nodes should also have icon tooltips.
This would require to define and transport the same data over and over again:
[
{"title": "Books", "folder": true, "children": [
{"title": "Little Prince", "icon": "ft-ico-book", "iconTooltip": "This is a book.", "price": 1.23},
{"title": "The Hobbit", "icon": "ft-ico-book", "iconTooltip": "This is a book.", "price": 2.34}
]},
{"title": "Computers", "folder": true, "children": [
{"title": "PC", "icon": "ft-ico-computer", "iconTooltip": "This is a computer.", "price": 549.85},
{"title": "Mac", "icon": "ft-ico-computer", "iconTooltip": "This is a computer.", "price": 789.00}
]}
]
Instead, we could use a simple pattern that allows to share data per node type.
Related properties:
- New first-class property
node.type
- New first-class property
tree.types
- All events pass
data.typeInfo
(or{}
if not defined) - TODO: support tree.types[node.type].extraClasses
-
TODO: should
data.typeInfo.icon
be evaluated automatically to set the icon without having to define theicon
callback? -
TODO: should we support hierarchical types?
For example:
books
,books.english
, andbooks.german
. We need a use case for this, but at least '.' should be proposed as delimiter for our pattern.
Some next steps are started in the types2 branch.
Allow to define options by type name:
$("#tree").fancytree({
// `types` is a tree option, that can be used to define shared data per node-type.
// It should contain an object with one key per expected type.
// We can pass it directly as fancytree option like this:
types: {
"book": {icon: "ft-ico-book", iconTooltip: "This is a book"},
"computer": {icon: "ft-ico-computer", iconTooltip: "This is a computer"},
},
source: { url: "/my/web/service"},
icon: function(event, data) {
// data.typeInfo contains tree.types[node.type] (or {} if not found)
// Here we will return the specific icon for that type, or `undefined` if
// not type info is defined (in this case a default icon is displayed).
return data.typeInfo.icon;
},
iconTooltip: function(event, data) {
return data.typeInfo.iconTooltip;
}
});
This pattern works especially well with
dynamic options
like checkbox
, icon
, iconTooltip
, tooltip
, unselectable
,
unselectableIgnore
, unselectableStatus
.
Sometimes it may be more convenient to get the shared types
info from the server.
The source JSON data can be a list of child nodes or an object with additional meta data.
Here we use the latter format to pass type information as well:
{
"children": [
{"title": "Books", "folder": true, "children": [
{"title": "Little Prince", "type": "book", "price": 1.23},
{"title": "The Hobbit", "type": "book", "price": 2.34}
]},
{"title": "Computers", "folder": true, "children": [
{"title": "PC", "type": "computer", "price": 549.85},
{"title": "Mac", "type": "computer", "price": 789.00}
]}
],
"types": {
"book": {"icon": "ft-ico-book", "iconTooltip": "This is a book"},
"computer": {"icon": "ft-ico-computer", "iconTooltip": "This is a computer."}
}
}
Note that sometimes things can even be more simplified by imposing conventions. For example if the icon class names follow a simple rule, we may omit the icon data altogether and derive it from the type:
$("#tree").fancytree({
...
icon: function(event, data) {
if( data.node.type ) {
return "ft-ico-" + data.node.type;
}
},
});