View
 

Tree

Page history last edited by Todd Parker 11 mos ago

 

type: widget

release: 0.0

status: in planning

documentation: url || N/A

demo: url || N/A

 


 

1 - Description:

 

The a spindown or tree control is used to selectively hide and show information or nodes in a hierarchical structure. The simplest form is a spindown or disclosure triangle which is used to hide or show a single block of information. A set of these stacked together is referred to as a tree control. More information on UI guidelines:

Apple UI guidelines for disclosure triangles and trees

 

 

There is a tree page on the UI documentation that seems broken and maybe should be removed:

http://docs.jquery.com/UI/Tree

 

jQuery tree plug-ins that are all fairly robust and should be used as a guide to all the features we need to consider:

http://www.jstree.com/

http://abeautifulsite.net/notebook/58

http://news.kg/wp-content/uploads/tree/

http://bassistance.de/jquery-plugins/jquery-plugin-treeview/

 


 

2 - Visual Design:

 

 


 

 

3 - Functional Specifications/Requirements:

 

(Detailed descrition of how the script will be structured: defaults, options, architecture, extensibility, etc.)

 


 

4 - Markup & Style:

 

     4.1 Initial markup examples

 

     (Pre-enhanced HTML markup structure that will be transformed into the final widget. There may be multiple possible HTML markup options per widget: for example, for a slider, radiobuttons, inputs or selects could all be used. )

 

     4.2 Recommended transformed HTML markup

 

     (The HTML markup structure and classes that will be used by the scripts in the enhanced version) 

 

     4.3 Accessibility recommendation

 

    (Detailed recommendations for ARIA, HTML markup, CSS and javascript that will contribute to universal access and full section 508 accessibility for screen readers, mobile devices and any other devices) 

 

     4.4 CSS & Theme

 

    (Description of the CSS classes to be used for all states, how custom theming and Themeroller support will work.) 

 


 

5 - Latest version of plugin:

 

(Link to the latest version in the jQuery UI trunk here)

 


 

6 - Open issues being discussed

 

(Use this area to place things that we're hashing out like featuresand options we're not sure we should include, questions about how this fits into UI and relates to other widgets and utilities, known problems, whether features should be broken across multiple releases, etc.)

 


 

 

 

 

Comments (Show all 42)

profile picture

Ivan Bozhanov said

at 4:35 pm on Mar 30, 2009

I believe jsTree has most of the needed features + some extra features not mentioned here. As of version 0.9.7 (which will be available in a few days) jsTree also has Themeroller support (most classes, icons, etc).
The tree section is not very active - is there some work in progress? If so - how can I help/contribute? If not - how do you evaluate jsTree? What does it lack so that I (and anyone willing of course) can work on it?

profile picture

Scott González said

at 6:07 pm on Mar 30, 2009

@vakata: The first step is fleshing out the docs on this page and getting approval from the jQuery UI team. Only once we have functional specs will we consider a plugin (otherwise we have no way of knowing if the plugin meets our requirements). Feel free to start listing out features/details here to get the conversation started.

profile picture

Titkov Anton said

at 8:12 am on Jul 26, 2009

Hi. Look at that <a href=";http://elsoft.tomsk.ru/index.php?option=com_content&view=article&id=17&Itemid=21">tree widget</a>. I create it for my project. It's alpha version. What are think about it?

profile picture

Ivan Bozhanov said

at 11:53 am on Oct 6, 2009

Just released jstree v.0.9.9 (packaged as jQuery plugin - follows the guidelines). Also updated the documentation and demos. jsTree now has support for various datastores (you can even build your own) and plugins (still basic but a good start I believe). It is a matter of time (or a branch off) to modify jsTree so that it follows the UI guidelines regarding settings.
I guess using draggable/droppable/sortable is a requirement for the final UI product - I guess this is a feature that will take some time to implement in jsTree.
As of 0.9.9 themeroller support is bundled as a plugin and theme (along with a few other themes). There is also a checkbox theme and plugin (three-state checkboxes). Other plugins include metadata, contextmenu, hotkeys (for keyboard navigation).

profile picture

sompylasar said

at 4:36 pm on Oct 6, 2009

I'll try to start using and testing it soon, so new thoughts will be reported.

By the way, speaking on "closed" state I've recently discussed with you @code.google.com: I've found these lines in the docs:
// Properties below are only used for NON-leaf nodes
state: "closed", // or "open"
Please, tell me how to specify that the node possibly has children that are not yet loaded - not using jsTree's default ajax ability?

The other thought I've remembered by now is about .lock method: the lock should only block _user_ interactions (that come from mouse and keyboard) and not API calls. Locking everything made me set up my own lock flag and check it in the event handlers (I must add new nodes while the tree is locked).

P.S. Please, make the code fragments on the jsTree site scrollable horizontally as they aren't fully readable ( overflow-x: auto or scroll ).

profile picture

sompylasar said

at 4:42 pm on Oct 6, 2009

One more question: are there any DOM events triggered on tree container (via .trigger jQuery method)? If not, you should consider reviewing jQuery UI core _trigger function and how the widgets are using it. The function calls the corresponding callback _and_ triggers an event on container element. That would be useful to have a list of bound events (atttached with .bind('jsTreecallbackname', ...)) instead of defining a single function during initialization procedure.

profile picture

sompylasar said

at 4:51 pm on Oct 6, 2009

More thoughts... Mark the functions that are strictly not intended for public use as private by using an underscore ( '_' ) prefix - that is a jQuery UI widget guideline. This will help you to build a jQuery UI widget out of your jQuery plugin faster and will help users not to mix the things up.

profile picture

sompylasar said

at 1:57 pm on Oct 8, 2009

Please, have a look: http://code.google.com/p/jquery-ui-tree/
My tree component that I've created some time ago but hadn't shared it then.

Thanks.

profile picture

Todd Parker said

at 2:07 pm on Oct 8, 2009

@sompylasar This Google Code page doesn't seem to have any code or demos to view. Is there a direct link to a demo and/or documentation?

profile picture

sompylasar said

at 7:42 am on Oct 9, 2009

Source code should be here: http://code.google.com/p/jquery-ui-tree/source/browse/trunk/ui/ui.tree.js
Demo here: http://code.google.com/p/jquery-ui-tree/source/browse/trunk/demos/tree/default.html
I rechecked its visibility to anonymous users - it seems to be OK.
But I couldn't manage to get Google Code return the demo page as HTML page, not as plain text. Any recommendations?

profile picture

Richard D. Worth said

at 7:51 am on Oct 9, 2009

Set the svn prop 'svn:mime-type' to 'text/html' (without the quotes). You'll need to do the same (with correct mime type of course) for any javascript and css files as well

profile picture

sompylasar said

at 8:16 am on Oct 9, 2009

Thanks!
Here is the direct link to the demo: http://jquery-ui-tree.googlecode.com/svn/trunk/demos/tree/default.html
It's not showing all the features but I'm working on that. The tests are now poor and should also be completed.

profile picture

Todd Parker said

at 8:26 am on Oct 9, 2009

This looks like a good start. Why is there a div wrapped around the contents of each li? It would be good to use the CSS framework classes and the theme switcher widget so we can test the theming capability (I see a theme included but I can't tell how it's applied). Could you write up what features this currently has and which you are thinking of including because it's hard to comment on the functionality without knowing what you're aiming for.

profile picture

sompylasar said

at 11:39 am on Oct 9, 2009

@Todd Parker

'div' holds background for tree structure dots ( http://jquery-ui-tree.googlecode.com/svn/trunk/themes/base/images/ui.tree-structure-states.gif ),
'a' holds background for node handle (plus/minus/nothing - http://jquery-ui-tree.googlecode.com/svn/trunk/themes/base/images/ui.tree-handle-states.gif),
'span' optionally holds background for node icon (the icon itself).
The dots and node handle states may be merged into one but that causes to have alot of states that are the combinations. It's easier to work with them separately.

I've started to improve theming just yesterday so now every node only gets 'ui-state-default','ui-state-highlight','ui-state-disabled', and the tree itself gets 'ui-widget' classes.

I haven't documented the API yet but I'm going to. Next, I'm going to test it. You can glance into the code and see public methods passed into 'widget' factory, some of them are already documented in VisualStudio XML style.
In the next comment I'll list all the features.

profile picture

sompylasar said

at 11:41 am on Oct 9, 2009

Methods:
* nodeAttr - Sets or gets node attributes. Predefined attributes: text,rel,href,title,disabledTitle,cache,hascached,remote,collapsed,expanded,enabled,disabled,selected,error.
* nodeContext - Constructs an object that describes node's current state.
* setChildNodes - Creates a collection of nodes and adds/replaces child nodes of the specified node.
* insertNode - Inserts one or more nodes into arbitary position in the tree (available options: prepend,append,after,before).
* removeNode - Removes one or more nodes from the tree.
* getNode - Finds closest tree node element from any child element or the node itself.
* getParentNode - Finds parent node of given node.
* expandNode - Expands one or more nodes. Allows to set how deep to expand (recursively).
* collapseNode - Collapses one or more nodes. Cancels pending node children requests.
* toggleNode - Toggles one or more nodes between expanded and collapsed state.
* selectNode - Selects one or more nodes. Multiselect is controlled by method argument.
* deselectNode - Deselects one or more nodes.
* enableNode - Enables one or more nodes.
* disableNode - Disables one or more nodes.
* hideNode - Hides one or more nodes.
* showNode - Shows one or more nodes.

profile picture

sompylasar said

at 1:22 pm on Oct 9, 2009

Forgot getChildNodes - also implemented.

profile picture

sompylasar said

at 11:41 am on Oct 9, 2009

Events (eventtypes are self-documenting):
* node-before-insert (cancellable)
* node-inserted
* node-before-remove (cancellable)
* node-removed
* node-before-expand (cancellable)
* node-expanded
* node-before-collapse (cancellable)
* node-collapsed
* node-before-load (cancellable)
* node-load-started
* node-load-success
* node-load-error
* node-load-complete
* node-click
* node-before-select (cancellable)
* node-selected
* node-before-deselect (cancellable)
* node-deselected
* node-before-enable (cancellable)
* node-enabled
* node-before-disable (cancellable)
* node-disabled
* node-before-hide (cancellable)
* node-hidden
* node-before-show (cancellable)
* node-shown

Extra features:
* templates for localized strings
* templates for generated ids
* templates for async request parameters

These were already implemented features. Of course, they need some testing, but the code is well-structured so it should not be a problem.

profile picture

sompylasar said

at 12:46 pm on Oct 9, 2009

@Todd Parker

I used to have another element inside 'span' to render icons on it. But recently i've removed it, and now I'm running into trouble applying both an icon background and a themeroller background.
One possible solution is to have 'ui-icon' span inside the 'span' mentioned above. But then I'll have to float it left and that can break up the structure without having the corresponding clear.

Please, give some advice.

profile picture

Todd Parker said

at 12:49 pm on Oct 9, 2009

I think what you have makes sense now that you've explained it. You would need two separate containers so place the icon and texture background images so that's reasonable.

profile picture

sompylasar said

at 1:18 pm on Oct 9, 2009

Is it also reasonable to place icon and text nested, not siblings? That simplifies icon positioning (left center, or right center for dir=rtl when implemented).

profile picture

Jörn Zaefferer said

at 2:11 pm on Oct 9, 2009

Hi sompylasar,

a Tree widget to make it into jQuery UI needs to very lightweight and fully build around progressive enhancement. It can't replicate any of the existing jQuery methods for DOM manipulation. Similar to Buttons and Menus, the Tree widget is responsible for rendering, both on intialization and when the underlying markup changes. The API therefore must provide a method to refresh the full tree (or parts of it, for better performance).

Based on that, manipulating the tree can use standard jQuery methods (eg. appendTo), and whenever a node is inserted, moved or deleted, the affected parts of the Tree need to be rerendered. The same applies to Drag'n'Drop, which also uses jQuery's DOM manipulation methods to insert temporary placeholders while dragging.

Selection is another feature that the Tree won't have, but which can be easily built on top. That could be done by simply inserting checkboxes into the unordered list, or via Selectables. We make sure that both variants (and more when the come up) are possible and provide demos.

I think your code would be a good start for rendering the tree. What do you think about the rest?

profile picture

sompylasar said

at 4:57 pm on Oct 9, 2009

That is a new way of thinking for me, really... But it makes sense. I'm starting to look at UI widgets from another point of view.

The one thing that comes along is that there is a lack of events on jQuery DOM manipulations. For example, we can't track CSS class change to invoke a state change event. The only event we can use is 'remove' (and you can see, I'm using it in the tree to track node removal anyways - both from the API and from jQuery DOM manip).

My project was started exactly to provide extensive events-driven component (I need it at my job). I might be using wrong instrument by choosing jQuery UI... but now I'm unable to change my way to something different.

I agree on Checkbox and Selectable - these may be somehow utilized by the tree. Of course, the same for Draggable and Droppable. But I think the add/remove logic of nodes, quite complex logic of downloading the nodes, tracking of network errors, should be in the tree, or we are loosing events capabilities. I see widget factory also goes towards having both callbacks and events, not just callbacks as most of other jQuery plugins still have.

Lightweight is good for some cases, but other ones need full control, which most of current plugins cannot (or don't want to) provide. Anyways, I can contribute to a lightweight version, though having a sophisticated one for my job.

Comments?

profile picture

sompylasar said

at 5:31 pm on Oct 9, 2009

Generally, I thought jQuery UI is being built ontop of jQuery itself, not nearby. Already existing widgets are for sure catching DOM events and presenting their own events - they use jQuery as a tool to get it cross-browser and convenient. The same should apply to a widget API. Why not redefine 'append' if it gets us onto a new level (e.g. adds some events triggering and JSON/HTML conversion)? The client code is working with data, not its representation as a bunch of HTML elements - that's what the User Interface framework should provide.

Please, don't beat me, that was an expression of my humble opinion.

profile picture

sompylasar said

at 5:52 pm on Oct 9, 2009

I agree we should reuse existing code (as I've already done in my Ribbon widget - thanks to Tabs). But working with a widget means working with it's API that is a higher level than just DOM manip. Inserting a node into a tree is not just appending a 'li' to an 'ul' - it's tracking parent node state and changing it properly, tracking possible rules of what can be added into tree and what cannot, etc.

I also agree that I should have reused $.data and $.metadata instead of writing my own 'nodeAttr' implementation. But that doesn't mean _client code_ should be using $.data itself - it will use 'nodeAttr' API of the tree widget and it should not know how it is implemented internally. The only thing the client code knows that it will get an attribute attached to a tree node, whether the node will be moving along the tree or temporarly be removed during a drag'n'drop operation.

profile picture

Ivan Bozhanov said

at 3:43 pm on Oct 9, 2009

Sompylasar,
Congrats - quite a good start :)
A few hints if I may - try to simplify the structure a bit - now the DOM is quite heavy and not semantic. If full themeroller support is required you'll need even one more DOM element for the icon (sprites).
Have a look at jsTree and borrow the good parts (ul->li->a) not more than that, only the recent version introduces an optional ins element for the icon (so that sprites can be better utilized).
Also try to merge as much images as you can in a sprite. For example - jsTree uses only one image for the whole user experience (+1 more dot image for IE6/7).
I know jsTree is not perfect (now I am rewriting it from scratch for the 1.0 version) , but a lot of ideas can be borrowed from it - most importantly - ideas that have accumulated in a large period of time in the jsTree user group, so a lot of stuff was remade over and over again - just do not go through all the same mistakes - that is all I am saying :).

I have come to believe that jsTree won't be a good start for an official ui widget - it has gone far from very lightweight and offers too much options and serves too many purposes, but at least can be used as a good reference point :)

Kindest regards,
Ivan

p.s. Let me know if I can help somehow

profile picture

sompylasar said

at 5:18 pm on Oct 9, 2009

I've studied your technique and pointed out that it's leading to non-consistent behavior that can be avoided (I think floating last element to crop the dots by shortening the element height is not right).

If merging all the states into one sprite is OK, I can do that. We'll have one element for tree structure dots ( ul ), one for node handle state with corresponding dots glued together ( li ), other for node background ( a ) and the last one for the text and icon ( span ). That looks fine for me.

P.S. In my opinion, the DOM after JS applied doesn't have to be so semantic as the initial markup. Before CSS[n] that will allow us to set multiple backgrounds appears, we have to use non-semantic DOM elements to mimic overlays... And if we decided not to use <img> for icons, we have to use some other element, e.g. span with another classname attached.

Regards.

profile picture

sompylasar said

at 6:16 pm on Oct 9, 2009

By the way, maybe we should try to get the dots as borders of some element? This will give us flexibility of colors and style though having the correct rendering in any sizes and line heights.

profile picture

Ivan Bozhanov said

at 12:24 am on Oct 10, 2009

Experimenting with borders is a good approach (keep in mind IE's dotted border - at least the older versions). You can also use an inline image - a single dot.gif file is quite small - it is one request less for new browsers, and a workaround for IE6/7.

P.S. As for the float - it is only there to enable background images on the tree container, I intend to have a config option for that with some autodetection if not set. So if a solid background is used, there will be no floats. Still this is not a solution for UI themes :)

profile picture

sompylasar said

at 11:35 am on Oct 10, 2009

On using borders, we aren't limited to dotted lines, we could use solid gray as a workaround for dotted black. And we are not limited to black/gray either! We can borrow borders from UI theme and then override other styles to remove background and rounded corners.

Don't remember IE7's behavior but IE8 renders your floats incorrect. A gap in the line appears between some nodes (don't remember exactly where).

profile picture

sompylasar said

at 11:38 am on Oct 10, 2009

Image is a reasonable approach for limited number of predefined themes - each with its own images. If we need to support capabilities of ThemeRoller that defines border colors we should move to using borders, not images.

profile picture

oscarantolinez said

at 5:33 pm on Dec 14, 2009

I initiated the development of an pluggin for tree control over The jQuery UI widget factory. I want you to evaluate what has been done so far. This link for this project: http://www.ontecnologia.info/superhero/jqsuperhero/demos/shtree.html

profile picture

Richard D. Worth said

at 10:08 pm on Dec 14, 2009

(line 4) 404 at this url
(line 5) this is not the right url for this plugin's documentation
(line 12) should mention that this plugin depends on ui.core.js
(line 18) use .disableSelection() from UI Core instead
(lines 19-20, 35, 36, 63-64, 69-70, 77-78, 85-86, 106, 107) curly braces should be used
(line 29) action is not a valid attribute for the A element (see http://www.w3.org/TR/html401/struct/links.html#edef-A). Recommend using a data attribute or metadata in the class attribute and triggering a custom 'select' or 'selected' event when a node is selected. Then the plugin user can handle the node selection based on the metadata on the item.
(line 30) it would be nice if nodes could contain hyperlinks, for navigation. This return false is preventing that.
(line 34) no need to check if event.target is LI since you bound the click event to the LI
(lines 38-39, 47-48, 122-125, 131-134) Code duplication. Suggest refactor
(lines 39, 48, 63, 77, 124, 133) "close" should be "closed" to match "open"
(line 56) $("<ul>"); should be written with a closing tag $("<ul></ul>");
(line 62) $("<li>") should be written with a closing tag $("<li></li>")
(lines 62, 76) I recommend against using lowercase L ( l ) as a variable name as it can too easily be mistaken for a numeral 1 or a capital I or a pipe | depending on the font used.
(lines 62-70, 76-86) $(node) should be cached in a variable

profile picture

Richard D. Worth said

at 10:08 pm on Dec 14, 2009

(lines 61-71, 75-87) almost all this code is duplicated. Suggest refactor
(line 91) _getData() , if defined, should be an override of UI widget's _getData which returns plugin option values based on key. It's rare that's ever even needed. You should pick a different name for this function
(line 108) nodo is undefined if both the previous ifs were false. What if type is not one of 'html' 'json' 'xml'?
(line 115-117) it would be nice if the user of the plugin could handle this error, instead of having an alert hard-coded. Use a custom event.
(lines 138-140) what is the need for this method? Why not just call $('#myTree').find('li').length ?
(line 142) $.widget.prototype.apply(this, arguments); should be $.widget.prototype.destroy.apply(this, arguments);
(line 143) the destroy method for this widget is not implemented. Should return original element as closely as possible back to its pre-init state, such as unbinding events
Why attr("clase") and node.clase instead of attr("class") and node['class']?
All css classnames should be prefixed, such as shtree-selected, shtree-open, shtree-closed
No jQuery UI CSS Framework classes have been used

profile picture

Richard D. Worth said

at 10:09 pm on Dec 14, 2009

If _getData() is getting data, why is it using the POST method? Also, why is async set to false? This will block the browser UI.
The value of using ajax to load a tree is that the whole tree does not need to be loaded up-front. In the examples you've shown, all the trees are loaded completely up-front, and synchrounously. It seems there's no way to get the data for a single collapsed node via ajax when it is expanded.
There is no implemented _setData() common to jQuery UI widgets, meaning option values get changed after initialization with no effect.
There is no implemented enable and disable methods common to jQuery UI widgets, meaning those methods will get called with no effect.
Why are collapseAll and expandAll defined as getters? Any reason these can't be chainable, as they don't return a useful value?
I recommend having options to specify how to find node parents (UL), node children (LI), and node items (A) instead of hard-coding throughout. This will
- make it more readable
- make it more configurable
- ensure you're not removing classes too aggressively from elements you shouldn't, such as self.element.find("a").removeClass("selected")

profile picture

Richard D. Worth said

at 10:10 pm on Dec 14, 2009

There is no visual indicator of keyboard focus
There doesn't seem to be a way to expand/collapse a node using the keyboard, only select one.
Overall, this is not yet a widget, it's a plugin. While I don't want to discourage you from using the jQuery UI widget factory, you haven't used it yet, beyond init and defaults setting init options. No options can be changed after init, there are no custom events, enable and disable are not implemented, destroy does nothing, there are no widget-specific classes, and there are no css framework classes.
A few things I would love to see
- full keyboard support
- separate A elements for expand/collapse and node selection
- full use of jQuery UI CSS Framework classes and icons
- clear plugin-specific classes identifying node parents, node children, node items, node states
- a way to have metadata for each node be persisted from json->html, xml->html
- a way to handle node selection
- dynamic loading of node data via ajax when a collapsed node is expanded

profile picture

oscarantolinez said

at 4:19 pm on Dec 15, 2009

Thanks Richard, I have a long work!!!

profile picture

Ivan Bozhanov said

at 3:11 pm on Mar 29, 2010

Hi all,

I am close to releasing v.1.0 of jstree. It is very close to the jquery UI widget factory, so porting will be easy. v.1.0 uses plugins so it is easy to configure a custom version, also all events are no longer callbacks but implemented using jQuery's event system. The release candidate is not yet available as a separate download - use the SVN to test - http://code.google.com/p/jstree/source/list
The actual RC will be available in a day or two after I have the chance to test everything.
Cheers,
Ivan

profile picture

Ivan Bozhanov said

at 1:09 pm on May 25, 2010

Just released jstree v.1.0rc - I believe a lightweight version can be built by just deleting some plugins. Docs, demos and download - http://www.jstree.com

profile picture

oscarantolinez said

at 4:44 pm on Jul 9, 2010

my respect, is a masterpiece.

profile picture

sergio said

at 1:05 pm on May 27, 2010

great job.

You don't have permission to comment on this page.