views:

108

answers:

2

I'm working on a project where I'd place an search box with a default set of results, over the layout using Prototype which is triggered from a click event.

When the output is set, that new page has it's own Javascript which is uses, to dynamically filter the results.

Now the new set of results do not work with the Javascript set previously.

How can I maintain a persistent event with calling new events each time? Or is that what I am supposed to do.

Here is a bit of code which is loaded in 'loaded_page.php'

<script language="javascript">
 var o = new Compass_Modal('add_button', 'history');
 var placetabs = new Tabs('tabs', {
  className: 'tab',
  tabStyle: 'tab'
 });
 $$('.add_button').each(function(s, index){
  $(s).observe('click', function(f) {
   loadData();
  });
 });

 function loadData() {
  new Ajax.Request('/sponsors/search', {
   onComplete: function(r) {
    $('overlay').insert({
     top:'<div id="search_table">'+r.responseText+'</div>'
    });
   }
  })
 }
</script>

Then in the included page which is inserted via javascript:

    <div id="search_overlay">
 <div id="form_box">
  <a href="javascript:void(null);"><img src="/images/closebox2.png" class="closebox" /></a>
  <form method="post" id="search_form" class="pageopt_left">
   <input type="text" name="search_box" id="search_box" value="search" /> 
  </form>
 </div>
 <div id="table_overlay">
  <table class="sortable" id="nf_table" cellpadding="0" border="0" cellspacing="0"> 
<tr> 
<th id="name_th">Name</th><th id="amount_th">Amount</th><th id="tax_letter_th">Tax Letter</th><th id="date_th">Date</th><th id="add_th">Add</th></tr> 
<tr> 
<td>Abramowitz Foundation (The Kenneth & Nira)</td><td><input type="text" name="amount" value="" id="amount_111" /></td><td><input type="checkbox" name="tax_letter" value="1" id="tax_letter_111" /></td><td><input type="text" name="date" value="" id="date_111" /></td><td><a href="http://compass.krd.webhop.net/sponsors/add/111" class="add_button"><img src="/images/icons/add.png" title="add contact" /></a></td></tr> 
... more rows
</table>
 </div>
</div>    
<script language="javascript">
 var c = new Compass_Search('contacts', 'table_overlay');
 c.set_url('/sponsors/sponsor_search');
 $$('.add_button').each(function(s, index) {
  $(s).observe('click', function(e) {
   $(e).stop();

   var params = $(s).href.split("/");
   var userid = params[5];
   var amount = 'amount_'+params[5];
   var date = 'date_'+params[5];
   var tax  = 'tax_letter_'+params[5];
   if(!Form.Element.present(amount) || !Form.Element.present(date)) {
    alert('your amount or date field is empty ');
   } else {
    var add_params =  {'amount':$F(amount), 'date':$F(date), 'tax':$F(tax), 'id':userid};
    if(isNaN (add_params.amount)) {
     alert('amount needs to be a number');
     return false;
    } else {
     new Ajax.Request('/sponsors/add', {
      method: 'post',
      parameters: add_params,
      onComplete: function(e) {
       var post = e.responseText;
       var line = 'amount_'+add_params.id;
       $(line).up(1).remove();
      }
     })
    }
   }
  });
 });

 this.close = $$('.closebox').each(function(s, index) {
  $(s).observe('click', o.unloader.bindAsEventListener(this));
})
</script>

You'll notice in the inserted portion, a new Javascript which also, updated its own content with yet new observers. When the content gets updated, the observers do not work.

A: 

As you're calling Element#insert, I suppose String#evalScripts should be automatically called (as having looked in the implementation of those methods)

Maybe you can try to do some console.log()/alert() messages before the Element#observe calls, to see where it is going wrong. It may be because the Javascript is not evaluated at all, or that there is something wrong with your code or something like that.

As a tip: check the documentation on Array#invoke, with that method you can rewrite something like:

$$('.add_button').each(function(s, index){
    $(s).observe('click', function(f) {
        loadData();
    });
});

into this:

$$('.add_button').invoke('observe', 'click', function(event){
    loadData();
});
// $$('.add_button').invoke('observe', 'click', loadData);
JoostK
+1  A: 

Use event delegation.

Besides making it possible to replace "observed" elements, this approach is also faster and more memory efficient.

document.observe('click', function(e){
  var el = e.findElement('.add_button');
  if (el) {
    // stop event, optionally
    e.stop();
    // do stuff... `el` now references clicked element
    loadData();
  }
});
kangax