views:

349

answers:

3

I putting together a page that will display a set of stored values. I am using mootools and AJAX calls to update the values without needing to refresh the page each time the user selects a new item from the drop down menus.

the HTML each line looks something like:

<div class="selections">
<input class="checkbox selector" type="checkbox" CHECKED />

<span class="b_name">
    <select class="b_n selector">
        <!-- options -->
    </select>
</span>

<span class="b_level">

    <select class="b_l selector">
        <!-- options -->
    </select>

</span>

<span class="values">
    <!-- the values -->
</span>

In the head I have set up an event listener like:

    $$('.selector').addEvent('change', function(event){changeValues(this);});

My problem is that when the "b_name" select changes I have to update the list of options in the "b_level" select. I accomplish that by getting a list of the possible options from my database through a php script on another page and replacing "b_level"'s innerHTML. Once I do that, the event listener attached to "b_l selector" no longer works.

I tried to resolve this issue by explicitly attaching an event listener to "b_l selector" each time "b_name" changes like so:

    row.getElement('.b_l').addEvent('change', function(event){changeValues(row.getElement('.b_l'));});

where 'row' is the html element 'div.selections'.

It still isn't working and I have no idea what's going on. Can anyone offer a suggestion as to how I can get this resolved? or perhaps a better way to do what I'm doing.

Thanks

+1  A: 

When you set innerHTML on an element, the element's contents are completely cleared and replaced with a new set of elements -- the ones parsed from the innerHTML property. Any events set on the old elements will not apply to the new ones.

jQuery provides a solution to this problem with live() events. I found a solution here that apparently achieves the same with mootools.

Andy E
That would probably work but I don't understand the code and I like to stick with stuff that makes sense to me... haha
baiano
I ended up needing to use this after all to get the event listeners to apply to rows added by the user. It works perfectly, now if I could just understand why.
baiano
the latest practice in mootools is to achieve this through click:relay, here's an example i put together here: http://www.jsfiddle.net/tgvYb/ - click to add a new div to menu that has event delegation listener and it will behave just as the previous ones w/o attaching any new events.
Dimitar Christoff
A: 

Your approach is correct, there's probably just a bug in your addEvent() code. The reason the event handler disappears when you replace the innerHTML is straightforward enough - you are removing the elements that the handlers are on, so the handlers are removed as well. But your approach to re-add the handler should work.

I think it's possible that it's a scoping issue. What happens if you reference the div explicitly, like this:

row.getElement('.b_l').addEvent('change', function(event){
{
  changeValues($$('div.selections .b_l'));
});
zombat
that makes sense. I changed my code so that it only replaces the options and not the select container element and now it works. Thanks
baiano
+1  A: 

This is how JavaScript works, it's not a bug.

What you need to use is Element Delegation - you attach an event to the parent element, in the same time specifying the element that the event should be delegated to.

Here's a basic example of Element Delegation in action: http://jsfiddle.net/oskar/ENR3E/

And the documentation: http://mootools.net/docs/more/Element/Element.Delegation

Oskar Krawczyk
Note that the current implementation of delegation in MooTools More doesn't support form events because these events do not bubble (and MooTool 1.2 doesn't give you the option to use capture).
Anutron
You might want to try out this alternative Delegation plugin: http://mootools.net/forge/p/better_event_delegationIt currently works better than the one shipped with MooTools.
Oskar Krawczyk