jsTree v.0.9.1
The new version is out and available for download at Google Code.
The big news is that I managed to create a few example pages (@jstree.com). I am working on a fully featured example that will combine all the small example pages that are available now - it should be out in a few days.
Please post any bugs you may encounter and don’t forget to request features.
Speaking of features - since the last official download there are some big changes (check out the changelog).
To point out but a few - full multitree support - both trees must have rules.multitree set to true and the receiving tree’s rules are respected; instance manager - a list of trees is maintained and the currently focused one can be reached by tree_component.focusInst().
Sorry, I’m both a jQuery and a jsTree newbie. I’ve set up jsTree and tried the ‘predefined html’ example. The code for the ‘Second root node’ appears to be missing. Also, my display of the example shows no dots. I tried to add a request for the dots into ‘init’, but I may have the syntax wrong - it did not work (as per below). I’m using IE6.
$(function() {
tree1 = new tree_component();
tree1.init($(”#demo”), { ui: { dots : true } });
});
Any assistance would be greatly appreciated.
Comment by Elliot — November 8, 2008 @ 11:38 pm
Oops, I was a bit premature on my comments about the missing dots. I simply didn’t realize there were two sets of images in two different places within the jsTree files. I simply needed to point the urls in the tree_component.css file to the correct place in my file system.
One other thing - At first, I inadvertently declared the include files in a different order than in the demo. This cause a js error. It might be helpful for the documentation to explicitly state that the order is relevant.
Thanks for your great work on this plugin!
Comment by Elliot — November 9, 2008 @ 8:40 pm
i’m just waiting for v1.0.0 :P
Comment by zhanglei.china — November 10, 2008 @ 9:20 am
A while ago, I wrote up a UX design pattern for trees. It might be helpful to make the user experience even better. Looks good so far.
http://commadot.com/the-ux-of-trees-design-pattern/
Also, you may want to get in touch with the jQuery UI team. I think they need to incorporate a tree component.
Comment by Glen Lipka — November 13, 2008 @ 6:07 pm
I was wondering if it would be possible to use jsTree as a sitemap? Simply I want to be able to click on a node and take someone to the URL in the href….
Am I just missing it in the documentation?
Comment by Eric Polerecky — November 14, 2008 @ 3:10 am
@Eric Polerecky
Just use the onchange callback and navigate to the appropriate URL. The function you assign will receive the DOM node of the clicked node in the tree.
So you could simply do:
...
onchange : function (NODE) {
document.location.href = $(NODE).children("a:eq(0)").attr("href");
},
...
Comment by vakata — November 14, 2008 @ 3:17 am
I haven’t look throughly through the docs and examples but I didn’t see a tree w/ checkboxes. If you’re going to add checkboxes in the near future I suggest writing a 3 state checkbox. That is if partial nodes are checked then the parent node should be partially checked. Most UI trees out there don’t do this properly.
I had to build one modifying the ExtJS tree for my company (admob.com) and it was a huge pain that I wouldn’t wish on anybody.
http://engblog.admob.com/2008/07/19/creating-new-ads/
Comment by Wayne Pan — November 14, 2008 @ 5:17 am
Nice tree. But maybe you should take a look at your examples in IE… The CSS is broken there.
Comment by PHPeter — November 14, 2008 @ 3:06 pm
hey ivan
great work!!!
i have one question about how you echo out your json
from this example
http://jstree.com/jsTree/examples/_data/async.html
i imagine that it can handle any json data, but everything is set as string
would it be possible (haven’t teste yet) but making use of php’s json_encode();
ie
<?
$array = Array(
“attributes”=>Array(
“id”:”1″
),
“state”=>”open”,
“data”=>”data”
)
return json_encode($array);
?>
thoughts?
Comment by yevhen — November 14, 2008 @ 5:44 pm
The plugin looks nice but where’s the source ? The RAR download package format stinks - why not use a conventional format that’s freely available like tar or even zip. (and no, I don’t consider some “trial” RAR version as an acceptable format - won’t load such a thing on our systems).
Comment by miles — November 15, 2008 @ 5:40 am
@Wayne Pan
I believe this is fully achievable using the callback functions - I’ll make an example and get to you (I’ll also publish the example on the examples page).
@PHPeter
Please, tell me how is it broken - I cannot reproduce this. (Maybe send me a screenshot).
@yehven
I’ll test and let you know (but I think it should work OK).
@miles
You can always download the source from the GoogleCode project page (source tab) (or even use the checkout).
Note taken - I’ll publish a zip next time!
Comment by vakata — November 15, 2008 @ 5:09 pm
hi, not sure if this is the best place to ask but i’m having trouble with a json async tree and opening the node. I’ve grabbed the 0.9.2 release thinking i’d use dflt property but i can’t get it to work - any ideas? my test site is at;
http://www.aha-online.org.uk/play/jstree/
i should say that in the example i posted above I want ‘Home’ to be open when it loads.
Comment by Johnb — November 18, 2008 @ 12:41 am
@Johnb
You could do two things:
1) Pass the Home node along with its children. Like this:
[
{
attributes: { id : '100', rel : 'file' },
data: 'Home', icons: "images/icons/globe.png" , state: 'open', rel:'root',
children: [
{
attributes: { id : '116', rel : 'file' },
data: 'someotherpage', icons: "images/icons/file.png" ,state: 'closed'
},
{
attributes: { id : '102', rel : 'file' },
data: 'my test page', icons: "images/icons/file.png" ,state: 'closed'
},
{
attributes: { id : '117', rel : 'file' },
data: 'johnwasehre', icons: "images/icons/file.png" ,state: 'closed'
},
{
attributes: { id : '112', rel : 'file' },
data: 'tmp_standard2', icons: "images/icons/file.png" ,state: 'closed'
},
{
attributes: { id : '114', rel : 'file' },
data: 'tmp_standard3', icons: "images/icons/file.png" ,state: 'closed'
}
]
}
]
2) Or pass an array for settings.dflt - like this:
dflt : ["100", "116"]
I hope this helps!
Comment by vakata — November 18, 2008 @ 10:23 am
Great plugin.
I am using your plugin for Group management with Group members. I am using the onmove callback function to make the changes to the DB.
I now want to implement the copy feature, after setting the drag_copy to ctrl. How can i differentiate between a copy and a move? Is there a specific callback for copy, that will allow me to persist the change the in the db same as onmove?
Thanks in advance.
Comment by Adnan Rashid — November 18, 2008 @ 6:51 pm
This code creates an infinite loop.
Am I instantiating cookies wrong? or is cookies and onclick (wired up as below) currently not compatible?
tree1.init(jQuery(”#testMap”), { cookies: { prefix: “sitemap”, opts: { path: ‘/’} }, callback: { onchange: function(NODE) { document.location.href = jQuery(NODE).children(”a:eq(0)”).attr(”href”); } } });
Comment by Eric Polerecky — November 18, 2008 @ 8:09 pm
I can confirm the inifinite loop. If cookies are used, a node is selected, and during refresh the onchange-callback is triggered, which in this case will reload the page and the stuff gets going.
FireBug bt:
onchange()editable_content (line 420)
select_branch()tree_component.js (line 824)
reselect()tree_component.js (line 683)
refresh()tree_component.js (line 256)
init()
Comment by fw — November 19, 2008 @ 2:10 am
Forgot to mention that the line numbers are from 0.9.1.
Thanx for a nice component :)
Comment by fw — November 19, 2008 @ 2:13 am
@Adnan Rashid
The oncopy method is called instead of the onmove method.
@Eric Polerecky, @fw
Yes, actually I did not think that you would need to reload the whole page and the tree - I imagined that you would do a
$("SOME_NODE").load(jQuery(NODE).children(”a:eq(0)”).attr(”href”));
or an iframe even.
Still, if you want to refresh the whole page - just modify the callback a bit:
onchange: function(NODE) {
if(!first_time) first_time = true;
else document.location.href = jQuery(NODE).children(”a:eq(0)”).attr(”href”);
}
This would skip the first onchange (triggered by the tree loading and reselecting the node found in the cookie).
I haven’t tested this - drop me a note how it went.
Comment by vakata — November 19, 2008 @ 10:35 am
This works great
onchange: function(NODE) {
document.location.href = jQuery(NODE).children(”a:eq(0)”).attr(”href”);
}
But I don’t want all the nodes to go somewhere. For example I want the parents to open the child nodes rather than go to a new page. How do I have the tree continue open in the callback?
thank you
Comment by Arman — November 19, 2008 @ 10:03 pm
scratch that last question. Seems if I qualify the href and do nothing the tree opens if i do nothing in the callback.
thanks!
Comment by Arman — November 19, 2008 @ 10:22 pm
Ok one more try..
The href all seem to work using the callback above, however when i specify an xml_flat type all of the hrefs are changed to ‘#’. The callback still occurs but how do I pass the hrefs now?
Thanks again for your time
Comment by Arman — November 19, 2008 @ 11:28 pm
I’m a newbie to all of this and need to be able to add links to the XML file. Please be specific about how and where to add the code referred to above. Thanks much!
Comment by Barry — November 19, 2008 @ 11:55 pm
Hi:
I´m using v 0.8.1
I use the onchange event of the tree to load different contents on a div.
One of the contents of this div is the name of the node itself.
So, at the end of onrename function i would like to call to onchange to get the new node name (and the other info) in the div.
How can i do it? I try doing:
- tree.onchange(NODE,TREE_OBJ);
- this.onchange(NODE,TREE_OBJ);
- onchange(NODE,TREE_OBJ);
None of this works. How can I do it?
Thank you very much in advance.
Comment by nomen — November 20, 2008 @ 1:43 pm
@Arman
You can pass the attribute (for example “href”, or any other attribute) in the xml “item” node. Then onchange just read:
$(NODE).attr("href");
Note that this time the attribute is attached to the LI DOM node.
@nomen
You could move your logic to an outside function and call that in both callbacks.
Anyway - if you want to trigger the change callback:
tree.settings.callback.onchange.call(null,tree.selected, tree);
NOTE that if you are calling from another callback in the same tree you would be better off with:
TREE_OBJ.settings.callback.onchange.call(null,TREE_OBJ.selected, TREE_OBJ);
Comment by vakata — November 20, 2008 @ 2:24 pm
Thank you Arman!
I finally use tree.settings.callback.onchange.call(null,NODE, TREE_OBJ);and works fine!
Comment by nomen — November 20, 2008 @ 5:13 pm
Perfect vakata!
I was looking for data in the wrong element.
$(NODE).attr(”href”); works great.
Comment by Arman — November 20, 2008 @ 7:47 pm
Hi Vakata:
I´m using version 0.9.1
I have a predefined HTML tree. Tree name is “tree”.
Lets supose this is the tree:
=>root
===>First_child
===>Second_child
We select “First_child”. To delete “First_child”, we make tree.remove();
In this moment the “root” node appears as selected (it is highlighted). But really it is not selected, because if we try to tree.create, tree.rename, tree.remove it will not work. The error says “NO NODE SELECTED”. If we click on the node, we can do it.
Is this a bug or is the correct behaviour?
Asociated with this I think there is another bug.
If we make the deletion of “First_child”, as I say, the “root” node is selected.
If we select “Second_child” the “root” node is not deselected. So, we have two nodes selected.
I try to find where is the bug and solve it but i´m beginner with javascript…anywhere i will work in it…
Comment by nomen — November 21, 2008 @ 5:54 pm
@Nomen
This is indeed a bug. As I have not yet commited to the SVN:
Comment out line #1149
this.selected = false;Thank you for finding it and sorry it was there in the first place ;)
Comment by vakata — November 21, 2008 @ 6:32 pm
Thanks for the great tree component.
I want to drag items from a table and drop them onto jsTree.
Is this feasible? If so, how can I hook into the jsTree event system?
Comment by Alvin Schur — November 21, 2008 @ 9:45 pm
Hi! Thanks for a GREAT component. I’m writing a Wicket integration module for jstree and I was wondering if it would be possible to support drag-n-drop of other objects into the tree?
Typical usecase: Treeview of product categories on the left, and product listing on the right. Select a product and drag it into another product category. I’ll be more than happy to pay you for the time it would take to add this behavior!
Comment by Edvin Syse — November 24, 2008 @ 12:49 am
@Alvin, @Edvin
I am already working on this! I just commited to the repository! Check out jsTree.com.
Comment by vakata — November 24, 2008 @ 1:34 pm
thank you for your help. great app!
Comment by Barry — November 24, 2008 @ 6:41 pm
All works great in Firefox but is blank in IE 7. Any suggestions.
Comment by Barry — November 24, 2008 @ 10:58 pm
@Barry
Tell me which version are you using? Check for a trailing comma in any array/object (a comma after the last element in an array or object). Mail me your config if you can’t find the error, so that I can check it!
Comment by vakata — November 25, 2008 @ 1:53 am
Dragging from a component outside of jsTree to inside jsTree works well from my initial testing. The droppable class is checked against the drag rules.
Thanks for the quick response.
Comment by Alvin Schur — November 28, 2008 @ 8:39 pm
Hello !
I was searching for a javascript tree and found yours ! very interesting :P I’m trying to found a way to keep all the selected nodes in a array or any other js object. I’m using the ‘onchange’ callback to execute code when a user select a node but how can I know if a node is selected ? Is there a NODE.selected property ?
thx,
Franck
Comment by Franck — December 1, 2008 @ 1:09 am
@Franck
You could always the selected_arr property of the tree. Access it by
your-tree-variable-name.selected_arrThis is an array of nodes (jQuery extended).
Comment by vakata — December 1, 2008 @ 3:31 pm
Ok nice I’ll try that :P
BTW, could you make a kind of API documentation ? List all the custom properties, custom functions and events (the events are well described in the documentation section) of your tree ?
All the “Is there a … property to …” would be answered with this documentation.
Comment by Franck — December 1, 2008 @ 7:06 pm
I am using jsTree 0.9.1. Where would I send this file? Do you need more than tree_component.js? Thank you.
Comment by Barry — December 1, 2008 @ 10:08 pm
@Barry
Actually I just need YOUR files - the file where you initialize and create your tree (the place where you call the init() function). I don’t need tree_component.js or any other files from the source.
Mail it to me - either at the address listed in the google code page, or use jstree [at] this domain.
Comment by vakata — December 1, 2008 @ 10:28 pm
The default async_data function breaks backwards compatibility.
jsTree 0.9.1: first AJAX call to server sends id=0
jsTree 0.9.2beta: first AJAX call to server sends id=undefined
Comment by Alvin Schur — December 2, 2008 @ 1:22 am
@Alvin Schur
Thanks, it is fixed now! If the id is undefined (as in the first request) 0 is sent to the server.
Comment by vakata — December 2, 2008 @ 1:52 am
I can configure a tree to
* display a context menu on a right click
* use drag and drop
but I do not know how to get both working together. It appears that the drag and drop is swallowing the right click.
Is there an easy way to get both?
Adding an icon (or other html element) for users to right click on is fine with me.
Comment by Alvin Schur — December 4, 2008 @ 8:48 pm
@Alvin Schur
In which browser does this happen? what do you do in the callback?
As I tested in IE6, IE7 & FF3 and could not reproduce the problem. My test code is:
callback : {
onrgtclk : function (NODE, TREE, EV) { $.log("R"); EV.preventDefault(); EV.stopPropagation(); return false }
}
Comment by vakata — December 5, 2008 @ 12:54 am
I am using Firefox 3.0.1 on Mac 10.5.5
The context menu does work in safari on the Mac.
Comment by Alvin Schur — December 10, 2008 @ 2:16 am
@Alvin Shur
I googled around and this is what I found:
Does it solve your problem?
Comment by vakata — December 10, 2008 @ 6:15 pm
The ‘disable or replace the context menu’ was already checked.
I found the following thread discussing context menus in FF3 on Mac:
http://n2.nabble.com/re:-oncontextmenu-td1091192.html
http://unixpapa.com/js/testmouse.html
On my Mac I can right-click 3 ways:
* Mighty Mouse right-click
* two fingers on track pad + click
* ctrl-click
The ctrl-click does activate the context menu. The other 2 methods do not.
I am not concerned about the context menu issue since there is a work-around and this is a bug in one browser / OS configuration.
Thanks for the help.
Alvin.
Comment by Alvin Schur — December 10, 2008 @ 8:58 pm
When working with multi drag/drop trees, what’s the most efficient way to prevent a duplicate file node in tree1 from being copied into a folder node in tree2?
Was trying to use the beforemove callback, using JQuery find to locate a duplicate child node. This works when preventing duplicate nodes in the originally loaded tree2, but fails when copying a node, then copying the same node:
// Validates drag from doc to topic tree.
function validateMove(sourceNode, destNode, treeObject){
// id of the document being moved
var sourceNodeID = sourceNode.id
// destination topic object
var finalDestNode = destNode;
var finalDestNodeID = ‘#’ + finalDestNode.id;
// Formatted id for JQuery #id selector
sourceNodeID = ‘#’+ sourceNodeID.replace(’_copy’, ”);
// Sometimes docs will be dragged on top of other docs
// Make sure we are working with the topic object, not another document
if($(finalDestNode).attr(”rel”) != ‘folder’){
finalDestNode = finalDestNode.parentNode.parentNode;
finalDestNodeID = ‘#’ + finalDestNode.id;
}
// If the topic already contains this document, do not allow the move
if($(finalDestNodeID).find(sourceNodeID).length){
return false
}
else{
//alert(tree2.settings.data);
document.getElementById(’stuff’).innerHTML = JSONstring.make(tree2.parseJSON(tree2.getJSON()));
return true
}
}
Comment by andy — December 10, 2008 @ 11:23 pm
Hi,
I really like the jstree design…
One limitation I see for now (maybe I am blind?) is that the create() API to add a tree node does not take an “id” so you cannot set an id to the newly create node… How can we do that, so that we can also create sub nodes to a node using the create(…) api…
Thanks
Comment by ludo — December 11, 2008 @ 10:48 pm
@andy
There is
nowno standard method in jsTree to do what you need - your way seems OK, maybe the function can be modified a bit for performance - I’ll investigate further and let you know!@ludo
I am glad you like jsTree and decided to use it.
Currently there is no way of setting the node id (unless you use the oncreate callback - which will fire after you create your node).
I included the id argument in version 0.9.5 which is in a beta phase now - you can use the callback function until it is final! Or just wait a few days - I’ll commit later this evening and maybe release a beta download.
Comment by vakata — December 11, 2008 @ 11:11 pm
Thanks for the feedback. jsTree is definitely a great resource!
Did you mean to say that there is no standard method in jsTree for validating against duplicate nodes under a node? I got all excited when I saw the word “now” in your post :)
My function does OK, except that when I test for the duplicate it doesn’t find it, because it is testing against the tree2 JSON that exists before the drop. I can’t seem to access the version of the tree2 JSON that exists after the drop. It doesn’t seem to replace the old tree2 JSON in memory until both beforemove and oncopy have finished.
I noticed that if I drag/drop a 2nd item into tree2 after the dup is dropped, then output the results of tree2.parseJSON(tree2.getJSON());, the dup is then present.
If I could figure out what I’m doing wrong there, I’d be set. Just can’t get to the updated JSON to test for the dup. May just be a result of my less than stellar javascript/jquery skillz :)
Comment by andy — December 14, 2008 @ 8:35 pm
Hello,
I use xml_flat async data.
I have some problem when I call a empty Node whis no children.
I send an empty list
whis IE (Chrome to, but beta): endless loop
whis Opéra & Safari: 5-10 sec waiting …
whis FF: OK.
Do you have some fix for this ?
Comment by Alain — December 16, 2008 @ 8:47 am
@alain
That indeed was a terrible bug!
I fixed it just now. If you cannot wait for the next official download or download from the SVN - search the source for if(str.length < 10) { and change that “10″ to “15″.
Thank you and sorry for the bug!
P.S - As posted in the notes in the changelog - don’t forget not to pass a parent_id in the XML when using async and xml_flat.
Comment by vakata — December 16, 2008 @ 5:09 pm
@andy
I am not very sure I understood what you need. Here is a suggestion that will prevent prevent nodes with the same ID’s being in the same folder. Just attach it to the oncopy/onmove callbacks:
function(NODE,REF_NODE,TYPE,TREE_OBJ) {
// REF_NODE will hold the jQuery extended copy of the folder where the node is dropped
REF_NODE = (TYPE != "inside") ? $(REF_NODE).parents("li:eq(0)") : $(REF_NODE);
if(REF_NODE.find("#" + NODE.id.replace("_copy","")).size()) $(NODE).remove();
}
If you need no duplication in the whole tree, use this one:
function(NODE,REF_NODE,TYPE,TREE_OBJ) { if(TREE_OBJ.container.find("#" + NODE.id.replace("_copy","")).size()) $(NODE).remove();
}
Comment by vakata — December 16, 2008 @ 5:48 pm
Awesome, thanks! That’s a lot cleaner than the mess I had!!!
That handles one of the two possible scenarios. It covers making sure that a node that already existed in tree2 when tree2 loaded is not duplicated.
What it doesn’t cover is if I drag a node from tree1 into a node in tree2, then immediately drag that same node into the same tree2 node again. Still end up with a duplicate.
One other oddity: I am using an ajax call to post tree changes to the server. After the call is complete, I am doing tree2.refresh() to try and show the saved changes. I am getting a “this.open is undefined”, Firefox says around line 654 of tree_component.js. Any idea what might be causing that?
Comment by Andy — December 16, 2008 @ 11:56 pm
@andy
For scenario 2 - replace the “.find” part with this:
.find("#" + NODE.id.replace("_copy","") + ", #" + NODE.id)
I believe this should work!
As for the refresh bug - I cannot reproduce it - which version are you using?
Comment by vakata — December 17, 2008 @ 12:31 am
Thanks for the quick response!
I’m using v.0.9.1.
One other question (while I have your attention :)) :
When in async mode, is it possible to have a url value with a query string already started? For example, in a Fusebox environment, all URL’s have a “?fuseaction=c.xxxx” value appended to the url.
Comment by Andy — December 17, 2008 @ 1:00 am
@andy
Could you send me your source files (only the ones related to the tree) so that I can reproduce the refresh bug.
As for the url - yes it is possible, but since 0.9.2 (the current version is 0.9.5 beta). But I am doing some final tests on it before releasing it as a featured download (big changes need a lot of testing - theme support, searching, etc).
Back to the URL - since 0.9.2 there is a callback function called async_data (”settings.data.async_data”), which should return a javascript object, that will be sent to the server as parameters (either get or post - this is controlled by “settings.data.method” - default is “get”).
So basically this should work:
...
data : {
...
url : "your-url-here",
async_data : function (NODE) {
return { id : jQuery(NODE).attr("id") || 0, fuseaction : "c.xxxx" }
}
...
}
...
I guess you could either browse the source at the SVN to download the latest, or wait a few days for the new download, or just add what you need in the 0.9.1 source (hardcode the needed parameter).
Comment by vakata — December 17, 2008 @ 1:14 am
Hi Vakata.
I correct and test it(on PC only),
whis FF(3) : OK.
whis IE(7) : OK. but no ‘loading’ message.
whis Safari(3): 5-10 sec waiting, no ‘loading’ message.
whis Opéra(9): endless loop
whis chrome(beta): endless loop, no ‘loading’ message.
In addition for the next version , could you add a parameter for change the ‘default’ image path ?
For marker.gif, dot.git, ect…
Comment by Alain — December 17, 2008 @ 10:45 am
@Alain
Version 0.9.5 (currently beta) adds theme support.
As for the endless loop - I’ll investigate further … the loop problem will be solved by setting a higher value. But I’ll look into the loading message.
Comment by vakata — December 17, 2008 @ 11:19 am