views:

59

answers:

3

I'm using mootools: I can't figure out how to use a variable when using an addEvent.

I want to use a for next loop to set values in a loop:

for (x=0;x<num;x++){
var onclickText = 'function (){onclick="addPageMoveEvent('+x+'"); }';
$('pageNum'+x).addEvent('click', onclickText);
}

>

I've search forums but not found any help.

Any help would be great.

Thanks

+2  A: 

Warning: this first example will not work! Read on for an explanation.

You are confusing onclick HTML syntax with the MooTools addEvent. Try

for (var x=0;x<num;x++){
    $('pageNum'+x).addEvent('click', 'addPageMoveEvent('+x+');');
}

This is simpler and cleaner, but might still not do what you want. This code will call the function addPageMoveEvent every time the link is clicked... is that what you want?

Since MooTools doesn't allow the above method, you must use the following:

A programmatically more interesting and less hazardous way to do the same would be:

factory = function (x) { return function() { addPageMoveEvent(x); }; };
for (var x=0;x<num;x++){
    $('pageNum'+x).addEvent('click', factory(x));
}

This uses a factory for creating closures that hold your values of x... rather complex code, but it's the purist way. It also avoids using the scary eval that occurs because you feed addEvent a string. (It seems that MooTools doesn't like the other option anyway.)

MvanGeest
Thanks, I tried the purists way and it work!! Thanks. Can you confirm to me my understanding. I think that it adds factory(0) factory(1) etc to the elements and then it calls that passing in the factory value as the x ?
AAA
If I understand that sentence correctly, yes. It calls `factory(1)` for example. `factory` executes and returns a function that, when executed, calls `addPageMoveEvent(1)`. Then this function is passed into the `addEvent` call. When the event fires, this function is called, which in turn makes the right `addPageMoveEvent` call. Essentially, `factory` is a function factory function that manufactures a function that calls another function passing on the ***value*** of the variable that was passed to the factory. ... Read over this a few times :) Hope this helps.
MvanGeest
+2  A: 

The addEvent method in MooTools accepts two arguments:

myElement.addEvent(type, fn);

Arguments:

  • type - (string) The event name to monitor ('click', 'load', etc) without the prefix 'on'.
  • fn - (function) The function to execute.

It does not take a string and passing a string such as "myFunction()" or "function() { myFunction(); }" will not work.

Since you are inside a loop, and the variable x will share the environment, you need to wrap its value inside another closure. One way is to use an additional closure:

$("pagenum" + x).addEvent("click", (function(value) {
    return function() { addPageMoveEvent(value); }
})(x));

See all questions on StackOverflow regarding this particular problem of creating closures within loops.

Also worth checking out is this MDC article - Creating closures in loops: A common mistake

Anurag
Oops, I was used to jQuery that is more flexible. I'll update my answer. I like MooTools more than any other framework, but I increasingly feel it's rather rigid.
MvanGeest
+1 for the reference link.
MvanGeest
Thanks @MvanGuest :) I haven't seen [bind](http://api.jquery.com/bind/) or one of the shorthand functions such as [click](http://api.jquery.com/click/) in jQuery accepting a string of executable JavaScript code before to be honest.
Anurag
Weird. I must have seen something like that somewhere, and MooTools and jQuery are the only frameworks I'm familiar with... If I find it, I'll tell you.
MvanGeest
A: 

That a use case for mootools pass method.

for (x=0;x<num;x++){
  $('pageNum'+x).addEvent('click', addPageMoveEvent.pass(x));
}

Pass internally creates a closure that holds x in the his scope, so when the click event is fired it has the right value cause its not the same from the for loop.

eskimoblood