1. Web Development with
Sass and CoffeeScript
Brian P. Hogan
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
2. Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
3. What about you?
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
4. Web pages run on CSS
and JavaScript
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
5. CSS feels limited
and repetitive
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
6. and many people don’t
really understand
JavaScript
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
7. Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
8. We need to use
better tools to build
modern web apps.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
9. CoffeeScript lets us
write complex JS with
simpler syntax.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
10. Sass gives us
extensions to CSS.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
11. Sass + CoffeeScript +
automated workflow
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
13. It’s more of a new
syntax than a new
language.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
14. Some jQuery
$(function() {
$("a#get").click(function(e) {
.get("/ajax/get",
{name: "John",time: "2pm"},
function(data) {
$("#result").html(data);
}
);
});
});
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
15. in CoffeeScript
$ ->
$("a#get").click (e) ->
$.get "/ajax/get",
{name: "John", time: "2pm"},
(data) ->
$("#result").html(data)
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
16. CoffeeScript borrows
from Python and Ruby
syntax.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
17. CoffeeScript uses
significant whitespace
for scope.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
18. CoffeeScript compiles
to regular, plain old
JavaScript.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
19. Declaring variables and objects
var box, colors, firstName, lastName;
firstName = "Homer" firstName = "Homer";
lastName = "Simpson" lastName = "Simpson";
colors = ["Green", "Blue", "Red"] colors = ["Green", "Blue", "Red"];
box = box = {
height: 40 height: 40,
width: 60 width: 60,
color: red color: red
};
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
20. JavaScript functions
// function declaration. Visible anywhere (hoisting)
(function hello(name){
alert("Hello " + name + "!");
}
// function expression, visible to the scope of the var
var hello = function(name){
alert("Hello " + name + "!");
}
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
21. Function declaration in CoffeeScript
hello ->
alert "Hello"
hello (name) ->
alert "Hello #{name}"
-> (thin arrow)
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
22. CoffeeScript uses function expressions.
hello (name) ->
alert "Hello #{name}!"
var hello = function(name){
alert("Hello " + name + "!");
}
#{} interpolates strings.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
23. New syntax
means new features.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
24. a jQuery example
$(function() {
var displayError, displaySuccess, url;
$("form").submit(function(event) {});
event.preventDefault();
url = $(this).attr("href");
$.ajax({
url: url + ".js",
success: function(data, status, xhr) {
displaySuccess($("#form"));
},
error: function(xhr, status, error) {
displayError(error);
}
});
displaySuccess = function(form) {
var element;
element = $("<p>Thanks for signing up!").addClass("success");
element.insertAfter(form);
form.hide();
};
displayError = function(error) {
$("#notice").attr("html", error);
};
});
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
25. jQuery $(function(){})
$ ->
$("form").submit (event) ->
event.preventDefault()
url = $(this).attr "href"
$.ajax
url: url + ".js"
success: (data, status, xhr) ->
displaySuccess($("form"))
error: (xhr, status, error) ->
displayError error
displaySuccess = (form) ->
element = $("<p>Thanks for signing up!").addClass("success")
element.insertAfter form
form.hide()
displayError = (error) ->
$("#notice").attr "html", error
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
26. jQuery event handler
$ ->
$("form").submit (event) ->
event.preventDefault()
url = $(this).attr "href"
$.ajax
url: url + ".js"
success: (data, status, xhr) ->
displaySuccess($("form"))
error: (xhr, status, error) ->
displayError error
displaySuccess = (form) ->
element = $("<p>Thanks for signing up!").addClass("success")
element.insertAfter form
form.hide()
displayError = (error) ->
$("#notice").attr "html", error
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
27. jQuery $.ajax
$ ->
$("form").submit (event) ->
event.preventDefault()
url = $(this).attr "href"
$.ajax
url: url + ".js"
success: (data, status, xhr) ->
displaySuccess($("form"))
error: (xhr, status, error) ->
displayError error
displaySuccess = (form) ->
element = $("<p>Thanks for signing up!").addClass("success")
element.insertAfter form
form.hide()
displayError = (error) ->
$("#notice").attr "html", error
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
28. success and error callbacks
$ ->
$("form").submit (event) ->
event.preventDefault()
url = $(this).attr "href"
$.ajax
url: url + ".js"
success: (data, status, xhr) ->
displaySuccess($("form"))
error: (xhr, status, error) ->
displayError error
displaySuccess = (form) ->
element = $("<p>Thanks for signing up!").addClass("success")
element.insertAfter form
form.hide()
displayError = (error) ->
$("#notice").attr "html", error
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
29. -> leaves (this) scope alone.
$ ->
$("form").submit (event) ->
event.preventDefault()
url = $(this).attr "href"
$.ajax
url: url + ".js"
success: (data, status, xhr) ->
displaySuccess($("form"))
error: (xhr, status, error) ->
displayError error
displaySuccess = (form) ->
element = $("<p>Thanks for signing up!").addClass("success")
element.insertAfter form
form.hide()
displayError = (error) ->
$("#notice").attr "html", error
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
30. =>
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
31. => binds this to the function body
$ ->
$("form").submit (event) ->
event.preventDefault()
url = $(this).attr "href"
$.ajax
url: url + ".js"
success: (data, status, xhr) =>
displaySuccess($(this))
error: (xhr, status, error) ->
displayError error
displaySuccess = (form) ->
element = $("<p>Thanks for signing up!").addClass("success")
element.insertAfter form
form.hide()
displayError = (error) ->
$("#notice").attr "html", error
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
33. Simple iteration
alert color for color in ["red", "green", "blue"]
var colors = ["red", "green", "blue"];
for (i = 0, length = colors.length; i < length; i++) {
var color = colors[i];
alert(color);
}
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
34. “for in”
people = [
{name: "Homer", age: 42}
{name: "Bart", age: 10}
]
for person in people
alert "#{person.name} is #{person.age} years old"
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
35. That’s just the
beginning.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
36. Existential operator (?)
total ?= 0
if (typeof total !== "undefined" && total !== null) {
total;
} else {
total = 0;
};
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
37. Object-oriented
JavaScript
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
38. Classes
var Person, p;
Person = (function() {
function Person(options) {
this.firstname = options.firstname;
this.lastname = options.lastname;
this.age = options.age;
}
Person.prototype.fullname = function() {
return "" + this.firstname + " " + this.lastname;
};
return Person;
})();
p = new Person({
firstname: "Brian",
lastname: "Hogan"
});
alert(p.fullname());
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
39. Classes
var Person, p;
Person = (function() {
function Person(options) {
this.firstname = options.firstname;
this.lastname = options.lastname;
class Person
this.age = options.age;
constructor: (options) ->
}
@firstname = options.firstname
Person.prototype.fullname = function() {
@lastname = options.lastname
return "" + this.firstname + " " + this.lastname;
@age = options.age
};
return Person;
fullname: ->
})();
"#{@firstname} #{@lastname}"
p = new Person({
firstname: "Brian",
lastname:="Hogan"
p new Person
}); alert p.fullname()
alert(p.fullname());
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
40. We can even extend classes!
class basicWindow
constructor: -> class mainWindow extends basicWindow
@window = Ti.UI.createWindow({ constructor: ->
backgroundColor: "#F5F5ED" super
}) @window.backgroundColor = "#fff"
open: ->
@window.open()
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
41. How do we use it?
In the web browser itself
via Node.js
With Ruby, via Guard
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
42. In the browser?
<script language="text/coffeescript">
people = [
{name: "Homer", age: 42}
{name: "Bart", age: 10}
]
for person in people
do (person) ->
alert "#{person.name} is #{person.age} years old"
</script>
<script src="coffee-script.js"></script>
(this is slow.)
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
43. With Node.js
Install Node.js
Install npm
npm install -g coffee-script
coffee --compile --output js/ coffee/
coffee -o js/ -cw coffee/
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
44. Ruby and Guard
Install Ruby
gem install guard-coffeescript
In our project
guard init coffeescript
guard
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
45. Guard watches input
folders for changes
and writes output
files.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
46. Guard works with Sass
too.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
47. Sass
Syntactically Awesome
Stylesheets
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
48. Sass gives CSS
everything programmers
want.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
49. CSS
.sidebar {
color: #000;
border: 1px solid #000;
}
.sidebar p {
margin-bottom: 20px;
}
.sidebar ul {
margin-bottom: 10px;
}
.sidebar h1 {
margin-bottom: 0;
}
.main{
color: #000;
}
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
50. CSS
.sidebar {
color: #000;
border: 1px solid #000;
}
.sidebar p {
margin-bottom: 20px;
}
.sidebar ul {
margin-bottom: 10px;
}
.sidebar h1 {
margin-bottom: 0;
}
.main{
color: #000;
}
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
51. CSS
.sidebar {
color: #000;
border: 1px solid #000;
}
.sidebar p {
margin-bottom: 20px;
}
.sidebar ul {
margin-bottom: 10px;
}
.sidebar h1 {
margin-bottom: 0;
}
.main{
color: #000;
}
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
52. Sass to
the rescue!
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
53. Variables!
$measure: 20px
$color: #ce4dd6
.sidebar
background-olor: $color
border: 1px solid lighten($color, 20%)
p
margin-bottom: $measure
ul
margin-bottom: $measure / 2
h1
margin-bottom: 0
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
54. Variables and helper functions!
$measure: 20px
$color: #ce4dd6
.sidebar
background-olor: $color
border: 1px solid lighten($color, 20%)
p
margin-bottom: $measure
ul
margin-bottom: $measure / 2
h1
margin-bottom: 0
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
55. Scope with nesting
$measure: 20px
$color: #ce4dd6
.sidebar
background-olor: $color
border: 1px solid lighten($color, 20%)
p
margin-bottom: $measure
ul
margin-bottom: $measure / 2
h1
margin-bottom: 0
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
56. Indented Sass SCSS
$measure: 20px $measure: 20px;
$color: #000 $color: #000;
.sidebar .sidebar{
color: $color color: $color;
border: 1px solid $color border: 1px solid $color;
p p{
margin-bottom: $measure margin-bottom: $measure;
}
ul
margin-bottom: $measure / 2 ul{
margin-bottom: $measure / 2;
h1 }
margin-bottom: 0
h1{
margin-bottom: 0;
}
}
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
57. But wait...
there’s more!
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
58. Modularization
_mixins.scss @import "mixins";
@import "reset";
@import "base";
_reset.scss @import "fonts";
_base.scss
_fonts.scss
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
62. Create well-organized
folders and libraries
of stylesheets.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
63. or use Compass.
http://compass-style.org/
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
64. Compass has helpers
@import 'compass'
@include box-shadow(#ddd 5px 5px 5px)
box-shadow: 5px 5px 5px #dddddd;
-moz-box-shadow: 5px 5px 5px #dddddd;
-webkit-box-shadow: 5px 5px 5px #dddddd;
-o-box-shadow: 5px 5px 5px #dddddd;}
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
65. How do we use it?
via Sass
via a supported IDE
With Ruby, via Guard
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
66. with Sass
Install Ruby
$ gem install sass
$ sass --watch sass:stylesheets
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
67. Ruby and Guard
Install Ruby
gem install guard-sass
In our project
guard init sass
guard
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
68. Using Sass and
CoffeeScript
together
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
69. Mindscape Web
Workbench
http://www.mindscapehq.com/products/web-workbench
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
70. Ruby and Guard
Install Ruby
gem install guard-sass guard-
coffeescript
In our project
guard init sass
guard init coffeescript
guard
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
71. Let’s talk deployment
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
72. Rails 3.1 and
Capistrano
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
73. Asset Packaging
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
74. So instead of this...
<link rel="stylesheet" href="stylesheets/layout.css">
<link rel="stylesheet" href="stylesheets/style.css">
<script src="javascripts/jquery-1.7.0.min.js"></script>
<script src="javascripts/app.js"></script>
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
75. ...let’s do this:
<link rel="stylesheet" href="assets/app.css">
<script src="assets/app.js"></script>
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
76. Ruby + Guard + Jammit
Install Ruby
$ gem install guard-jammit
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
77. Sass, CoffeeScript,
Jammit
watch Sass files for changes
Place output css in tmp/ folder
watch CoffeeScript files for changes
Place output js in tmp/ folder
Use Jammit to combine them.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
78. config/assets.yml
stylesheets:
app:
- tmp/app.css
- tmp/style.css
javascripts:
app:
- javascripts/jquery-1.6.4.js
- tmp/app.js
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
79. Guardfile
guard "coffeescript", :input => "coffeescripts", :output => "tmp"
guard "sass", :input => "sass", :output => "tmp"
guard "jammit" do
watch(/^javascripts/(.*).js/)
watch(/^stylesheets/(.*).css/)
watch(/^tmp/(.*).js/)
watch(/^tmp/(.*).css/)
end
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
80. Jammit places
files in
public/assets
<link rel="stylesheet" href="assets/app.css">
<script src="assets/app.js"></script>
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
81. Deploy with Rake
SERVER = "yourhost.com"
USERNAME = "yourusername"
REMOTE_FOLDER = "/home/#{USERNAME}/yourhost.com"
REMOTE_FOLDER = 22
require 'net/scp'
desc "compile CSS, js files"
task :compile do
require 'guard'
Guard.setup
Guard::Dsl.evaluate_guardfile
Guard::guards.each{|guard| guard.run_all}
end
desc "Deploy web site"
task :deploy => :compile do
Net::SSH.start(SERVER, USERNAME, {:port => PORT} ) do |ssh|
ssh.sftp.rmdir File.join(REMOTE_FOLDER, "public")
ssh.scp.upload! "public", REMOTE_FOLDER, :recursive => true
end
end
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
82. qedproject
https://github.com/napcs/qedproject
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
83. qedproject
Install Ruby
gem install qedproject
qedproject myapp -c -s -a -l jquery
creates app with Sass,
CoffeeScript, Asset packaging, and
jQuery
Sets up Guard and a simple Rake
file for deployment
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
85. Short syntax Nested
Selectors
Catch errors at
compile time Variables
List Mixins
Comprehensions
Composition
Classes
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
86. With asset packaging
and automated deployment...
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
87. ...CoffeeScript and Sass
make developers happy.
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
88. Questions?
http://pragprog.com/book/wbdev/web-
development-recipes
Brian P. Hogan
twitter: @bphogan
www.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
Editor's Notes
\n
\n
\n
Everyone who&#x2019;s done something on the web knows something about these languages.\n
Despite the new properties from CSS3, the language itself lacks basic features that programmers expect.\n
\n
Instead many developers go out to StackOverflow and swipe some code, slap it in the project, and cause all sorts of trouble for previous developers.\n
The solution is for us to use better tools and workflows to build our applications.\n
\n
\n
\n
\n
\n
\n
\n
It borrows the indentation of Python and some of the language features of both Python and Ruby.\n
\n
\n
Variable declarations are all done by omitting the var keyword. CoffeeScript automatically adds this so we don&#x2019;t accidentally get a variable in the wrong scope.\n
We can define functions many ways in Javascript. These are the two most popular - we can use &#x201C;function declarations&#x201D; or we can use function expressions. \n
The thin arrow defines our functions. If we want to take in parameters, we list them before the fat arrow. Everything within the function is indented. \n
If we have no params for our function, we simply use the dash rocket. If we do want to have params come in, we can specify them before the dash rocket in parentheses.\n
CoffeeScript always turns out regular JavaScript, but some of that JavaScript can be really, really hard to follow, so people don&#x2019;t write it very often.\n
Let&#x2019;s take a look at this jquery example. We have a form submission, and we have two events attached to the ajax request we fire during the form submission. It&#x2019;s a lot of callbacks and it&#x2019;s a bit hard to follow.\n
We can replace the documentReady jQuery method with a simple dollar sign and a dash rocket\n
Then we can locate an element just like we would with jQuery, but we declare the click handler with the dash rocket again.\n
jQuery&#x2019;s ajax method takes a settings object. We can define the object literal using CoffeeScript&#x2019;s syntax\n
Then since CoffeeScript uses the function expression form of function declaration, we declare the success and error callbacks using the same dashrocket feature.\n
the &#x2018;this&#x2019; keyword references the current context we&#x2019;re in. In the submit handler, (this) refers to the element that received the click. But in the success handler, we don&#x2019;t have access to that element anymore - &#x2018;this&#x2019; has changed so we have to use jquery again to grab the element.\n
This is the fat arrow. It works like the thin arrow except for one very important feature - it passes the scope of this into the function\n
Now &#x201C;this&#x201D; is bound and handled for us. We do a lot of hacks to avoid this in JavaScript. CoffeeScript gives us a language feature to solve that.\n
We can use CoffeeScript syntax to loop over collections much more easily.\n
Like in Ruby, we can iterate over arrays easily. This is equivalent to the typical &#x201C;for&#x201D; loop we are all used to writing\n
We can even iterate over collections of objects this way. This writes 100% cross-browser javascript code. We often bring in things like Underscore.js or jquery just for things like this, but with CoffeeScript we&#x2019;re not forcing our users to download those libraries just so we can have some convenience.\n
CoffeeScript has some amazing syntax that saves us some time.\n
We can use this to initialize a variable if it&#x2019;s not already defined.\n
JavaScript isn&#x2019;t really an object-oriented language, even though programmers pretend it is. \n
We can have classes in JavaScript. But to do that, we&#x2019;d need to write monster code like this.\n
We can replace that with this CoffeeScript code.... which is a LOT nicer.\n
\n
but how do we actually *use* it?\n
We can use it in the browser. CoffeeScript is actually written in CoffeeScript, thus the interpreter is a JS file.\n
We can also install Node.JS and NPM to get the &#x2018;coffee&#x2019; command on our machines.\n
Or we can use Guard and Ruby. \n
Guard is a simple commandline utility that watches folders for changes and executes tasks. It works on Windows and OSX and many Linux flavors.\n
More on Guard in a bit, but first, let&#x2019;s talk about Sass\n
Sass is how I write my stylesheets\n
As a programmer, I miss certain things in CSS, like variables and functions\n
Look at how much CSS makes us repeat ourselves. We have to repeat this sidebar selector three times just so we can specify that we want to target elements within the sidebar scope.\n
These repeated color codes make it hard for us to refactor styles later.\n
And look at these measurements. These should be computed or something.\n
\n
We can declare variables and even work with them. Notice that the 20px value can be divided, while still retaining its suffix?\n
We can also work with colors. We can use functions to alter the colors.\n
And we can nest selectors so we can avoid repeating ourselves. This makes scoping so much more apparent.\n
There&#x2019;s a different syntax, if the whitespace indentation stuff isn&#x2019;t your thing.\n
The variables and nesting go a long way to making our CSS less repetitive, but we can go even farther.\n
We can break up our styles into smaller files that we can compose together, and then build one main stylesheet out of those parts.\n
We can create mixins, or reusable functions to build up a library of common, useful features for our stylesheets.\n
And we can make them even more powerful, by combining mixins and iteration with our variables.\n
This is a great way to reduce duplication in our code.\n
We can then create some pretty amazing collections of reusable code.\n
But we can also use Compass, a nice framework for working with Sass\n
So instead, we just use Compass&#x2019; helpers instead of building our own. And there are a lot of them.\n
but how do we actually *use* it?\n
\n
Or we can use Guard and Ruby. \n
So now you&#x2019;re all excited about these things.\n
Support in Visual Studio 2010 for Sass and CoffeeScript\n
Or we can use Guard and Ruby. Guard can watch for CoffeeScript and Sass files at the same time.\n
Deployment should be automated. The days of moving files by FTP should be over, so there should be some script or process that pushes apps to production.\n
Basically done for you thanks to the asset pipeline. Deployment is handled by Capistrano tasks.\n
We&#x2019;ve got all these stylesheets and JavaScript files, but our browser shouldn&#x2019;t have to make people download all of these files.\n
This makes the end user download multiple files which means additional HTTP requests.\n
Let&#x2019;s combine our css and JS files so we eliminate the need for those extra requests.\n
To do this, we can use Ruby, Guard, and Jammit.\n
We can put Guard to work along with Jammit, an asset packager which will combine our JS and CSS files into single files, with compression.\n
So we list our stylesheets that we want to combine, and we do the same with JS. We tell Jammit to look in the tmp folder, which is where Sass and CoffeeScript are placing the generated JS files. Our web page will reference these in the public/ folder\n
This is a Guardfile that specifies the folders we want to watch. \n
We just need to make sure our web page looks in the assets/ folder for the files.\n
We then script the deployment. We could use any scripting language, really, but by using Rake, which is written in Ruby, we can actually invoke Guard and tell it to force compilation of our assets. When we run our deploy task, our compile task runs first, thanks to the => dependency declaration.\n
qedproject is a simple command-line utility written in Ruby for creating projects that let you work with sass and Coffeescript. It&#x2019;s a work in progress but I use it when I&#x2019;m trying to figure something out.\n
\n
\n
To sum it up, here are the main benefits to both of these technologies\n
\n
I&#x2019;ve stopped writing regular CSS, and I&#x2019;m looking to stop writing regular JavaScript. There are too many productivity advantages.\n