Oops, I forgot to take out the if(document.addEventListener). That would cause problems in IE.
The code should be
Code:
(function() {
var thumbs = document.getElementById("thumbnails").getElementsByTagName("a");
var largeImgs = document.getElementById("largeImage").getElementsByTagName("div");
var n = thumbs.length;
function toggle(x) {
for(var i=0; i<n; ++i)
if(i!=x) largeImgs[i].style.display = "none";
else largeImgs[i].style.display = "block";
}
for(var i=0; i<n; ++i)
thumbs[i].onclick = (function() {
var x = i;
return function(e) {
toggle(x);
};
})();
})();
javascript:void(0) means do nothing and return nothing.
Now an explanation:
Code:
for(var i=0; i<n; ++i)
thumbs[i].onclick = (function() {
var x = i;
return function(e) {
toggle(x);
};
})();
This sets up a loop that iterates n times, where n is defined above as thumbs.length.
Then for each element in thumbs, thumbs[i], I tell it to react to a user's click, via onclick.
Now I need to explain something that might be a little confusing:
Code:
var myFunc = function(){something};
This creates a function that does something when activated, aka, through myFunc();
Now if you did:
Code:
function(){something};
This creates a function that would do something if activated. But the question is how? It is not attached to a variable such as myFunc. This is called an anonymous function. It has no name.
However, there are uses for them even if you can't call them whenever you want.
One thing to notice is that if you take the variable a function is stored in, you could do this:
This is equivalent to:
This is analogous to parenthesis around numbers:
All these do the same thing.
To understand why this works with functions requires an understanding of variable references. For example:
Code:
var func1 = function(){ alert('hi'); };
var func2 = func1;
The above code creates two variables, func1 and func2, but there is only one function. When you do
you are not copying the entire function(){alert('hi');} into func2... only references to it. Rather when you do
Code:
var func1 = function(){ alert('hi'); };
Javascript creates a function, function(){alert('hi');}, and stores it in the computer's memory somewhere. Then when the assignment happens, instead of giving func1 the function, the computer stores into func1 a reference of the function stored in memory.
In other words, the computer tells func1 where to find the function. So when you do
the computer asks func1 what is is holding. It finds out it is holding a reference to a function. Then it asks, where is this function located, and func1 returns the actual function. Once returned, the computer takes that function and activates it.
Anyway, (myFunc)() works because myFunc will return the function, and you can think of it as for a split second, the actual function sits around within those parenthesis before becoming activated via the ().
The reason why this matters is because you can use this principle with anonymous functions. Say you had the anonymous function:
Code:
function(x){ alert(x); }
And you wanted to execute it immediately, right when you made it.
You could do
Code:
(function(msg){ alert(msg); })("hello");
Note where the "hello" is. Just like a normal function, you still have to supply arguments, in this case, for msg.
Now, you might be wondering what the point of creating a one-time function and executing it immediately. Why not write the code outside of a function if you are going to do that?
The key is that functions create their own scope, meaning variables made inside it are only known to the function. This means the outside world can't change what's happening inside it.
So in my code I do:
Code:
(function() {
var x = i;
return function(e) {
toggle(x);
};
})();
First I created an anonymous function and immediately execute it once made. Inside the function, I make a variable called x and assign it the value i.
While x cannot be seen from the outside, the function can see variables that are outside it (to a certain extent). So it knows i.
Then it creates a function
Code:
function(e) { toggle(x); };
and returns the reference of that function via the return keyword to thumbs[i].onclick.
A useful thing about Javascript is that it allows something called a closure. I'll get around to that in a sec.
Normally, when a function is finished executing, all the local variables it creates vanish. However, if you can return something that can reference at least one of those local variables, then the local variables can live beyond the life of their function. At the same time, they are still considered local. Things that were not created in the function still cannot see or touch them.
In my case, I return a new (and anonymous) function that makes reference to the local variable x. Since this function was returned and therefore can be used outside of the function that created it, and at the same time, it uses the local variable x of it's parent function, x does not die.
This is the essence of a closure: to make variables that are local within a function, but linger after a function has died.
Code:
thumbs[i].onclick = function(e){something};
Means that whenever that element is clicked, do that function. All functions assigned as events (such as clicking) need the paramater e as their first and only paramater.
It should be noted that thumbs[i].onclick is assigned a function reference, in this case, the reference of the
Code:
function(e) { toggle(x); }
that was returned.
Now, all the thumbs[i]'s have been assigned event handlers (function for events). Each of these handlers have their own local variable x that cannot and will not interfere with one another despite having the same name.
So when clicked, the anonymous function assigned to the onclick will activate toggle(x).
The function toggle says hide all the images in largeImgs, except for the x'th image (rememeber, there is a 0'th index).
To tie things up, I wrapped my entire code within an anonymous function that I immediately execute so that you wouldn't get variable name collisions. (Like a self-inclosed namespace.)
I hope this makes sense
Bookmarks