Using DOM to change styles instead of IDs...

G

Giggle Girl

Hi there,
I have a nav tree similar to the XP Windows Explorer in behavior. It
uses styles to underline a row on mouseover, and change the look of a
row when clicked.

Currently, it is working fine using CSS/Javascript, by calling
functions that underline and highlight by passing in IDs.

The problem is, I do not want to pass in IDs. Currently it has one the
TDs to be changed, but I may need to add one for images (to change the
look of a plus to minus) and many other things. Instead I would like a
way of passing the row index, and having it "walk through the DOM" to
change behavior, picking the correct child nodes to change the
appearance. Can this be done?

It is for an intranet app and only needs to work with IE 6 (and later).

Thanks!
Ann

Here is the current working javascript:

var old_clicked_tree_nav = -1 // initially there is no row
highlighted...

function hover_tree_nav(row_id,bool)
{
if(document.getElementById('td_' + row_id).className !=
'nav_selected')
{
if(bool==1)
document.getElementById('td_' + row_id).className='nav_highlighted'
else
document.getElementById('td_' + row_id).className='nav_normal'
}
}

function click_tree_nav(row_id, do_action)
{
// turn off old highlight
if(old_clicked_tree_nav > -1)
document.getElementById('td_' +
old_clicked_tree_nav).className='nav_normal'
old_clicked_tree_nav = row_id

// make new highlight
document.getElementById('td_' + row_id).className='nav_selected'
}

And here is one snip of the tree:

<tbody>
<tr id="tr_0"><td onclick="click_tree_nav(0, 0)"><span
id="span_0"><table class="tree_nav_interior"><tr><td><img
src="../images/tree_minus.gif" align="absmiddle"></td><td id="td_0"
class="nav_normal" onmouseover="hover_tree_nav(0,1)"
onmouseout="hover_tree_nav(0,0)"><img
src="../images/tree_folder_open.gif" align="absmiddle">Owned
Deals</td></tr></table></span></td></tr>
<!-- daddy --><tr id="tr_1"><td onclick="click_tree_nav(1, 0)"><span
id="span_1"><table class="tree_nav_interior"><tr><td><img
src="../images/tree_spacer.gif"><img src="../images/tree_minus.gif"
align="absmiddle"></td><td id="td_1" class="nav_normal"
onmouseover="hover_tree_nav(1,1)" onmouseout="hover_tree_nav(1,0)"><img
src="../images/tree_folder_open.gif" align="absmiddle">Deal
A</td></tr></table></span></td></tr>
 
M

Martin Honnen

Giggle Girl wrote:

The problem is, I do not want to pass in IDs. Currently it has one the
TDs to be changed, but I may need to add one for images (to change the
look of a plus to minus) and many other things. Instead I would like a
way of passing the row index, and having it "walk through the DOM" to
change behavior, picking the correct child nodes to change the
appearance. Can this be done?
<tr id="tr_0"><td onclick="click_tree_nav(0, 0)">

You can pass in the element the onclick handler is attached to e.g.
<td onclick="click_tree_nav(this);">
then your function
function click_tree_nav (element) {
can walk the DOM tree e.g.
element.parentNode
or
element.nextSibling
or
element.previousSibling
 
G

Giggle Girl

Here is a link to a real example of the tree:

http://c.1asphost.com/giggy/tree01a/main/default.htm

Note, the script to open/close is not working yet, only the "style
changes" (underline and highlight)...

If someone could show me the actual code to change classes using the
DOM I would appreciate. (Thanks Martin, I am trying to develop your
suggestion but I have never coded something like this.)

Also, FYI, it _is_ necessary for me to have a table in each table row
due to the type of visual behavior I want. I am not sure if having a
table in a table makes manipulating the DOM more difficult...

Ann
 
G

Giggle Girl

Say I want to change the class of the interior TD with the id="td=1"
below. How could I use the DOM to target it, if I start by passing in
the element of the the TD containing the table with the TD I am
targetting, like

<td onclick="click_tree_nav(this);">

For this row?

<!-- daddy --><tr id="tr_1"><td onclick="click_tree_nav(1, 0)"><span
id="span_1"><table class="tree_nav_interior"><tr><td><img
src="../images/tree_spacer.gif"><img src="../images/tree_minus.gif"
align="absmiddle"></td><td id="td_1" class="nav_normal"
onmouseover="hover_tree_nav(1,1)" onmouseout="hover_tree_nav(1,0)"><img
src="../images/tree_folder_open.gif" align="absmiddle">Deal
A</td></tr></table></span></td></tr>

And yes, as I said in my last message, I need to keep the
table-in-table and span tags there. In fact, this code is exactly as
it actually must be used, with the exception (hope, hope) of the IDs
(which I _do_ want to remove).

What would the function "click_tree_nav(element)" look like?

Thanks,
Ann
 
M

Martin Honnen

Giggle said:
Say I want to change the class of the interior TD with the id="td=1"
below. How could I use the DOM to target it, if I start by passing in
the element of the the TD containing the table with the TD I am
targetting, like

<td onclick="click_tree_nav(this);">

function click_tree_nav (tableCell) {
var embeddedTable = tableCell.getElementsByTagName('table')[0];
if (embeddedTable && embeddedTable.rows) {
var embeddedCell = embeddedTable.rows[0].cells[1];
embeddedCell.className = 'whatever';
}
}

Depending on whether the contents might change you would need to use
more checks e.g. if you are not sure there is one row with two cells
then you need more checks

function click_tree_nav (tableCell) {
var embeddedTable = tableCell.getElementsByTagName('table')[0];
var embeddedRow, embeddedCell;
if (embeddedTable && embeddedTable.rows &&
(embeddedRow = embeddedTable.rows[0]) &&
(embeddedCell = embeddedRow.cells[1])
{
embeddedCell.className = 'whatever';
}
}
 
G

Giggle Girl

Thank you so much, Martin!

I will try to implement using your code!

I really appreciate your time and effort. :)

Ann
 
R

RobG

Giggle said:
Here is a link to a real example of the tree:

http://c.1asphost.com/giggy/tree01a/main/default.htm

Note, the script to open/close is not working yet, only the "style
changes" (underline and highlight)...

If someone could show me the actual code to change classes using the
DOM I would appreciate. (Thanks Martin, I am trying to develop your
suggestion but I have never coded something like this.)

Also, FYI, it _is_ necessary for me to have a table in each table row
due to the type of visual behavior I want.

Given the demonstration link above, it isn't necessary to use a table, a
list will do the job will a lot less HTML and much simpler navigation. It
will also give you considerably more control over the layout of the
structure using CSS - discuss it in a CSS or HTML group:

news:comp.infosystems.www.authoring.stylesheets
news:comp.infosystems.www.authoring.html

Have a look at some of these:

I am not sure if having a
table in a table makes manipulating the DOM more difficult...

Depending on how you manipulate the DOM, it is very likely. But mostly it
will make maintenance of your structure more complex.
 
G

Giggle Girl

Hey Rob,
thanks for the reply. That example is just a scaled down version of
what the tree has to do. Another thing it has to do is add rows
dynamically.

Here is another question:

Is there a way, using the code below with the event handler in a TD
like this:

onclick="click_tree_nav(this)"

to determine what row you are clicking in the table (called
"tree_nav_1")?

Yes, I know I could pass in a 2nd parameter, but I do not want to. I
want to know how I can determine what row you are at in all of the rows
of the table, which could number more than 200, simply by passing in
the TD object in a particular row, with no other arguments.

Anyone have any ideas?

Thanks,
Ann

Here is a fragment of what the first two rows look like:

<table id="tree_nav_1" class="tree_nav" width="100%" style="display:
inline;">
<tbody>
<tr><td onclick="click_tree_nav(this)"><span id="span_0"><table
class="tree_nav_interior"><tr><td><img src="../images/tree_minus.gif"
align="absmiddle"></td><td class="nav_normal"
onmouseover="hover_tree_nav(this,1)"
onmouseout="hover_tree_nav(this,0)"><img
src="../images/tree_folder_open.gif" align="absmiddle">Owned
Deals</td></tr></table></span></td></tr>
<!-- daddy --><tr><td onclick="click_tree_nav(this)"><span
id="span_1"><table class="tree_nav_interior"><tr><td><img
src="../images/tree_spacer.gif"><img src="../images/tree_minus.gif"
align="absmiddle"></td><td class="nav_normal"
onmouseover="hover_tree_nav(this,1)"
onmouseout="hover_tree_nav(this,0)"><img
src="../images/tree_folder_open.gif" align="absmiddle">Deal
A</td></tr></table></span></td></tr>
 
G

Giggle Girl

Disregard my last request... I was making things too complicated.

I needed to have a way to generate rows dynamically -- like if an Admin
adds a new document to the tree -- and I figured it out.

To see what I have thus far, go to:

http://c.1asphost.com/giggy/tree02h/main/default.htm

Thanks everyone for your help so far... I am getting there.

Ann
 
R

RobG

Giggle Girl said on 24/03/2006 8:14 AM AEST:

Please quote what you are replying to - trim quotes and reply
immediately below the relevant bits.
thanks for the reply. That example is just a scaled down version of
what the tree has to do. Another thing it has to do is add rows
dynamically.

You don't need to use a table. Your use of tables so far has lead you
to create invalid HTML - e.g. putting tables inside spans. You are also
trying to emulate a list by making your tables display:inline.

Use a list.

Here is another question:

Is there a way, using the code below with the event handler in a TD
like this:

onclick="click_tree_nav(this)"

to determine what row you are clicking in the table (called
"tree_nav_1")?

Yes. Climb the DOM tree until you hit a TR:

function getTRParent(el)
{
while (el.parentNode && 'tr' != el.nodeName.toLowerCase()){
el = el.parentNode;
}
return el;
}

If there is no TR parent, a reference to the HTML element will be
returned. A more general approach is in the script below.

Yes, I know I could pass in a 2nd parameter, but I do not want to. I
want to know how I can determine what row you are at in all of the rows
of the table, which could number more than 200, simply by passing in
the TD object in a particular row, with no other arguments.

Table rows have a rowIndex property.

Anyone have any ideas?

Thanks,
Ann

Here is a fragment of what the first two rows look like:

<table id="tree_nav_1" class="tree_nav" width="100%" style="display:
inline;">

Making a table inline is an indicator that it is not the right element
to be using.
<tbody>
<tr><td onclick="click_tree_nav(this)"><span id="span_0"><table

Putting a table inside a span is invalid HTML.

class="tree_nav_interior"><tr><td><img src="../images/tree_minus.gif"
align="absmiddle"></td><td class="nav_normal"

The align attribute is deprecated, use CSS. You should post properly
blocked, valid HTML to make life easier for those who might help you.
Here's a partial implementation of what you are trying to do using a list.

The + and - gifs can be combined with the folder open/closed gifs, and
you can apply styles easily. If scripting is disabled, the menu is open
at all levels and use an 'open' folder image.

To highlight the element last clicked on, add a highlight style that is
added when it's clicked, then remove it when the next one is clicked.
The HTML and CSS are both vastly simpler than yours.


Feature detection omitted for brevity.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html><head><title>Menu play</title>
<meta http-equiv="Content-Type"
content="text/html; charset=ISO-8859-1">
<style type="text/css">
#menu { cursor: pointer; }
..files { list-style-image: url('tree_document.gif'); }
..open, .folder { list-style-image: url('tree_folder_open.gif'); }
..open li {display: normal;}
..closed { list-style-image: url('tree_folder_closed.gif'); }
..closed li li {display: none;}
</style>
<script type="text/javascript">
function getParentByTagName(el, tag)
{
tag = tag.toLowerCase();
while (el.parentNode && tag != el.tagName.toLowerCase()){
el = el.parentNode;
}
if (el.tagName && tag == el.tagName.toLowerCase()){
return el;
}
return null;
}

function initMenu(id)
{
var menu = document.getElementById(id);
var ul, uls = menu.getElementsByTagName('ul');
for (var i=0, len=uls.length; i<len; ++i){
ul = uls;
if (ul.className && /\bfolder\b/.test(ul.className)){
ul.className = ul.className.replace(/\bfolder\b/g,' closed ');
}
}
menu.onclick = doMenuClick;
}

function openClose(el)
{
if (el.className){
if (/\bopen\b/.test(el.className)){
el.className = el.className.replace(/\bopen\b/g,' closed ');
} else {
el.className = el.className.replace(/\bclosed\b/g,' open ');
folder(el);
}
}
}

function doMenuClick(e)
{
var e = e || window.event;
var tgt = e.target || e.srcElement;
var pUL = getParentByTagName(tgt, 'ul');
pUL && openClose(pUL);
}
</script>
</head><body>
<div id="menuList">
<ul class="folder">
<li>head 1 <!-- header -->
<ul class="folder">
<li>sub 1-1
<ul class="files">
<li>file 1-1-1
<li>file 1-1-2
</ul>
<ul class="folder">
<li>folder 1-1-3
<ul class="files">
<li>file 1-1-3-1
<li>file 1-1-3-2
</ul>
</ul>
<ul class="files">
<li>file 1-1-4
<li>file 1-1-5
</ul>
</ul>
<ul class="folder">
<li>sub 2-1
<ul class="files">
<li>file 2-1-1
<li>file 2-1-2
</ul>
</ul>
</ul>

<ul class="folder">
<li>head 2
<ul class="folder">
<li>sub 2-1
</ul>
<ul class="folder">
<li>sub 2-2
</ul>
</ul>
<script type="text/javascript">initMenu('menuList');</script>

</body></html>
 
R

RobG

RobG said on 24/03/2006 11:03 AM AEST:
[...]

A couple of fixes...

<style type="text/css">
#menu { cursor: pointer; }

That should be:

#menuList { cursor: pointer; }

.files { list-style-image: url('tree_document.gif'); }
.open, .folder { list-style-image: url('tree_folder_open.gif'); }
.open li {display: normal;}

And that should be:

.open li {display: list-item;}


[...]
 
G

Giggle Girl

Hey Rob,
tanks so much for your help.

Regarding "Is there a way, using the code below with the event handler
in a TD", you said:
Yes. Climb the DOM tree until you hit a TR:

function getTRParent(el)
{
while (el.parentNode && 'tr' != el.nodeName.toLowerCase()){
el = el.parentNode;
}
return el;
}

I plugged your code in and alerted the result, and it said "[object]".
What I need is the Row number in the Rows Collection of the parent
table. That is, if I click the 13th Row, I am hoping it returns 13.

I need to know this info because the code needs to have the ability to
add rows dynamically, so I can't use IDs on any elements because they
will no longer apply correctly (for other things I have to do) when new
rows are inserted..

If you look at my latest example -- in IE6 -- you will see what I mean.

http://c.1asphost.com/giggy/tree02h/main/default.htm

I am looking at the code you have posted here.... thanks.

Ann
 
M

Martin Honnen

Giggle said:
Yes. Climb the DOM tree until you hit a TR:

function getTRParent(el)
{
while (el.parentNode && 'tr' != el.nodeName.toLowerCase()){
el = el.parentNode;
}
return el;
}


I plugged your code in and alerted the result, and it said "[object]".
What I need is the Row number in the Rows Collection of the parent
table. That is, if I click the 13th Row, I am hoping it returns 13.

That function looks for a tr element object which you can use then as
needed e.g.
var parentRow = getTRParent(el);
var rowIndex = parentRow.rowIndex;
 
G

Giggle Girl

Wow Martin and Rob,
you guys are great. Thanks so much!

One final, small question.

Where can I get resource info on all of the code that you are giving
me?

I have several books on Javascript, some even saying "Advanced", and
they have very little information (and sometimes none at all) on
working with the DOM and the Table Object Model...

The couple that do mention things talk on a high level with little code
showing how to actually do stuff?

Any recommendations for books or online resources that go into detail
-- especially with working examples! -- on this stuff?

Thanks so much for your help,
Ann
 
T

Thomas 'PointedEars' Lahn

Giggle said:
Where can I get resource info on all of the code that you are giving
me?

I have several books on Javascript, some even saying "Advanced", and
they have very little information (and sometimes none at all) on
working with the DOM and the Table Object Model...

What you (and Microsoft) call "Table Object Model" is a part of the
Document Object Model, standardized as interfaces by the W3C:

<URL:http://www.w3.org/DOM/>

Examples are contained in, and reference material is pointed to by the
FAQ <URL:http://jibbering.com/faq/>.


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top