Emergent Web Technologies Spring 2009 Class 9

esse quam videri
Jump to: navigation, search

Introduction

We already talked about getting remote data with JavaScript using JSONp and jQuery, but, until now, we haven't been able to use Ajax. Now that we can create simple sites with Ruby on Rails I'll cover how to write some simple Ajax code to make your pages more dynamic.

Activity 1

With this activity we'll take a regular scaffolded Rails site and add a little bit of Ajax. The idea is that the site is designed to work without Ajax, but if the user has JavaScript enabled, we can make it a little bit more dynamic.

1. Open Instant Rails and the Ruby console window

2. Generate a new Rails site

 rails ajax

3. Navigate to the new rails site and create the scaffold for a simple locations database

 cd ajax
 ruby script/generate scaffold Location name:string address:string city:string state:string zip:string
rake db:migrate

4. Make sure that your site works by starting the server

ruby script/server

And then open the link to your site http://localhost:3000/locations

5. Create a new location using your site and then go back to the site index.

Notice that you can click around on the urls to view the location, edit it and delete it. We can use Ajax to enhance the site so that you won't need to reload the page every time you want to move around the site.

Note: this is meant to demonstrate Ajax more than it is to demonstrate good user interface design. In real life, some of the Ajax used here might not be the best way of designing things.

6. The first thing we can do is modify the page so that we don't need to reload to view a location. We can just view it on the same page as the locations index.

Open up the location index view at

 /app/views/locations/index.html.erb

7. Add a new div to the bottom of the page where we can show the preview content

 <div id="preview-div">
 </div>

And modify the show link to add a new class that will we target with JavaScript

 <%= link_to 'Show', location, :class => 'show-link' %>

8. We're going to be using jQuery for Ajax calls, so you'll need to download it here

I usually modify the name of the file so it's just called jquery.js. You can modify the file name if you want.

9. Once you have the file downloaded you'll need to put it in the following directory

 /public/javascripts

The public folder is where files that aren't part of your Rails application be created and accessed.

10. Go back to your view page and add the following line to the top of the page

 <%= javascript_include_tag "jquery" %>

The javascript_include_tag helper function will automatically include the jquery.js file from the javascripts folder (convention over configuration).

Reload your page and look at the source to make sure that your JavaScript is being included.

11. Now we can finally create the JavaScript to add some Ajax to our page. Create a new file for the JavaScript at

 /public/javascripts/show.js

And add the following code to it

var Show =
{
   init: function()
   {
       jQuery('.show-link').click(function(event)
       {
           event.preventDefault();
           Show.load(this.href);
       });
   },
   
   load: function(url)
   {
       jQuery.ajax(
       {
           url: url,
           success: function(html)
           {
               jQuery('#preview-div').html(html);
           }
       });
   }
};

jQuery(Show.init);

The Show object contains a couple utility functions for adding Ajax to our page.

The init function finds any links that have have a class name "show-link" and adds a click handler to them. The click handler prevents the link from being followed and instead calls the Show.load function and passes the url of the link to it.

The load function uses jQuery's ajax function to make an Ajax call to the link's url. If the call succeeds, an anonymous function is called that fills the preview div with the content that came back from the Ajax call.

12. To get this script to load on your index page, you'll need to include it. So modify the javascript_include_tag call so it's loading jQuery and the show library

 <%= javascript_include_tag "jquery", "show" %>

13. Reload your index page in the browser and click on the show link. Instead of taking you to another page, the show link should load in the content for the location in the preview div.

If you open up the Firebug console you should be able to see the Ajax calls as they go by.

Activity 2

Let's add some more changes to the locations page we created by adding an Ajax powered delete button.

For the delete button on your index page, Rails already adds some JavaScript to delete the entry. So you don't have to worry about the item getting deleted with a GET request, because only the JavaScript function will delete it. But the JavaScript is added inline and we don't have any control over what it looks like. We'll create our own JavaScript for deleting an entry.

1. Modify the "Destroy" link by removing the extra Rails parameters and adding a class name that we can target

 <%= link_to 'Destroy', location, :class => "delete-button" %>

2. Create a JavaScript file located at

 /public/javascripts/delete.js

And add the following code to it

var Delete =
{
   init: function()
   {
       jQuery('.delete-button').click(function(event)
       {
           event.preventDefault();
           
           var link = this;
           Delete.location(link);
       });
   },
   
   location: function(url)
   {
       jQuery.ajax(
       {
           url: url,
           type: "DELETE"
       });
   }
};

jQuery(Delete.init);

This script is similar to the show script. It's an object called Delete that contains some utility functions for deleting a location.

The Delete.init function adds a click handler to any links that have a class "delete-button" and prevents the links from being followed when clicked. Then it passes the link that was clicked on to the Delete.location function.

The Delete.location function makes an Ajax call to the url that was clicked, but this time uses DELETE instead of GET. Rails has already set up a controller action called destroy automatically gets called when you send a DELETE request to an item.

3. Include the JavaScript by modifying the javascript_include_tag again

 <%= javascript_include_tag "jquery", "show", "delete" %>

4. Reload your page and click the Destroy click. If everything goes well, it should look like nothing happened. But if you check the Firebug console, you should see a DELETE request that was made to link for the location.

If you reload the index page, the location should be gone.

5. Everything technically works at this point, but it's not very friendly for the user. Let's add a callback function that will remove the deleted location from the page once it has been successfully deleted.

You'll need to modify the JavaScript in your delete.js file. Change it to look like this

 var Delete =
 {
   init: function()
   {
       jQuery('.delete-button').click(function(event)
       {
           event.preventDefault();
           
           var link = this;
           Delete.location(link, function()
           {
               jQuery(link).closest('tr').fadeOut();
           });
       });
   },
   
   location: function(url, callback)
   {
       jQuery.ajax(
       {
           url: url,
           type: "DELETE",
           success: callback
       });
   }
 };
 
 jQuery(Delete.init);

This Delete.location function now takes in a callback function. We pass that callback function on to the Ajax call. If the Ajax call was successful, the callback function will be called automatically.

If you look at the call to the Delete.location function from the Delete.init function you can see that we're passing in an anonymous function that will be used as the callback. The anonymous function uses jQuery's closest function to find the closest table row to the link that was clicked and then fades it out.

6. Add a new location and go back to the index page. Click the destroy button again. This time, you should see the item you click on fade away after it has been deleted.