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
The idea of UJS is to move the javascript code out of the views into separate js files. The way you're doing it is defeating that goal. Instead, I believe you should have a js file with a "dom:loaded" or similar handler that sets up handlers for rails callbacks and other events.
Something like (using prototype):
(function () {
$(document).on('dom:loaded', function (event) {
$$('a[data-remote=true]').each(function (link) {
link.on('ajax:complete', function (request) {
// do something
});
});
});
}());
This way all javascripts are separated from the view, which is the idea of unobtrusive javascript.
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.