.rjs and link_to_function 3

Posted by Daniel Wanja Thu, 12 Jan 2006 05:57:00 GMT

A neat little trick is that .rjs templates can be used to generate local javascript functions and be invoked without doing a server roundtrip.

playground_controller.rb
class PlaygroundController < ApplicationController
  def rjs
     response.headers['content-type'] = 'text/html'
  end
end
rjs.rhtml
<html>
<head>
  <%= javascript_include_tag :defaults %>    
</head>
<body>
<h1 id='header'>Javascript function test</h1>

<%= link_to_function('Add', 'add_item()' ) -%> | 
<%= link_to_function('Clear', 'clear_list()') %>
    <ul id='list' />
<script type='text/javascript'>
  <%= render :partial => 'functions', :type => 'rjs' %>
</script>
    <script type='text/javascript'>
    <%= # Note: following javascript is run when the page is loaded.
        update_page do |page|
            3.times { page.call 'add_item' }
        end
    %>
    </script>    
</body>
</html>

The rjs method in the PlaygroundController set’s the content-type as we perform a render of an rjs from within a .rhtml and this seems to change the content-type, so we need to reset it.

_function.rjs
page << 'function add_item() {'
    page.insert_html :bottom, 'list', content_tag('li', 'item', :id => 'list_item' )
    page.visual_effect :highlight, 'list', :duration => 3
page << '}'

page << 'function clear_list() {'
    page.replace_html :list, ""
    page.visual_effect :highlight, 'list', :duration => 3
page << '}'

In the partial _function.rjs we insert the function declaration before writing to the page object. This allows us to invoke the add_item _ and clear_list _ methods using the link_to_function _ from in the .rhtml file. Note also in the .rhtml file we invoke directly the update_page method to insert three calls to add_item().

The generated html files looks like this

<html>
<head>
  <script src="/javascripts/prototype.js" type="text/javascript"></script>
<script src="/javascripts/effects.js" type="text/javascript"></script>
<script src="/javascripts/dragdrop.js" type="text/javascript"></script>
<script src="/javascripts/controls.js" type="text/javascript"></script>    
</head>
<body>
<h1 id='header'>Javascript function test</h1>

<a href="#" onclick="add_item(); return false;">Add</a> | 
<a href="#" onclick="clear_list(); return false;">Clear</a>
    <ul id='list' />
<script type='text/javascript'>
  function add_item() {
new Insertion.Bottom("list", "<li id=\"list_item\">item</li>");
new Effect.Highlight('list',{duration:3});
}
function clear_list() {
Element.update("list", "");
new Effect.Highlight('list',{duration:3});
}
</script>
    <script type='text/javascript'>
    add_item();
        add_item();
        add_item();
    </script>    
</body>
</html>
Comments

Leave a response

  1. Tommy Fri, 31 Mar 2006 15:54:16 GMT
    Thanks a lot for posting this. This helped me get started with RJS. I'd like to use this technique to add multiple select boxes to a form and I'd like to be able to pass a variable to the rendered javascript. For example, add_select(index, var) ... select(:date, :day, :index= index) ... hidden_field(:foo, :bar, :index= index, :value=var) } is this possible? When I try to pass the variable, rails won't render the page and says index and var don't exist.
  2. daniel wanja Fri, 31 Mar 2006 21:42:49 GMT
    As you see in this article the add_item function defined in the _function.rjs doesn't take a parameter. If I understand well your question is how to pass a 'javascript' parameter to this function that can be referenced with the the rjs statements, thus allowing to write pretty powerful javascript functions by only using rjs. Like you, I am not sure that this is possible witht the current implementation of the rjs functionality, besides writting the whole function using the page http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper/JavaScriptGenerator/GeneratorMethods.html for some more information.
  3. john@venuesoftware.com Mon, 21 Apr 2008 21:30:12 GMT

    DONT USE BLACK BACKGROUNDS! Making things difficult to read is not useful!

Comments