Today we are going to create an iOS-like home screen using CoffeeScript – a new JavaScript based language, and the jQuery library. CoffeScript has a clean syntax that lies somewhere in between Ruby and Python. If you haven’t used any of them, don’t worry – it is not required. However you will need to be familiar with JavaScript so you can better understand the concepts behind the language.
We are also going to use the Touchable plugin, so we can listen for touch-based events.
First, what is CoffeeScript?
CoffeeScript is a neat programming language meant to enhance the good parts of JavaScript, while working around the not so good. It makes OOP easy and introduces a number of useful additions such as comprehensions, new syntax for functions and scope handling, along with numerous small improvements.
CoffeeScript works in every browser out there, and is compatible with all your existing JavaScript code (including libraries like jQuery and plugins). But how does this work if it is a different language? Simple –CoffeeScript compiles down to JavaScript, so it works in any browser that supports it.
Before you start following this tutorial, I would suggest that you read through the examples on theCoffeeScript website (be sure to check out the “Try CoffeeScript” tab), and The Little Book on CoffeeScriptfor an introduction to the language.

iOS -like Home Screen with CoffeeScript
The HTML
index.html
> <script type="text/javascript" src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <section id="homeScreen"> <div id="mask"> <div id="allScreens"></div> </div> <div id="dock"></div> </section> <!-- JavaScript includes --><script type="text/javascript" src="http://code.jquery.com/jquery-1.6.3.min.js"></script> <script type="text/javascript" src="assets/js/touchable.js"></script><script type="text/javascript" src="assets/js/coffee-script.js"></script> <script type="text/javascript">// <![CDATA[ # Our Code Goes Here // ]]></script>
overflow:hidden to show only one screen at the time. The #allScreens div inside it, as the name suggests, contains all the dynamically generated .screen divs with icons.
<script type="text/coffeescript"> tags on the page, which is where we will be writing our code.The CoffeScript Code
# The Icon class.
class Icon
# The constructor. The -> arrow signifies
# a function definition.
constructor: (@id, @title) ->
# @ is synonymous for "this". The id and title parameters
# of the constructor are automatically added as this.id and this.title
# @markup holds the HTML of the icon. It is
# transformed to this.markup behind the scenes.
@markup = "</pre>
<div class="icon" style="background-image: url('assets/img/icons/#{@id}.png');" title="#{@title}"></div>
<pre>
# The DockIcon class inherits from Icon
class DockIcon extends Icon
constructor: (id, title)->
# This calls the constructor if Icon
super(id, title)
# Changing the class name of the generated HTML
@markup = @markup.replace("class='icon'","class='dockicon'")
Using super() will call Icon’s constructor and initialize the markup property. We only need to replace the class name.
We will divide the home screen in individual .screen divs, each holding their own set of icons. Here is the class for that:
# The Screen Class
class Screen
# Function arguments can have default values
constructor: (icons = [])->
@icons = icons
attachIcons: (icons = [])->
Array.prototype.push.apply(@icons, icons)
generate: ->
markup = []
# Looping through the @icons array
markup.push(icon.markup) for icon in @icons
# The last line of every function is implicitly returned
"<div class='screen'>#{markup.join('')}</div>"

The iOS Dock
class Stage
# The width of our "device" screen. This is
# basically the width of the #mask div.
screenWidth: 332
constructor: (icons)->
@currentScreen = 0
@screens = []
# Calculating the number of screens
# necessary to display all the icons
num = Math.ceil(icons.length / 9)
i = 0
while num--
# we pass a slice of the icons array
s = new Screen(icons[i...i+9])
# adding the screen to the local screens array
@screens.push(s)
i+=9
# This method populates the passed element with HTML
addScreensTo: (element)->
# We are using the jQuery library from within CS:
@element = $(element)
@element.width(@screens.length*@screenWidth)
for screen in @screens
@element.append(screen.generate())
addIndicatorsTo: (elem)->
# This method creates the small circular
# indicators. Also using jQuery
@ul = $(elem)
for screen in @screens
@ul.append('<li>')
@ul.find('li:first').addClass('active');
# ... More methods go here ...
The Stage takes an array of icons in the constructor. It then calculates how many screens will be needed, and creates an object for each one, passing it a slice of the icons array.
We now have the markup of all these elements on the page, but we are still missing the methods that control the transition between the slides. You can see them below (still part of the Stage class):
goTo: (screenNum)->
# This method animates the allScreen div in
# order to expose the needed screen in #mask
if @element.is(':animated')
return false
# if this is the first or last screen,
# run the end of scroll animation
if @currentScreen == screenNum
# Parallel assignment:
[from, to] = ['+=15','-=15']
if @currentScreen != 0
[from, to] = [to, from]
# Tell the user there aren't any more screens:
@element.animate( { marginLeft : from }, 150 )
.animate( { marginLeft : to }, 150 )
else
# If everything is ok, animate the transition between the screens.
# The fat arrow => is a function that preserves the context of "this"
@element.animate( { marginLeft:-screenNum*@screenWidth }, => @currentScreen = screenNum )
@ul.find('li').removeClass('active').eq(screenNum).addClass('active');
next: ->
toShow = @currentScreen+1
# If there is no next screen, show
# the last one
if toShow == @screens.length
toShow = @screens.length - 1
@goTo(toShow)
previous: ->
toShow = @currentScreen-1
# If there is no previous screen,
# show the first one
if toShow == -1
toShow = 0
@goTo(toShow)
Both the next() and previous() methods call goTo() internally, passing a screen number (starting from zero). The goTo() method animates the #allScreen div to show the needed screen.
All we need to do now is bind a function to the document.ready event. For this we will use jQuery .
# This is equivalent to $(function(){}):
$ ->
# You can skip the comma if it's on the end of a line:
allIcons = [
new Icon('Photos', 'Photo Gallery'), new Icon('Maps', 'Google Maps')
new Icon('Chuzzle', 'Chuzzle'), new Icon('Safari', 'Safari')
new Icon('Weather', 'Weather'), new Icon('nes', 'NES Emulator')
new Icon('Calendar', 'Calendar'), new Icon('Clock', 'Clock')
new Icon('BossPrefs', 'Boss Prefs'), new Icon('Chess', 'Chess')
new Icon('Mail', 'Mail'), new Icon('Phone', 'Phone')
new Icon('SMS', 'SMS Center'), new Icon('Camera', 'Camera')
new Icon('iPod', 'iPod'), new Icon('Calculator', 'Calculator')
new Icon('Music', 'Music'), new Icon('Poof', 'Poof')
new Icon('Settings', 'Settings'), new Icon('YouTube', 'Youtube')
new Icon('psx4all', 'PSx4All'), new Icon('VideoRecorder', 'Record Video')
new Icon('Installer', 'Installer'), new Icon('Notes', 'Notes')
new Icon('RagingThunder', 'RagingThunder'), new Icon('Stocks', 'Stocks')
new Icon('genesis4iphone', 'Genesis'), new Icon('snes4iphone', 'SNES Emulator')
new Icon('Calendar', 'Calendar'), new Icon('Clock', 'Clock')
new Icon('Photos', 'Photo Gallery'), new Icon('Maps', 'Google Maps')
]
dockIcons = [
new DockIcon('Camera', 'Camera')
new DockIcon('iPod', 'iPod')
new DockIcon('Calculator', 'Calculator')
]
allScreens = $('#allScreens')
# Using the Touchable plugin to listen for
# touch based events:
allScreens.Touchable();
# Creating a new stage object
stage = new Stage(allIcons)
stage.addScreensTo(allScreens)
stage.addIndicatorsTo('#indicators')
# Listening for the touchablemove event.
# Notice the callback function. Braces on
# function calls are optional
allScreens.bind 'touchablemove', (e,touch)->
stage.next() if touch.currentDelta.x < -5
stage.previous() if touch.currentDelta.x > 5
# Adding the dock icons:
dock = $('#dock')
for icon in dockIcons
dock.append(icon.markup)
By calling the Touchable method we are extending the element to support several touch based events. Among them is touchablemove, which is executed when the user moves his finger across the screen. It is also called when we drag with the mouse. Further down, when we bind for that event, we get a touchobject as the second argument of the callback function. It holds the delta, or difference, from the beginning of the movement.
With this our iOS-like Home Screen is complete!
Conclusion
CoffeeScript is an interesting language that can make developing in the browser easier. You can expect to write up to 50% less code comparing to pure JavaScript.
But don’t fall pray to the hype surrounding it just yet – CoffeeScript isn’t going to replace JavaScript any time soon, as it sacrifices some of the agility that JS provides in attempt to make development easier. The CS way might not be the best fit for your project.
CoffeeScript also introduces an extra compilation step that separates you from deploying your code, but this can be solved by web frameworks that compile the code for you as is the case with Rails, where CS became a default.

