Rails and JavaScript: page.call gotchas

Ruby on Rails has wonderful out of the box javascript support, but sometimes implementing dynamic user interfaces is not so easy as it seems.

In an application I’m working on I have a list of people with a checkbox each. In the load event of the page I add a click handler to every checkbox using this javascript code:

  $$('.ConfermaInvitati').each(function(element) {
    Event.observe(element, 'click', clickHandler);
  });
 
// ... 
 
function clickHandler(event) {
  var e = Event.element(event);
  new Ajax.Updater(e.up(), 'my/invited/toggle', {
    parameters: { id: e.up().up().id },
    onLoading: function() { e.src = "/images/admin/spinner.gif"; },
    onSuccess: function() { new Ajax.Request('my/refresh', {}) }
  });  
}

This works fine until I add a new person via an Ajax call. That person won’t have a clickHandler because the element wasn’t on the page when I called the click handler. So I thought it was time to test page.call in the render :update block I had in the rails application.

I tried this code:

render :update do |page|
  # Do stuff that creates the new objects and adds it to the page
  # The data I need is in @invited
  page.call("Event.observe($$('##{@invited.permalink} .ConfermaInvitati').first()), 'click', clickHandler)")

Obviously that didn’t work, and it turned out I have to read documentation before doing fancy things :)

The rails docs told me that I had to use call passing the function name as the first argument and an array of parameters as the second argument, the problem is that call turns all the parameters into strings—this means I could not pass the clickHandler function to Event.observe.

I found the solution in <<. If you do page << "foo", foo will be evaluated as raw javascripts. This meant I was able to do

page << "Event.observe($$('##{@invited.permalink} .ConfermaInvitati').first()), 'click', clickHandler)

and finally have the functionality I was looking for. So remember, don’t page.call if you need to pass javascript variables to your functions.

Comments are closed.