javascript - Prototype add event listener - Stack Overflow

For some reason, when I try assigning a actionlisetner to the list elements the value does not stick. H

For some reason, when I try assigning a actionlisetner to the list elements the value does not stick. Here is what I mean:

Event.observe(window, 'load', function() {
    for(i = 1; i <= $$('ul#review_list li').length; i++) {
        $('cover_' + i).observe('click', function(event) {
            alert(i);
        }); 
    }

});

So there are 7 list elements in #review_list and for some reason whenever any of the li elements are click I get an alert with value 8 for every element clicked. I want each to alert its respective i value. What am I doing wrong here?

Thanks!

For some reason, when I try assigning a actionlisetner to the list elements the value does not stick. Here is what I mean:

Event.observe(window, 'load', function() {
    for(i = 1; i <= $$('ul#review_list li').length; i++) {
        $('cover_' + i).observe('click', function(event) {
            alert(i);
        }); 
    }

});

So there are 7 list elements in #review_list and for some reason whenever any of the li elements are click I get an alert with value 8 for every element clicked. I want each to alert its respective i value. What am I doing wrong here?

Thanks!

Share Improve this question edited Dec 28, 2011 at 13:36 Rob W 349k87 gold badges807 silver badges682 bronze badges asked Aug 16, 2009 at 12:35 DannyDanny 4,7746 gold badges44 silver badges55 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

Try this:

Event.observe(window, 'load', function() {
    for(i = 1; i <= $$('ul#review_list li').length; i++) {

        (function (i) { // i is passed as an argument below

            $('cover_' + i).observe('click', function(event) {
                alert(i); // creates a closure around the argument i
            });

        })(i); // pass i as an argument

    }
});

The reason for which the first method does not work is because alert(i); creates a closure around the loop variable i, which gets incremented for each event assignment. At the time the first event will be fired, the value of i, which is mon for all the events is 8, that's why you get 8 no matter where you click.

In the second method, the one I posted, alert(i) creates a closure around the argument i, which won't be shared with any other event listener.

Anyway, you should read this article on JavaScript closures to better understand them.

As Ionut G. Stan says, the issue is the closure over 'i'. RaYell is right about your wanting to declare the var (but not about that solving the problem).

That loop also repeatedly re-executes the $$ call, which isn't really ideal, and pletely unnecessarily calls $ to look up elements you've already looked up (via $$).

FWIW:

Event.observe(window, 'load', function() {

    $$('ul#review_list li').each(function(elm, index) {
        ++index; // Now it's 1-based
        elm.observe('click', function(event) {
            alert(index);
        });
    });
});

$$ looks up the elements, Enumerable#each then iterates through the result calling the given function with the element reference and its zero-based index in the array. The event handler is then a closure over several things, including the index parameter passed into the #each iterator.

Edit: I'm sorry, I just realized I made a massive assumption below: That the cover_x elements are, in fact, the list items under review_list. If they're not, disregard the below and my apologies! - T.J.

So that works, but it's also unnecessarily plex. Event delegation could be your friend here: Look for clicks on the list, rather than list items:

Event.observe(window, 'load', function() {
    $('review_list').observe('click', function(event) {
        var li;
        li = event.findElement('li');
        if (li) {
            // ...your code here to interact with the list item.
            // If you need the index, you can find it easily enough:
            // index = parseInt(li.id.substring(6));
            // ...since your IDs on the LI items is "cover_x" with x
            // being the index.
        }
    });
});

Try adding a var keyword to your for loop. Without var you are assigning a global variable i, which is then incremented on every loop iteration. So after the loop it will have the value 8 and your alert is refering to that value.

Event.observe(window, 'load', function() {
    for(var i = 1; i <= $$('ul#review_list li').length; i++) {
        $('cover_' + i).observe('click', function(event) {
                alert(i);
        });     
    }
});

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745208820a4616721.html

相关推荐

  • javascript - Prototype add event listener - Stack Overflow

    For some reason, when I try assigning a actionlisetner to the list elements the value does not stick. H

    6小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信