Handle events from central script

M

Markus Ernst

Hello

I try to hanlde events centrally for avoiding the need to write four event
handler attributes to every link. The task is changing the class name of a
link's containing <div> element. After lots of googling I came to this:

if (document.getElementsByTagName) {
a = document.getElementsByTagName("a");
for (var i=1; i<a.length; i++) {
var element = a;
element.onmouseover = function() { element.parentNode.className =
"aktiv"; };
element.onMouseOut = function() { element.parentNode.className =
"passiv"; };
element.onFocus = function() { element.parentNode.className =
"aktiv"; };
element.onBlur = function() { element.parentNode.className =
"passiv"; };
}
}

The script does not throw any errors neither in IE 6 nor in Firefox, but it
does only change the last element to aktiv, regardless of which element is
hovered or unhovered.

I thought of the a overwriting the element variable in every loop and
also tried calling a directly, and other things such as
var element = document.getElementById(a.id);
or an for-in-loop; the result is only the same.

Is my approach totally wrong, or is there anything I am missing?

Thanks for any hint
Markus
 
M

Michael Winter

On 23/06/2005 14:24, Markus Ernst wrote:

[snip]
if (document.getElementsByTagName) {
a = document.getElementsByTagName("a");
for (var i=1; i<a.length; i++) {
var element = a;
element.onmouseover = function() { element.parentNode.className =
"aktiv"; };
element.onMouseOut = function() { element.parentNode.className =
"passiv"; };
element.onFocus = function() { element.parentNode.className =
"aktiv"; };
element.onBlur = function() { element.parentNode.className =
"passiv"; };
}
}


The problem is that you're forgetting about case-sensitivity: for
instance, there is no recognised onMouseOut property, but there is a
generally recognised onmouseout property. The same goes for onFocus and
onBlur.

However, you don't need a script to do what you're attempting. CSS is
quite capable:

a:link {
/* Declarations used by the .passiv class */
}
a:focus,
a:hover {
/* Declarations used by the .aktiv class */
}

Note: IE doesn't support the :focus pseudo-class, though others do.

[snip]

Mike
 
M

Markus Ernst

Michael said:
On 23/06/2005 14:24, Markus Ernst wrote:

[snip]
if (document.getElementsByTagName) {
a = document.getElementsByTagName("a");
for (var i=1; i<a.length; i++) {
var element = a;
element.onmouseover = function() {
element.parentNode.className = "aktiv"; };
element.onMouseOut = function() {
element.parentNode.className = "passiv"; };
element.onFocus = function() {
element.parentNode.className = "aktiv"; };
element.onBlur = function() {
element.parentNode.className = "passiv"; };
}
}


The problem is that you're forgetting about case-sensitivity: for
instance, there is no recognised onMouseOut property, but there is a
generally recognised onmouseout property. The same goes for onFocus
and onBlur.


Thank you very much for your input. The case sensitivity issue does indeed
solve a part of my problem - now all four events are performed, but still
always on the last element.
I think I need to find a way to save a reference to a which is not
overwritten by the following loop.
However, you don't need a script to do what you're attempting. CSS is
quite capable:

Yes I use this for the <a> element itself. The task is to highlight also the
containing element of this html structure:

<div class="passiv">
<a href="koepfe/paolo_tonti.html">Paolo Tonti</a>
<span>Werbung / Konzept / Graphic Design</span>
</div>

I don't know if CSS provides a syntax to address the parent element - but I
am sure that it would not be supported by today's common browsers anyway...

Of course I have a working solution with four event handlers in every link -
but I would be happy to find a solution that makes a maximum separation of
content and presentation.
 
M

Michael Winter

On 23/06/2005 15:11, Markus Ernst wrote:

[snip]
Thank you very much for your input. The case sensitivity issue does indeed
solve a part of my problem - now all four events are performed, but still
always on the last element.

Sorry, I forgot to comment on the functions.

Closures do not take a 'snapshot' of the variables in their scope chain,
but remain live. All of these functions will share the same element
value, and that value will always be the last A element in the
collection at the end of the loop. The solution is simple though, and is
more efficient, too:

function setAktiv() {
var pN = this.parentNode;

if(pN) {pN.className = 'aktiv';}
}
function setPassiv() {
var pN = this.parentNode;

if(pN) {pN.className = 'passiv';}
}

if(document.getElementsByTagName) {
var a = document.getElementsByTagName('a'),
i = a.length;

while(--i) {
a.onmouseover = a.onfocus
= setAktiv;
a.onmouseout = a.onblur
= setPassiv;
}
}

By the way, if you didn't mean to ignore the first A element in the
collection (arrays and collections use zero-based indices), then change
the while condition to a postfix decrement: i--

[snip]
The task is to highlight also the containing element of this html structure:

Sorry. I'm clearly not being very attentive today. :(

[snip]

Mike
 
M

Markus Ernst

Michael said:
[snip]

Closures do not take a 'snapshot' of the variables in their scope
chain, but remain live. All of these functions will share the same
element value, and that value will always be the last A element in the
collection at the end of the loop. The solution is simple though, and
is more efficient, too:

function setAktiv() {
var pN = this.parentNode;

if(pN) {pN.className = 'aktiv';}
}
function setPassiv() {
var pN = this.parentNode;

if(pN) {pN.className = 'passiv';}
}

if(document.getElementsByTagName) {
var a = document.getElementsByTagName('a'),
i = a.length;

while(--i) {
a.onmouseover = a.onfocus
= setAktiv;
a.onmouseout = a.onblur
= setPassiv;
}
}


This is really amazing, thanks a lot!
By the way, if you didn't mean to ignore the first A element in the
collection (arrays and collections use zero-based indices), then
change the while condition to a postfix decrement: i--

I actually meant to leave out index 0, anyway it is a better solution to
only address the links below a specified main container (such as navigation,
contents or whatever). So my final solution can be called with a list of
containers:
<body onLoad="aktiviereLinks('navigation', 'contents')>

That's the script:

function machAktiv() {
var pN = this.parentNode;
if (pN) {
var klasse = "aktiv";
if (pN.className.indexOf("Unten") != -1) klasse = klasse + "Unten";
pN.className = klasse;
}
}
function machPassiv() {
var pN = this.parentNode;
if (pN) {
var klasse = "passiv";
if (pN.className.indexOf("Unten") != -1) klasse = klasse + "Unten";
pN.className = klasse;
}
}
function aktiviereLinks() {
if (document.getElementsByTagName) {
args = aktiviereLinks.arguments;
j = args.length;
while (j--) {
a = document.getElementById(args[j]).getElementsByTagName("a");
i = a.length;
while (i--) {
a.onmouseover = a.onfocus = machAktiv;
a.onmouseout = a.onblur = machPassiv;
}
}
}
}

Thank you very much for your great inputs, I learnt a lot today!
 
M

Mick White

Markus Ernst wrote:

[snip]
function aktiviereLinks() {
if (document.getElementsByTagName) {
args = aktiviereLinks.arguments;
j = args.length;
while (j--) {
a = document.getElementById(args[j]).getElementsByTagName("a");
i = a.length;
while (i--) {
a.onmouseover = a.onfocus = machAktiv;
a.onmouseout = a.onblur = machPassiv;
}
}
}
}


Couple of things:
[1] "Function.arguments" deprecated
[2] Localize scope of loop variables (i & j)

See rewritten function below:

function aktiviereLinks() {
if (document.getElementsByTagName) {

var j = arguments.length;
while (j--) {
a = document.getElementById(args[j]).getElementsByTagName("a");
var i = a.length;
while (i--) {
a.onmouseover = a.onfocus = machAktiv;
a.onmouseout = a.onblur = machPassiv;
}
}
}
}

Mick
 
M

Markus Ernst

Mick said:
Couple of things:
[1] "Function.arguments" deprecated
[2] Localize scope of loop variables (i & j)

Thanks a lot. Now I added a recursive function call to make the hover in all
elements up to the next <div> element:

function machAktiv() {
var pN = this.parentNode;
umschalten(pN, "aktiv");
}
function machPassiv() {
var pN = this.parentNode;
umschalten(pN, "passiv");
}
function umschalten(pN, klasse) {
if (pN) {
var kl = klasse;
if (pN.className.indexOf("Unten") != -1) kl = kl + "Unten";
pN.className = kl;
if (pN.nodeName.toLowerCase() != "div") umschalten(pN.parentNode,
klasse);
}
}
function aktiviereLinks() {
if (document.getElementsByTagName) {
var j = arguments.length;
while (j--) {
a =
document.getElementById(arguments[j]).getElementsByTagName("a");
var i = a.length;
while (i--) {
a.onmouseover = a.onfocus = machAktiv;
a.onmouseout = a.onblur = machPassiv;
}
}
}
}

So in the following HTML the "person" element and all children will be
highlighted if one of the links is hovered:

<body onLoad="aktiviereLinks('head')">
<div id="person" class="passiv">
<img src="myimage.gif" alt="">
<p class="passiv">
My name<br>
<a href="mailto:[email protected]">[email protected]</a><br>
<span class="passiv"><a
href="http://www.domain.com">www.domain.com</a></span>
</p>
</div>
</body>

Thank you all for your help!!
Markus
 

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,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top