Can some one help me with javascript.
Hi,
I am working on javascript. And i could not understand the following…
In the following code:
var ulNodes = getElementsByClass("nice-menu");
var liNodes = null;
for(var i = 0; i < ulNodes.length; i++) {
liNodes = ulNodes[i].getElementsByTagName("li");
for(var j = 0; j < liNodes.length; j++) {
if(liNodes[j].className == "menuparent") {
liNodes[j].onmouseover=function()
{
this.className += " over";
}
liNodes[j].onmouseout=function()
{
this.className = "menuparent";
}
}
}
}
The above code is working properly, but when i try to put dealy in the mouseout function its not working. I have changed the onmouseout function in the following way…
liNodes[j].onmouseout=function()
{
timer = window.setTimeout(function (){
alert("this.className is undefined here" + this.className );
this.className = "menuparent";
},4000);
}
Here this.className is undefined when it is used in the function setTimeout. Any sujjestions highly appriciated.
Hi and welcome to sitepoint, justsaynik.
setTimeout argument is executed in global content, therefore “this” is the Window and not your html node. You have to “bind” the method to an object to be able to use “this”:
Function.prototype.bind = function(obj) {
var me = this;
return function() { me.apply(obj) }
}
someObject.onmouseout = function() {
setTimeout(
function() {
alert(this.className)
}.bind(someObject)
,1000
)
}
The fact that the whole happens in a loop, makes it even more tedious. Not only do you need to bind the method, you should also isolate the object from others by creating the separate scope for it.
function createHandler(o) {
return function() {
setTimeout(
function() {
alert(this.className)
}.bind(o)
,1000
)
}
}
var cc = <your collection>
for(var i = 0; i < cc.length; i++)
cc[i].onmouseout = createHandler(cc[i]);
Looks pretty ugly doesn’t it? That’s exactly the reason why iterators are preferred over loops and setter methods over direct assignment. This is how the above looks with prototype:
$A(<your collection>).each(function(o) {
Event.observe(o, 'mouseover', function() {
setTimeout(function() {
alert(this.className)
}.bind(o), 1000);
});
});
Thanks a lot. Your post has helped me a lot. The problem with which i am working is solved. 