Usage Documentation

Applying Behaviours To Elements Using CSS

The standard (and recommended) way to apply behaviours to page elements is via apply_behaviour and apply_behavours.

apply_behaviour(css_selector, javascript, options={})

The first argument of apply_behaviours is an event:Selectors style selector that specifies both the CSS selector for the elements to target and the event to attach the behaviour to in this format: css_selector:event

The second argument is the behavior to apply. Pass a string to specify the JavaScript code to execute directly. There are two variables available to the behaviour JavaScript. In the JavaScript code, this refers to the triggering element and event refers to the JavaScript event object.

If you omit the event type from the selector the behaviour will be executed as soon as the element is loaded. Here are some examples of the usage of apply_behaviours:

apply_behavior 'a.help:click', 'Help.open(this.href)'
# Notice the use of this.href to get the href attribute of the triggering element.

apply_behaviour '#comment_form:submit', 'return validate(this)'
# You can return false to stop the default action (in this case submitting the form).

apply_behaviour 'div.draggable', 'new Draggable(this)'
# Here the event is omitted from the selector so the code is executed as soon as 
# the element is loaded.

apply_behaviour(css_selector, options={}, &rjs_block)

As well as specifying the behaviour as a JavaScript string you can use a block to write RJS-style code. The block takes three optional arguments, page (which works the same as page in RJS templates), element and event. The event object is passed so you can call event.stop to prevent the default behaviour of the event:

apply_behaviour '.list_item:dblclick' do |page, element, event|
  element.replace_html "Deleted." 
  event.stop
end

Available Options

The apply_behaviour methods can both take an options hash. Currently, the options available are:

  • :external – determines whether the javascript should be sent to the external behaviours js file or not. The default is true.
  • :prevent_default – when this is set to true the default behaviour of an element will be cancelled automatically – for instance, stopping a link from being followed or a form from being submitted.

Applying Multiple Behaviours

As a shorthand syntax for applying a group of behaviours, UJS For Rails provides apply_behaviours.

apply_behaviours(&on_block)

The syntax for apply_behaviours is simple and CSS-like. You pass a block containing calls to the on method which takes the same arguments as apply_behaviour:

apply_behaviours {
  on 'a:mouseover' { |page, element| element.visual_effect :highlight }
  on 'a:click', 'alert("You clicked me!")'
}

This is really useful for specifying reusable groups of behaviours that you can write as helpers:

# Output a text field with attached JS date selector
def date_input(name, value)
  apply_behaviours {
    on 'input.date_input:click', 'Calendar.show(this)'
    on 'input.date_input:change', 'Calendar.update(this)'
  }
  text_field_tag name, value, :class => 'date_input'
end

Using The Behaviour Helpers

RJS For Rails includes a suite of helper methods that generate behaviours that you can plug in to apply_behaviour. These helper methods make it much easier to implement Scriptaculous features such as drag and drop, and sortable elements. It’s easy to write your own too. Notice that when using the behaviour helpers you don’t need to specify an event, just the CSS selector.

make_remote_link(options={})

This is the unobtrusive equivalent to link_to_remote and as such allows you to create links that trigger Ajax requests. The options available are identical to link_to_remote with one difference. If you don’t specify the :url option the URL of the Ajax call defaults to the href attribute of the assigned element.

apply_behaviour 'a.add_comment', make_remote_link( :update => 'new_comment' )

make_remote_form(options={})

This is the unobtrusive equivalent to remote_form and makes forms submit via Ajax. The options available are identical to remote_form except if you don’t specify the :url option the URL of the Ajax call defaults to the action attribute of the form.

apply_behaviour 'form', make_remote_form

make_observed(type, options={})

Creates an observer for each of the selected elements, of the type specified (which can be :field or :form). The options available are the same as observe_form and observe_field.

apply_behaviour 'input.uri_slug', make_observed(
  :field, 
  :onChange => 'alert("changed!")'
)

make_sortable(options={})

Makes the children of the selected elements sortable. The options available are identical to those of sortable_element.

make_draggable(options={})

Makes the selected elements draggable. The options available are identical to those of draggable_element.

make_drop_receiving(options={})

Makes the selected elements drop targets. The options available are identical to those of drop_receiving_element.

apply_behaviours {
  on 'ul.wishlist', make_sortable
  on 'div.product', make_draggable( :revert => true )
  on '#shopping_baskit', make_drop_receiving ( :url => { :action => 'add' } )
}

Using Rails JavaScript Helpers Unobtrusively

UJS For Rails adapts the JavaScript, JavaScript Macro, Prototype and Scriptaculous helpers so they can be used unobtrusively. Just use them as normal but instead of the JavaScript being inserted directly into the HTML, a DOM id is automatically generated (if the element doesn’t already have one) and the script is attached via the external behaviour file. This is good as an initial step in cleaning up the JavaScript in your views and does allow you to take advantage of script caching to improve the download sizes of your pages. This is not however the sum total of unobtrusive scripting. In order to implement true unobtrusive scripting a more layered approach to the design of the UI must be taken but this will be covered in future articles. In the meantime, for an introduction to unobtrusive scripting try Jeremy Keith’s Behavioural Separation over at A List Apart.

Caching Behaviour Scripts

UJS For Rails gives you a certain level of caching for free by means of the If-None-Modified and Etag HTTP headers by monitoring the behaviours on a page and only sending a new behaviour JavaScript file if it has changed since the users last view. You don’t need to do anything to enable this form of caching or worry about expiring behaviours.

However, if your behaviours change very infrequently you can cache your behaviour JavaScript to the file system in the same style as page caching.

caches_behaviour(*actions)

RJS For Rails provides caches_behaviour which is a class method of ActionController::Base and works in the same way as caches_page. Just specify one or more actions whose behaviour you want to cache.

expire_behaviour(url_options={})

Use expire_behaviour in the same way as expire_page to remove cached behaviours from the file system.

class ForumController < ApplicationController
  caches_behaviour :list, :thread

  def new_post
    expire_behaviour :action => 'list'
    # more code here...
  end
end

Cached pages and action automatically cache and expire their associated behaviours.

Limitations

As UJS For Rails uses the session to store behaviour information between requests all pages using the plugin must have the session enabled.

Note On Method Spellings

We (the authors) are British and as a result have implemented the methods with the British English spelling of behaviour. However we realise that many developers will want to use the American English spelling so we’ve alias all methods with the american spelling of behaviour so apply_behavior, caches_behavior and the other equivalents will work fine.

Return to home page