1

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>
</div>

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.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Aaron Luman
  • 635
  • 1
  • 10
  • 29

3 Answers3

2

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
  • 3,492
  • 17
  • 20
  • 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 Apr 11 '10 at 00:37
  • You might want to try out this alternative Delegation plugin: http://mootools.net/forge/p/better_event_delegation It currently works better than the one shipped with MooTools. – Oskar Krawczyk Apr 11 '10 at 22:14
1

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.

Community
  • 1
  • 1
Andy E
  • 338,112
  • 86
  • 474
  • 445
  • That would probably work but I don't understand the code and I like to stick with stuff that makes sense to me... haha – Aaron Luman Apr 09 '10 at 22:08
  • 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. – Aaron Luman Apr 10 '10 at 00:18
  • 2
    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 Apr 10 '10 at 08:28
  • +1 to Dimitar Christoff for offering the MooTools solution. User is asking MooTools, not jQuery. – Alejandro García Iglesias Dec 19 '11 at 17:46
  • @AndyE Sorry, you're right. Still, +1 to Dimitar Christoff because his proposal is the newer way of doing in MooTools. Best regards. – Alejandro García Iglesias Dec 20 '11 at 18:05
0

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
  • 92,731
  • 24
  • 156
  • 164
  • 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 – Aaron Luman Apr 09 '10 at 22:09