Search code examples
javascriptprototypejsdom-events

Observing events on injected elements using prototype


I asked a question previously, it was answered correctly in the form I asked it but realised now why it wasn't working for me.

I have this code to observe multiple select menus:

$('product_options').select('select').invoke("observe","change",optchange); 

This does work - as pointed out - with static layout like this:

<html> 
  <head> 
    <title>optchange</title> 
    <script type="text/javascript" src="prototype.js"></script> 
  </head> 
  <body> 
    <div id="product_options"> 
      <select id="o0"> 
        <option>1</option> 
        <option>2</option> 
      </select> 
      <select id="o1"> 
        <option>1</option> 
        <option>2</option> 
      </select> 
      <select id="o3"> 
        <option>1</option> 
        <option>2</option> 
      </select> 
    </div> 
    <script type="text/javascript"> 
      function optchange(e) { 
        alert("optchanged"); 
      } 
      $('product_options').select('select').invoke("observe","change", optchange); 
    </script> 
  </body> 
</html> 

But in my context, making a selection in the first select menu fires of an Ajax.Updater that completely replaces the content of Select 2 - this is killing the event observer. Is there a way to fix this without having to apply a new event observer each time?


Solution

  • What you're looking for here is event bubbling - With event bubbling, you can assign just one event handler to a higher element and the browser will pass any events on its children up the chain to their parent. You would end up with something more like this:

    $('product_options').observe("change",function(event){optchange(event);});
    
    function optchange(event){
        console.log(Event.findElement(event, 'select'));
    }
    

    However, there is a bit of a gotcha here - according to this post select events don't bubble in IE6