, or . If so, it strips the table down and rebuilds it dynamically, thus giving you the appearance of having updated the table in place.
the server-side call, the :complete callback is fired (if defined). This gives you a great place to turn off progress indicators, reenable forms and fields, and generally put the page back into its ready state.
link_to_remote One of the most common Ajax uses allows the user to request a new piece of information to add to the current page. For example, you want to provide a link that allows the user to fetch the current status of their inbox, compute the current balance in their account, or perform some other computationally intense or time-sensitive action that you otherwise didn’t want to perform at page initialization. Because users of web applications are trained to use hyperlinks as the main point of interaction with your application, it makes sense to use a hyperlink to provide this behavior. Generally, your initialized page will render the link and also render an empty or invisible container element (often a , but it can be any element with an id). Taking the example of letting a user check their inbox status, you might provide an empty to hold the data and a link to gather the data and update the page: Unknown <%= link_to_remote 'Check Status...', :url => {:action => 'get_inbox_status', :user_id => @user.id}, :update => 'inbox_status' %>
In the example, the text of the link will be Check Status..., which will call the get_inbox_status method of the current controller, passing along the current user’s id. The results will be injected into the inbox_status . Report erratum this copy is (P1.0 printing, March 2009)
574
P ROTOTYPE
All of the common options we covered earlier are available for link_to_remote. Look at this more detailed example: Unknown <%= link_to_remote 'Check Status...', :url => {:action => 'get_inbox_status', :user_id => @user.id}, :update => 'inbox_status', :condition => "$('inbox_status').innerHTML == 'Unknown'" , :before => "Element.show('progress_indicator')" , :complete => "Element.hide('progress_indicator')" %>
This version will fire the XHR request only if the current value of the target element is "Unknown", thus preventing the user from requesting the data twice. It uses the :before and :complete options to turn on and off progress indication.
periodically_call_remote Instead of relying on the user to make the remote call, you might want to call the server at regular intervals to check for changes. For example, in a webbased chat application, you would want to ask the server every few seconds whether a new chat message had arrived. This is a common way to supply distributed status checking and is a stand-in for a real “push” communication technology. The periodically_call_remote method takes care of this for you. It works almost exactly like link_to_remote, except instead of taking a string value to use as the link text, it takes an interval value that tells it how long to go between posts to the server. Let’s modify the previous example to show the user’s inbox status every sixty seconds: Unknown <%= periodically_call_remote :url => {:action => 'get_inbox_status', :user_id => @user.id}, :update => 'inbox_status', :frequency => 60, :condition => "$('inbox_status').innerHTML == 'Unknown'" , :before => "Element.show('progress_indicator')" , :complete => "Element.hide('progress_indicator')" %>
periodically_call_remote takes the same options as link_to_remote (as well as the
option :frequency). This means that you could provide a value for the :confirm option. Be very careful here. Not only will a modal dialog box pop up asking the user to approve an otherwise completely transparent event, but while the dialog box is onscreen, the timer managing periodically_call_remote is still ticking and firing off the confirmation requests. This means that you could easily get in a situation where the confirmation dialog boxes are piling up and every time you click OK or Cancel the dialog box disappears only to be immediately replaced with another.
Report erratum this copy is (P1.0 printing, March 2009)
575
P ROTOTYPE
link_to_function Although not technically a Prototype helper, link_to_function is a commonly used Ajax-enabling helper from the standard Rails helper libraries. It lets you provide the link text and a snippet of JavaScript to execute when the link is clicked. It does not accept all the fancy options we looked at earlier; instead, you can pass any of the various HTML options accepted by the more standard link_to helper. link_to_function lets you create arbitrary links to invoke client-side functions. The JavaScript need not be relegated to client-side activity only, though. You can provide a JavaScript snippet that invokes XHR as well. This helper (and its act-a-like cousin button_to_function) is for creating more customized interaction models than can be expressed through the common Prototype helpers and options.
For example, you may be using the excellent Prototype Window Class framework by Sébastien Gruhier (http://prototype-window.xilinus.com/). Built on top of Prototype and Script.aculo.us, this framework lets you create JavaScript-only windows inside your application. You might want to create a link that launches a Prototype window to display the About information for your application: <%= link_to_function "About..." , "Dialog.alert({url: 'about.html', options: {method: 'get'}}, {windowParameters: {className: 'default'}, okLabel: 'Close'});" %>
remote_function It turns out that the Prototype helpers described previously all use another Prototype helper, remote_function, to actually generate the XHR call. You can use this helper yourself if you want to embed XHR calls in other contexts besides links and periodical executors. Let’s say that your users have checked the status of their inbox and want to look at the messages. A standard interface might be to display a list of message subjects and then allow the user to select one to view. However, you know your users are used to thick-client mail interfaces, and the standard interaction is to double-click the e-mail subject to view the message. You want to provide the same functionality, but you need to make an XHR call to the server to fetch the specific e-mail. This example is the partial you might use to render the list: <% for email in @emails %> <%= email.id %> | <%= email.body %> | <% end %> Report erratum this copy is (P1.0 printing, March 2009)
576
P ROTOTYPE
This injects the JavaScript code needed to make the XHR call, harvest the response, and replace the contents of email_body. remote_function accepts all the standard options described earlier.
observe_field The first example in this chapter shows the use of observe_field. In general, this helper binds a remote_function to the onchange event of a target field, with all the same implications and options for other types of remote functions.
observe_form Sometimes, you aren’t just interested in changes to one specific field. Instead, you’re monitoring changes in any of a group of related fields. The best way to handle this is not to invoke individual observe_field helpers for each field but instead to wrap those fields in a |