Search code examples
ruby-on-railsajaxprototypejsujs

Rails 3 UJS driver events


According to Simone Carletti blog post, Rails 3 ajax helpers have changed a lot. We are supposed to write more javascript with rails 3 than we used to with rails 2.

I tried to figure out how to show up an ajax loading gif -while an ajax query is running- in the "rails 3 way". I came up with this kind of code, which uses javascript events sent by the Rails 3 UJS driver. This example uses prototype:

<div id="wait" style="display:none">
    <img src="/images/ajax-loader.gif"> Please wait...
</div>

<div>
    <%= link_to 'Get', 'finished', :id => "mylink", :remote => true %>
</div>

<%= javascript_tag do %>
        Event.observe('mylink', 'ajax:before', function(event) {
            $('wait').show();
        });
        Event.observe('mylink', 'ajax:complete', function(event) {
            $('wait').hide();
        });
<% end %>

This works well, but I wish it was possible to write these ajax events "triggers" with the help of the prototype and scriptaculous helpers, just like when we use link_to_function for example:

<%= 
  link_to_function("toggle visibility") do |page|
    page.toggle "wait"
  end
%>

Is there a way to do that, or are we supposed to write ajax events "triggers" in javascript directly, either prototype or jquery?

Best regards,

Philippe Lang


Solution

  • After looking at rails source code, I came up with this solution:

      def javascript_event_tag(name, event, &block)
        content = "Event.observe('#{name}', '#{event}', function() {"
        content = content + update_page(&block)
        content = content + "});"
    
        content_tag(:script, javascript_cdata_section(content))
      end
    

    This makes it easier to react to UJS events:

    <div id="wait" style="display:none">
        <img src="/images/ajax-loader.gif"> Please wait...
    </div>
    
    <%= link_to 'ajax call', 'code_on_controller', :id => "mylink", :remote => true %>
    
    <%= 
       javascript_event_tag('mylink', 'ajax:before') do |page|
         page.show 'wait'
       end
     %>
     <%= 
       javascript_event_tag('mylink', 'ajax:complete') do |page|
         page.hide 'wait'
       end
     %>
    

    Instead of having to write raw prototype or jquery code, you can use rails helpers.