Click here to Skip to main content
15,892,281 members
Articles / Web Development / CSS
Article

JScript Tree List Control with Resizable Columns

Rate me:
Please Sign up or sign in to vote.
4.65/5 (20 votes)
4 Oct 20023 min read 148.1K   2.1K   52   26
A tree list control written using CSS and JScript. Resizable columns!

Sample Image - jstreelistcontrol.gif

Introduction

Note: this code requires internet explorer 5.5 or better.

Following up on a tree list control I made using JScript and ASP (article here), I have created a new one which requires no ASP at all. It is not very fast in adding a whole lot of nodes at once, but expanding and contracting a node is instantaneous. Hovering over text in a row will cause the node for that row to highlight, making it easier to determine which node you are looking at.

Usage:

Create an instance of the tree:

JavaScript
var myTree = new TreeListControl("myUniqueID");
Add the columns:
JavaScript
myTree.addColumn([column name], [width], [alignment]);
Create the tree, specifying the parent element:
JavaScript
myTree.createIn(document.body);
Add Nodes:
JavaScript
myTree.addNode([parent ID], [relative path to icon], [expand branch?], 
                [column text 1], ..., [column text n]);
Delete a Node:
JavaScript
myTree.deleteNode([node ID]);

API

Methods:

TreeListControl ( strID )

Each instance of the tree must have its own unique identifier. This will become the .id property of the element, and is used in id assignment for all the nodes.

TreeListControl
. addColumn ( strTitle[, [intWidth[, strAlign]]] )

Adds a column to the tree. This must be done before the createIn() method of TreeListControl is called.

TreeListControl
. createIn ( objContainerElement )

This builds the main tree object and appends it to the object passed in.

TreeListControl
. addNode ( intParentID, strIconSrc, boolExpandChildren, strColumnText1, ..., strColumnTextN
)

Used to add an entry in the tree. The return value is the integer ID value for that node, which can be used to reference that node later if desired. First supply the parent ID for the node you are adding (0 or null if there is no parent), then a path to the icon to be used, then true/false depending on whether you want this branch to be collapsed or expanded, then the text for each column. If you use the string [[id]] in the text for the columns, it will be replaced with the actual id number that node is assigned. Also, if a node is added, and the specified parent does not exist, it will be queued and added when the parent id is added to the tree.

TreeListControl
. setText ( intNodeID, intColumnIndex, strText )

Changes a node's text in the specified column. If you use the string [[id]] in the text for the columns, it will be replaced with the actual id number that node is assigned.

TreeListControl
. deleteNode ( intNodeID )

Deletes the specified node and all its children.

TreeListControl
. deleteAllChildren ( intNodeID )

Deletes all the children of the specified node, but not the node itself.

TreeListControl
. redrawAllIcons ( )

Forces the tree to redraw all the line connection images that make the tree look correct. This must be called if nodes have been added while the property autoRedrawIcons was set to false.

Properties:

TreeListControl
. autoRedrawIcons

When a new node is added, this determines whether or not to recalculate which line connector images to draw so that the tree looks correct. If you are adding a whole bunch of nodes at once, set this to false, add the nodes, then set it to true. This should speed up the operation.

Example usage

JavaScript
function addone(parentid) {
    var opt = "[ Delete";
    opt += " | Add Child ]"
    var newid = xx.addNode(parentid,
                xx.pathtoicons+"icon_folder.gif", //the icon to use
                true, //expand this node's children?
                s[Math.floor(Math.random()*s.length)], //value for column 1
                s[Math.floor(Math.random()*s.length)], //value for column 2
                s[Math.floor(Math.random()*s.length)], //value for column 3
                s[Math.floor(Math.random()*s.length)], //value for column 4
                opt); //value for column 4
}

xx = new TreeListControl("tlc1"); //create an instance of the control 
                                  // and specify its unique identifier string
xx.autoRedrawIcons = false;       //don't calculate the icons until we've added
                                  // all the nodes (faster this way)
xx.pathtoicons = "treelistcontrol/treeicons/"; //specify the path to the tree 
                                               // icons
xx.addColumn("Things",250) //add some columns (label, width, alignment)
xx.addColumn("More Things",150)
xx.addColumn("Interesting Things",150)
xx.addColumn("Other Things",150)
xx.addColumn("Options",null,"right") //the last column should not have a width

xx.createIn(document.body); // create the tree, passing in the container object
                            //to generate the tree inside

s = new Array("yay","cool","wonderful","great","awesome","fluff",
              "green","beans","mean","machine", "high","balloons",
              "flying","for","fun","great","happy",
              "apples and cherries","bump"); //make some random text values
for(var z=0; z<50; z++){
    addone(Math.floor(Math.random()*z));
}

xx.autoRedrawIcons = true; //remember to set this back to true so that future 
                           //nodes added will be drawn correctly
xx.redrawAllIcons(); //since no icons were drawn, redraw all of them

History

5 Oct 2002 - Updated source code

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Australia Australia
Web application developer, graphic designer, aspiring entrepreneur, snowboarder and electronic music afficianado.


Comments and Discussions

 
QuestionCan't Print if the page more than one page Pin
erros2218-May-09 20:06
erros2218-May-09 20:06 
GeneralWow ! Pin
satsat19-Mar-07 13:55
satsat19-Mar-07 13:55 
Questionresizing problem Pin
Muharrem DEMİR30-Jul-06 4:05
Muharrem DEMİR30-Jul-06 4:05 
Generaltree binding Pin
sunilmskr6-May-05 2:17
sunilmskr6-May-05 2:17 
GeneralTree lIst control rows get invisible problem Pin
sunilraje8-Jan-04 20:57
sunilraje8-Jan-04 20:57 
GeneralWonderful control Pin
rstgp29-Oct-03 22:25
rstgp29-Oct-03 22:25 
GeneralError with createIn(document.body) function Pin
Anonymous29-May-03 13:54
Anonymous29-May-03 13:54 
GeneralRe: Error with createIn(document.body) function Pin
Nathan Ridley29-May-03 19:04
Nathan Ridley29-May-03 19:04 
GeneralWow...and suggestions ...of course...;-) Pin
skyii28-Oct-02 11:02
skyii28-Oct-02 11:02 
GeneralRe: More thoughts (after looking at the code). Pin
skyii29-Oct-02 7:13
skyii29-Oct-02 7:13 
Ok. I couldn't resist peeking at the code even though I have a ton of stuff that needs attention...and it got so engrossing that I stayed up till four or five....

Ok. I understand how you dumped the table layout solution for a series of stacked Divs -- which is the secret for the speed diff. Neat. Never thought of that approach.

Ok. But why the creation of the spans inside the divs -- especially for the secondary columns? I havn't tried yet removing them (I am assuming you had a good reason--that's why I am asking about them) but it is the creation of another DOM element...and since we were both looking for more speed, any type of dieting should be useful...in theory...
So instead of re-discovering the whole wheel again, and finding the reason for the necessity of the span within the div, I thought it would be easier asking you?

Your solution also makes it much easier for a column swap feature -- just cut paste the innerHTML of column 3 to 'tmp', innerHTML of 1 to 3, and tmp to 1 and done. I think.... ? Any ideas on this being not possible? (also have to do the headers of course)...

As for list sorting, I havn't had time to feel at home with your logic enough to think yet of how this could be done lightly...

Also, to inject a TreeInColumn_N var to be able to have small icons to the left of the tree column looks like it won't be hard. That's good news.

As for the optional showing of the tree lines, ...hum. I guess a marginLeft could do the same trick...Not as pretty -- but again, less DOM elements, and certainly less fetching of images to slow down rendering... It's certainly worth a thought, no?

What also impresses me is how much 'air' you have in your code...and it is still 18k! Wow. Trimmed of all excess notes, and shortening varnames to raw essentials...10k? Maybe.... Wink | ;-)

What I do find missing is a secondary class: you have CTree, but not CNode...I don't know if my using this approach was making it slower, (I'll look into this) but it certainly had advantages in terms of attaching whole bunches of non-displaying data.

In the mean-time, the solution appears to add columns with width=0, and using those -- but that is a lot more rendering than necessary...and it will slow it down again. Maybe if there was a style.display=none flag for a hidden column it might be as fast, but I doubt it. I think I still prefer the notion of a CNode object.

But again, I will play with your code to try both and see if there is a notable drag if using eg: 6 hidden columns to store additional info (for example, if looking at a db, you need to keep RowID somewhere..., and maybe the Note column that won't fit in a column, and is best shown in a seperate div below/beside the grid as you move over it).


Again, great work. The 30+% speed increase over a table solution is really the best part Wink | ;-)

I just wanted to check with you again that the only thing you see not working on a IE5.0 is the column resizing...right? Does the cut-off work correctly though, even if not resized, or does this overflow/rolloever and make a mess?

Could you also explain a little your notion of injecting nodes that don't have parents yet? Eh? I saw a NB to that effect in the code, and was wondering under what circumstances such a thing could happen? Since you are always adding a child to a parent -- or the parent grid -- it always has a parent, right? When not?

Also was looking for a means of getting a ChildCount var to be up to date, but not be due to a realtime count of children -- I mentioned the reason in the previous post -- any ideas/tips/ in this direction?







GeneralRe: More thoughts (after looking at the code). Pin
Nathan Ridley29-Oct-02 10:23
Nathan Ridley29-Oct-02 10:23 
GeneralAnother suggestion Pin
ashman_webdev7-Oct-02 19:23
ashman_webdev7-Oct-02 19:23 
GeneralRe: Another suggestion Pin
Nathan Ridley8-Oct-02 0:12
Nathan Ridley8-Oct-02 0:12 
GeneralAwesome work ! Pin
Ranjeet Chakraborty3-Oct-02 10:14
Ranjeet Chakraborty3-Oct-02 10:14 
GeneralWow! Pin
Megan Forbes24-Sep-02 9:13
Megan Forbes24-Sep-02 9:13 
GeneralX-browser Pin
Martrix10124-Sep-02 0:00
Martrix10124-Sep-02 0:00 
GeneralRe: X-browser Pin
Nathan Ridley24-Sep-02 13:09
Nathan Ridley24-Sep-02 13:09 
GeneralRe: X-browser Pin
Anonymous26-Sep-02 9:20
Anonymous26-Sep-02 9:20 
GeneralRe: X-browser Pin
Daniel Turini3-Oct-02 5:34
Daniel Turini3-Oct-02 5:34 
GeneralRe: X-browser Pin
Dave Comer15-Oct-03 6:02
sussDave Comer15-Oct-03 6:02 
GeneralRe: X-browser Pin
Nathan Ridley15-Oct-03 14:05
Nathan Ridley15-Oct-03 14:05 
GeneralExcellent! Pin
Philip Patrick22-Sep-02 22:15
professionalPhilip Patrick22-Sep-02 22:15 
GeneralImpressed Pin
Paul Watson19-Sep-02 21:14
sitebuilderPaul Watson19-Sep-02 21:14 
GeneralRe: Impressed Pin
Nathan Ridley22-Sep-02 17:45
Nathan Ridley22-Sep-02 17:45 
GeneralSuggestion Pin
Eric Lacroix19-Sep-02 17:00
Eric Lacroix19-Sep-02 17:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.