homepage Welcome to WebmasterWorld Guest from 54.211.157.103
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
Forum Library, Charter, Moderator: open

JavaScript and AJAX Forum

    
Attaching Behaviors
Why doesn't this work?
rocknbil




msg:3242779
 4:47 am on Feb 5, 2007 (gmt 0)

In a function called by window.onload, I can attach a mouseover/mouseout object behavior easily enough by referencing the id's directly:


document.getElementById('about-link').onmouseover = function() {
document.getElementById('about').src = 'about-over.gif';
};
document.getElementById('about-link').onmouseout = function() {
document.getElementById('about').src = 'about.gif';
};
<a href="about.shtml" id="about-link"><img src="about.gif" width="84" height="22" id="about"
border="0" alt="ABOUT"></a>

But that makes for long redundant code, so why doesn't this work?


function attachRollovers () {
if (document.getElementById) {
var ids = new Array ('about','contact','join','help','members','main');
var lnks = new Array('about-link','contact-link','join-link','help-link','members-link','main-link');
for(i=0;i<ids.length;i++) {
if ((document.getElementById(ids[i])) && (document.getElementById(lnks[i]))) {
document.getElementById(lnks[i]).onmouseover = function() {
document.getElementById(ids[i]).src = ids[i] + '\-over.gif';
};
document.getElementById(lnks[i]).onmouseout = function() {
document.getElementById(ids[i]).src = ids[i] + '.gif';
};
}
}
}
}
window.onload = function() { attachRollovers(); };

Of course, the ids array references the ids of the images, and the links array references the ids of the links surrounding them, as in the first example. When you attempt to mouseover, you get "document.getElementById(ids[i]) has no properties." But all objects are present, been alert - debugging this for hours and it's driving me batty. :-)

It's not the dashes.

It obviously finds the images by ID's or it would croak in the loop, it's only on mousover it errors.

What am I missing?

 

ericjust




msg:3242805
 5:58 am on Feb 5, 2007 (gmt 0)

I've run into this myself.

Add the following line into your onmouseover function and you will see the problem:

alert(i);

It's because the function uses the last value of i which will always be ids.length -1. Therefore you should attach the mouseover and mouseout functions via another function. Alternatively you could do it within the same function, but you cannot use the i variable in the mouseover/mouseout functions... you could store that value in a property on the link itself and then reference that like: this.image_id, this.over_src.

I haven't tested the code below but it should work. Let me know if you still have trouble.

- Cheers!

function attachRollovers(lnk,img) {
lnk.onmouseover = function() {
img.src = lnk.id + '-over.gif';
}
lnk.onmouseout = function() {
img.src = lnk.id + '.gif';
}
}

function setupRollovers () {
if (!document.getElementById) return false;
var ids = new Array ('about','contact','join','help','members','main');
var lnks = new Array('about-link','contact-link','join-link','help-link','members-link','main-link');
for(i=0;i<ids.length;i++) {
if (!document.getElementById(ids[i]) ¦¦!document.getElementById(lnks[i])) continue;
var lnk = document.getElementById(lnks[i]);
var img = document.getElementById(ids[i]);
attachRollovers(lnk,img);
}
}

Fotiman




msg:3243114
 2:43 pm on Feb 5, 2007 (gmt 0)

The problem is one of scope. You have this:


for(i=0;i<ids.length;i++) {
if ((document.getElementById(ids[i])) && (document.getElementById(lnks[i]))) {
document.getElementById(lnks[i]).onmouseover =
function() {
document.getElementById(ids[i]).src = ids[i] + '\-over.gif';
};

document.getElementById(lnks[i]).onmouseout = function() {
document.getElementById(ids[i]).src = ids[i] + '.gif';
};
}
}

When your anonymous function fires, the first thing it does is:

document.getElementById(ids[i]).src = ...

What is ids[i]? It doesn't exist in this scope. It only existed in the scope where you assigned the listener.

There are ways around this, but the solution I prefer is to use the Yahoo UI Library's Event Utility to attach listeners. It does all of the heavy lifting for you.

mep00




msg:3243872
 7:27 am on Feb 6, 2007 (gmt 0)

document.getElementById(lnks[i]).onmouseover = function() {
document.getElementById(ids[i]).src = ids[i] + '\-over.gif';
};

In this case there is a simple way to fix the scope issue. If you think about it, "document.getElementById(ids[i]).src" is very redundant. It's being called from the same element which the onmuserover is an event of, so you already have a reference to the node: "this". Try the following:

function() {this.src = this.id + '\-over.gif';};

I haven't tested this (pun not intended, but welcomed:)), so I might have made an error somewhere, but I don't think so.

Scope and closures in JavaScript are hard to get your head around, but when you do, you have a very powerful tool at your disposal.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved