Change onclick attribute

G

Giacomo

I work on a page structured like:

<h2> ... </h2>
<div ="div1" class="show"> ... </div>

<h2> ... </h2>
<div id="div2" class="show"> ... </div>

<h2> ... </h2>
<div id="div3" class="show"> ... </div>


---
I obtain the list of h2 by getElementsByTagName and I'd like to
associate to every h2 the onclick attribute in order to call a function
to hide the first div following each of the h2.
I tried:
***
window.onload = function init()
{
var h2 = document.getElementsByTagName('h2');

for ( var i=0; i<h2.length; i++ )
{
div = h2.nextSibling;

while ( div.tagName != 'DIV' )
{
div = div.nextSibling;
}

// these two lines are a trick, but it's absolutely horrible...
h2.name = div.id;
// ...but I can't find a way to set the onclick attribute
h2.onclick=function () {showhideElement(this.name)};
}



function showhideElement(id)
{
var el = document.getElementById(id);

if ( el.className != "hide" )
{
el.className = "hide";
} else {
el.className = "show";
}
}
***



Obviously, there's a CSS:
***
..hide {
display: none;
}
..show {
display: block;
}
***


As I said, the two lines are a trick, but I tries unsuccessfully all
these ways:

//h2.onclick=showhideElement('div.id');
//h2.onclick=showhideElement(div.id);
//h2.addEventListener('click',showhideElement (div.id),false)
//h2.onclick=function () {"showhideElement ('" + divId.id + "');"};


Who can help me? Please, answer me only if you are very sure and you
have tested the solution proposed.


Thanks in advance,
Giacomo.
 
T

tim.n.hunt

Giacomo said:
I obtain the list of h2 by getElementsByTagName and I'd like to
associate to every h2 the onclick attribute in order to call a function
to hide the first div following each of the h2.

Hi Giacomo

You can get the source element of onclick events and other mouse events
inside the function you use to handle the event

Theres some useful info on
http://www.quirksmode.org/js/introevents.html, read the sections after
the heading "Accessing the event".

This way everything can be done in the showHide function, I just copied
over what you had in the init function and it worked on ff + ie.

function init() {
var h2 = document.getElementsByTagName('h2');

for ( var i=0; i<h2.length; i++ ) {
h2.onclick = showHide;
}
}

function showHide( e ) {
el= (e) ? e.target : window.event.srcElement;

el = el.nextSibling;
while ( el.tagName != 'DIV' )
{
el = el.nextSibling;
}

if( el) {
if ( el.className != "hide" )
{
el.className = "hide";
} else {
el.className = "show";
}
}
}

I would change the loop that finds the adjacent div to a do{} while
loop and use the method on the evolts.org page inside the loop to skip
empty empty text nodes
http://lists.evolt.org/archive/Week-of-Mon-20040823/163638.html

Only a personal preference, works either way

Seeya

Tim
 
R

RobG

Giacomo said:
I work on a page structured like:

<h2> ... </h2>
<div ="div1" class="show"> ... </div>

<h2> ... </h2>
<div id="div2" class="show"> ... </div>

<h2> ... </h2>
<div id="div3" class="show"> ... </div>


---
I obtain the list of h2 by getElementsByTagName and I'd like to
associate to every h2 the onclick attribute in order to call a function
to hide the first div following each of the h2.
I tried:
***
window.onload = function init()
{
var h2 = document.getElementsByTagName('h2');

for ( var i=0; i<h2.length; i++ )
{
div = h2.nextSibling;

while ( div.tagName != 'DIV' )
{
div = div.nextSibling;
}

// these two lines are a trick, but it's absolutely horrible...
h2.name = div.id;


Attach the onclick to the h2 element and have the function look for the
next div and toggle it between hidden and visible, e.g.

for ( var i=0; i<h2.length; i++ ) {
h2.onclick = hideDiv;
}

Then hideDiv is something like:

function hideDiv()
{

var div = this.nextSibling;
while (div && (!div.tagName || div.tagName.toLowerCase() != 'div'))
{
div = div.nextSibling;
}

if (div)
{
div.className = ('show' == div.className)? 'hide':'show';
}
}


[...]
Who can help me? Please, answer me only if you are very sure and you
have tested the solution proposed.

Dang you're tough. Here's a working sample:



<script type="text/javascript">

function initH2()
{
if (!document.getElementsById){ return; }

var h2 = document.getElementsByTagName('h2');

for ( var i=0; i<h2.length; i++ ) {
h2.onclick = hideDiv;
}
}

function hideDiv()
{

var div = this.nextSibling;
while (div && (!div.tagName || div.tagName.toLowerCase() != 'div'))
{
div = div.nextSibling;
}

if (div) {
div.className = ('show' == div.className)? 'hide':'show';
}
}

</script>

<body onload="initH2();">

<h2>h2 element</h2>
<div ="div1" class="show">div 1</div>

<h2>h2 element</h2>
<div id="div2" class="show">div 2</div>

<h2>h2 element</h2>
<div id="div3" class="show">div 3</div>

</body>
 
R

RobG

Hi Giacomo

You can get the source element of onclick events and other mouse events
inside the function you use to handle the event

Theres some useful info on
http://www.quirksmode.org/js/introevents.html, read the sections after
the heading "Accessing the event".

This way everything can be done in the showHide function, I just copied
over what you had in the init function and it worked on ff + ie.

function init() {
var h2 = document.getElementsByTagName('h2');

Feature testing is good.

for ( var i=0; i<h2.length; i++ ) {
h2.onclick = showHide;
}
}

function showHide( e ) {
el= (e) ? e.target : window.event.srcElement;


There is no need to use the event object: because you used a function
reference to assign the function to the element's click event, 'this'
will refer to the element that fired the event:

var el = this;

el = el.nextSibling;
while ( el.tagName != 'DIV' )

The posted code has whitespace between the h2 element and div. That
will be replaced by a #text node in some browsers. #text nodes don't
have a tagName attribute, so your script will fail. You need to test
for a tagName attribute first. It is also a good idea to always test
using lower case - not essential, but in preparation for XML I guess.

You also need to test that there was a nextSibling:


while (el && (!el.tagName || el.tagName.toLowerCase() != 'div') ){
el = el.nextSibling;
}

if (el){
// toggle className
}

Another strategy is to use:

var nextDiv = el.getElementsByTagName('div')[0];


Which will get the first div after the element, but not necessarily the
first child div.


[...]
 
T

Thomas 'PointedEars' Lahn

RobG said:
el = el.nextSibling;
while ( el.tagName != 'DIV' )

The posted code has whitespace between the h2 element and div. That
will be replaced by a #text node in some browsers. [...]

It is _not_ replaced by a text node, it /is/ a text node with whitespace
content. _Not_ in some browsers, but in /all/ browsers respecting the
W3C DOM in that regard. AFAIK, that only does not include IE-based
browsers, which would represent the numerical minority of browsers (but
not of distributed software) here. It would therefore be correct to say
that /most/ browsers work as specified and described (ignoring the
wrong "replace" wording).


PointedEars
 
R

Randy Webb

Thomas 'PointedEars' Lahn said the following on 4/20/2006 12:30 PM:
RobG said:
el = el.nextSibling;
while ( el.tagName != 'DIV' )
The posted code has whitespace between the h2 element and div. That
will be replaced by a #text node in some browsers. [...]

It is _not_ replaced by a text node, it /is/ a text node with whitespace
content.

Half true. It is a text node with whitespace content in some browsers,
not in others.
_Not_ in some browsers, but in /all/ browsers respecting the W3C DOM
in that regard.

Kudo's to the W3C and it's ability to enforce its "standards". Same for
ECMA too.
AFAIK, that only does not include IE-based browsers, which would represent
the numerical minority of browsers (but not of distributed software) here.

Unless you have tested every browser on the web then AFAYK doesn't mean
a whole lot. That could be limited to 5 browsers.

As for the "numerical minority", be careful how you say that. Telling
your boss that 'Hey, IE has a numerical minority in the range of 150-1
so I am coding to standards that IE doesn't give a crap about. Yeah, I
know IE represents about 80-90% of our viewing audience but I don't give
a crap about them because IE is a "numerical minority' will get you a
one way last check.

And, there are approx 200 million Internet Users (modify that number to
your likings, the math is still the same). Of those 200 million take the
low number of 80%. That gives you 160million IE users and 40 million
other users. How you get a "numerical minority" from that is beyond me
as your reasoning seems to elude me at times.
It would therefore be correct to say that /most/ browsers work as specified
and described (ignoring the wrong "replace" wording).

That is always correct to say they "work as described" or there would be
a flaw in the documentation of that browser. IE is closer to its own
documentation and specification than most browsers are. And when I say
its own "documentation and specification" I am referring to the MS
generated docs and specs.
 
R

RobG

Thomas said:
RobG said:
el = el.nextSibling;
while ( el.tagName != 'DIV' )
The posted code has whitespace between the h2 element and div. That
will be replaced by a #text node in some browsers. [...]

It is _not_ replaced by a text node, it /is/ a text node with whitespace
content.

I think you've over-played the semantics here Thomas. It is whitespace
until a parser (either software, your grey matter or some other device)
reads to it, whereupon it is converted into a DOM text node under
certain conditions. The author did not code a text node, one was
inferred from the source based on where the whitespace occurred.

So the whitespace is replaced by a text node.
 
T

Thomas 'PointedEars' Lahn

RobG said:
Thomas said:
RobG said:
(e-mail address removed) wrote:
el = el.nextSibling;
while ( el.tagName != 'DIV' )
The posted code has whitespace between the h2 element and div. That
will be replaced by a #text node in some browsers. [...]

It is _not_ replaced by a text node, it /is/ a text node with whitespace
content.

I think you've over-played the semantics here Thomas. It is whitespace
until a parser (either software, your grey matter or some other device)
reads to it, whereupon it is converted into a DOM text node under
certain conditions. The author did not code a text node, one was
inferred from the source based on where the whitespace occurred.

So the whitespace is replaced by a text node.

No, you are confusing things. A DOM is not necessary at all, only a markup
parser is needed. That markup parser usually parses whitespace before and
after an element as a text node containing that whitespace (as it parses
non-whitespace into elements and CDATA content). And this text node can
later be accessed as an object via the DOM, provided the parser did not
ignore it /before/. _Nothing_ is /replaced/ by anything whatsoever here.


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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top