Screencasts

Building a Simple AJAX Website with Sinatra & jQuery

Download Files ↓

Show Notes

To mark AJAX's birthday on 18th March, we've put together a screencast to show you how to create your very own AJAX-updating countdown website for the big day.

We're using Haml, Sinatra and jQuery to do this and recommend you look at our introduction videos if you're not familiar with any of these languages or frameworks.

Links

What you'll learn

  • How to build your own updating "Is it" website
  • How to determine in Sinatra if a request is an XMLHttpRequest or not
  • How to disable layouts on XHR requests in Sinatra

Script

Welcome to a special Screencasts.org episode. March 18th marks the anniversary for when Internet Explorer 5 was released. Included in that release was the formative version of the XMLHttpRequest API. In other words, on March 18th, it's AJAX's birthday! And what better way to celebrate than by building a website that uses AJAX to tell us if it's AJAX's birthday or not!

In this episode we'll be using Sinatra, Haml and jQuery. If you're new to any of these, we recommend you check out our introduction screencasts on these topics on Screencasts.org. They'll get you up to speed.

"Is It" Websites

You may have come across this genre of website before. They're simple websites with a "Yes" or a "No" in the middle of the page. They answer a question like "Is it Christmas?", "Is it November?" or some other time-sensitive question. Sometimes the pages also have a countdown timer.

In this episode we're going to create isitajaxsbirthday.com with a countdown timer.

Building an "Is It" website

Below this video is a zip file with the beginnings of our Sinatra application in app.rb, with an empty get route for the root URL. You'll notice it requires 'birthday_countdown'.

require 'sinatra'
require 'birthday_countdown'

get '/' do

end 

If we look in BirthdayCountdown', we have several methods, but we're only going to be using the constructor,isit?andseconds_to_go`. All the other methods are there to help these three methods, and are there for readability.

The constructor takes in two arguments, month and day, which get cached as @birthday_month and @birthday_day. Also, for convenience, instead of repeating Time.now all the time, we cache @month, @day and @year for the current date.

...
# Cache @month, @day and @year on initialization
def initialize(month, day)
  @birthday_month = month
  @birthday_day = day
    
  # Current date
  @month = Time.now.month
  @day = Time.now.day
  @year = Time.now.year    
end
...

In the isit? method ,we make sure the current month and birthday month match as well as the current day and birthday day.

...
# Is it birthday?
def isit?
  @month == @birthday_month && @day == @birthday_day
end
...

The seconds_to_go method returns an integer of how many seconds we've got left until we celebrate. It uses one of the helper methods called next_birthday to help us do that.

...
# For the countdown
def seconds_to_go
  next_birthday.to_i - Time.now.to_i
end
...

Examining our downloaded files further, we have a layout and two views: One for when it's AJAX's birthday, and one for when it's not.

In our layout, we've included jQuery already, and left some space to write our jQuery code.

OK so let's add some logic to our root URL block to show either the :yes or the :no view.

So let's initialize a BirthdayCountdown instance by passing it 3, 18 for the month and day.

require 'sinatra'
require 'birthday_countdown'

get '/' do
   @countdown = BirthdayCountdown.new(3,18)

end 

Now for the view. We need to pass in either :yes or :no. Let's implement a method within BirthdayCountdown called to_view.

If it is the birthday, let's return :yes and :no if it's not.

# Returns the view needed for Sinatra to present
def to_view
    isit? ? :yes : :no
end

Here we're using the ternary operator to reduce lines of code. This is a shorthand way of writing an if and else statement. The first value will be returned if the condition is true, and the second if it's false. This is also known as an inline if or conditional operator.

Now in our app.rb, in our get route, we can include haml @countdown.to_view.

require 'sinatra'
require 'birthday_countdown'

get '/' do
   @countdown = BirthdayCountdown.new(3,18)
    haml @countdown.to_view
end 

Let's start up our application by typing ruby -rubygems app.rb, which will automatically include rubygems. Then, let's visit http://localhost:4567 in our browser and we'll see that the code works: Since today isn't March 18th, it says "No".

As you can see from the downloaded code, there's a countdown at the bottom of our no view. It's static at the moment, so let's write some jQuery to check if it's AJAX's birthday every second, because we just can't wait! We want to see those seconds count down!

Under the Haml :javascript filter, we can write our JavaScript. Since we're including this code in the head of the document, we need to trigger some code on ready. Let's use the shorthand $(). Usually your ready function is going to be an anonymous function containing the code you want to execute. But in this case, we're going to be doing the same thing on ready that we want to do every second, so we'll pass in the name of our function, getUpdate, instead of writing an anonymous function.

So let's create this getUpdate() function, and inside it, let's load the contents of the root path into the $("body") element. Then let's set a timeout of 1000 milliseconds, or 1 second, to call the getUpdate method.

$(getUpdate);
function getUpdate(){
  $("body").load("/");
  setTimeout(getUpdate,1000);
}

If we refresh our browser window, we'll see the timer update. And that's it we're all done!— Well almost.

If we look in the Resources tab of the Web Inspector we see that the full page, layout and view, is sent by Sinatra when requested by the AJAX call. This may have some unwanted side effects down the road. All we want to do is send the view with no layout. To solve this we need to switch off the layout when the request is an XHR request. Sinatra allows you to query the request to see if it's an XHR request by calling .xhr? on the request object.

Sinatra allows you to turn off or specify layout files. This is done by setting the :layout option: false to disable the layout, or you can pass in the name of the layout as a symbol to enable it. In our case, our layout is named layout.haml so we set the :layout option to :layout.

require 'sinatra'
require 'birthday_countdown'

get '/' do
    @countdown = BirthdayCountdown.new(3, 18)
    haml @countdown.to_view, :layout => (request.xhr? ? false : :layout)
end 

OK let's restart our Sinatra app, and go back to our Web Inspector. Now, we can see all the new requests only have the view part of the markup. Great.

And that's it!

We're going to post this site up at isitajaxsbirthday.com. Feel free to share it on the rub up to AJAX's birthday.

Happy Birthday AJAX! And here's to another year of developing awesome dynamic websites!

Thanks for watching! Subscribe to our RSS feed, follow us on Twitter, and please leave any questions, comments or suggestions for new screencasts in the comments below. If you like our videos, and think your friends, followers or colleagues would benefit from seeing them, please feel free share via any of the links below the video. We really appreciate your support.

See you next time!

← Latest Episodes

blog comments powered by Disqus