Skip to content

Commit

Permalink
more refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
maccman committed Nov 6, 2011
1 parent 860adec commit f9d48f3
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 36 deletions.
4 changes: 2 additions & 2 deletions coffeescript/01_introduction.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ <h1>What is CoffeeScript?</h1>

<h2>Initial setup</h2>

<p>One of the easiest ways to initially play around with the library is to use it right inside the browser. Navigate to <a href="http://coffeescript.org">http://coffeescript.org</a> and click on the <em>Try CoffeeScript</em> tab. The site uses a browser version of the CoffeeScript compiler, converting any CoffeeScript typed inside the left panel, to JavaScript in the right panel.</p>
<p>One of the easiest ways to initially play around with the library is to use it right inside the browser. Navigate to <a href="http://coffeescript.org">http://coffeescript.org</a> and click on the <em>Try CoffeeScript</em> tab. The site uses a browser version of the CoffeeScript compiler, converting any CoffeeScript typed inside the left panel to JavaScript in the right panel.</p>

<p>You can also convert JavaScript back to CoffeeScript using the <a href="http://js2coffee.org/">js2coffee</a> project, especially useful when migration JavaScript projects to CoffeeScript.</p>

Expand All @@ -57,7 +57,7 @@ <h2>Initial setup</h2>
&lt;/script&gt;
</code></pre>

<p>Obviously, in production, you don't want to be interpreting CoffeeScript at runtime, as it'll slow things up for your clients, so CoffeeScript offers a <a href="http://nodejs.org">Node.js</a> compiler to pre-process CoffeeScript files.</p>
<p>Obviously, in production, you don't want to be interpreting CoffeeScript at runtime as it'll slow things up for your clients. Instead CoffeeScript offers a <a href="http://nodejs.org">Node.js</a> compiler to pre-process CoffeeScript files.</p>

<p>To install it, first make sure you have a working copy of the latest stable version of <a href="http://nodejs.org">Node.js</a>, and <a href="http://npmjs.org/">npm</a> (the Node Package Manager). You can then install CoffeeScript with npm:</p>

Expand Down
10 changes: 8 additions & 2 deletions coffeescript/02_syntax.html
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ <h3>Function arguments</h3>

<pre><code>trigger = (events...) -&gt;
events.splice(1, 0, this)
this.parent.trigger.apply(events)
this.constructor.trigger.apply(events)
</code></pre>

<h3>Function invocation</h3>
Expand Down Expand Up @@ -252,7 +252,13 @@ <h2>Flow control</h2>
<p><span class="csscript"></span></p>

<pre><code>if true is 1
"Type coercion fixed!"
"Type coercion fail!"
</code></pre>

<p>As an alternative to <code>is not</code>, you can use <code>isnt</code>.</p>

<pre><code>if true isnt true
alert "Opposite day!"
</code></pre>

<p>You may have noticed in the examples above, that CoffeeScript is converting <code>==</code> operators into <code>===</code> and <code>!=</code> into <code>!==</code>. This is one of my favorite features to the language, and yet one of the most simple. What's the reasoning behind this? Well frankly JavaScript's type coercion is a bit odd, and its equality operator coerces types in order to compare them, leading to some confusing behaviors and the source of many bugs. There's a longer discussing on this topic in chapter 7.</p>
Expand Down
2 changes: 1 addition & 1 deletion coffeescript/04_idioms.html
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ <h2>And/or</h2>
<pre><code>hash or= {}
</code></pre>

<p>If hash evaluates to <code>false</code>, then it's set to an empty object. It's important to note here that this expression also recognizes <code>0</code>, <code>""</code> and <code>[]</code> as false. If that isn't your intention, you'll need to use CoffeeScript's existential operator, which only gets activated if <code>hash</code> is <code>undefined</code> or <code>null</code>:</p>
<p>If hash evaluates to <code>false</code>, then it's set to an empty object. It's important to note here that this expression also recognizes <code>0</code>, <code>""</code> and <code>null</code> as false. If that isn't your intention, you'll need to use CoffeeScript's existential operator, which only gets activated if <code>hash</code> is <code>undefined</code> or <code>null</code>:</p>

<p><span class="csscript"></span></p>

Expand Down
2 changes: 1 addition & 1 deletion coffeescript/05_compiling.html
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ <h2>Server side support</h2>

<p>Using Cake for CoffeeScript compilation is fine for static sites, but for dynamic sites we might as well integrate CoffeeScript compilation into the request/response cycle. Various integration solutions already exist for the popular backend languages and frameworks, such as <a href="http://rubyonrails.org/">Rails</a> and <a href="https://www.djangoproject.com/">Django</a>.</p>

<p>When it comes to Rails 3, CoffeeScript support comes via <a href="https://github.com/sstephenson/sprockets">Sprockets &amp; the asset pipeline</a>. Add your CoffeeScript files under <code>app/assets/javascripts</code>, and Rails is smart enough to pre-compile them when they're requested. JavaScript &amp; CoffeeScript files are concatenated and bundled using special comment directives, meaning you can fetch all of your application's JavaScript with one request. When it comes to production, Rails will write the compiled output to disk, ensuring it's cached and fast to serve.</p>
<p>When it comes to Rails 3.1, CoffeeScript support comes via <a href="https://github.com/sstephenson/sprockets">Sprockets &amp; the asset pipeline</a>. Add your CoffeeScript files under <code>app/assets/javascripts</code>, and Rails is smart enough to pre-compile them when they're requested. JavaScript &amp; CoffeeScript files are concatenated and bundled using special comment directives, meaning you can fetch all of your application's JavaScript with one request. When it comes to production, Rails will write the compiled output to disk, ensuring it's cached and fast to serve.</p>

<p>Other Ruby options include Rack servers such as 37signal's <a href="http://pow.cx/">Pow</a> and Joshua Peek's <a href="http://josh.github.com/nack/">Nack</a>, both highly recommended if your application doesn't need Rail's other features and associated overhead.</p>

Expand Down
32 changes: 28 additions & 4 deletions coffeescript/06_applications.html
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ <h2>Stitch it up</h2>
"dependencies": {
"coffee-script": "~1.1.2",
"stitch": "~0.3.2",
"express": "~2.5.0"
"express": "~2.5.0",
"eco": "1.1.0-rc-1"
}
}
</code></pre>
Expand Down Expand Up @@ -164,15 +165,15 @@ <h2>Stitch it up</h2>
&lt;/html&gt;
</code></pre>

<p>When the page loads, our <em>DOMContentLoaded</em> event callback is requiring the <code>app.coffee</code> script (which is automatically compiled), and invoking our <code>init()</code> function. That's all there is to it, we've got CommonJS modules up and running, as well as a HTTP server and CoffeeScript compiler. If, say, we wanted to include a module, it's just a case of calling <code>require()</code>.</p>
<p>When the page loads, our <em>DOMContentLoaded</em> event callback is requiring the <code>app.coffee</code> script (which is automatically compiled), and invoking our <code>init()</code> function. That's all there is to it, we've got CommonJS modules up and running, as well as a HTTP server and CoffeeScript compiler. If, say, we wanted to include a module, it's just a case of calling <code>require()</code>. Let's create a new class, <code>User</code>, and reference it from <code>app.coffee</code>:</p>

<p><span class="csscript"></span></p>

<pre><code># models/user.coffee
<pre><code># app/models/user.coffee
module.exports = class User
constructor: (@name) -&gt;

# app.coffee
# app/app.coffee
User = require("models/user")
</code></pre>

Expand Down Expand Up @@ -230,9 +231,32 @@ <h2>JavaScript templates</h2>

<p>Stitch will automatically compile our template and include it in <code>application.js</code>. Then, in our application's controllers we can require the template, like it was a module, and execute it passing any data required.</p>

<p><span class="csscript"></span></p>

<pre><code>require("views/users/show")(new User("Brian"))
</code></pre>

<p>Our <code>app.coffee</code> file should now look like this, rendering the template and appending it to the page when the document loads:</p>

<p><span class="csscript"></span></p>

<pre><code>User = require("models/user")

App =
init: -&gt;
template = require("views/users/show")
view = template(new User("Brian"))

# Obviously this could be spruced up by jQuery
element = document.createElement("div")
element.innerHTML = view
document.body.appendChild(element)

module.exports = App
</code></pre>

<p>Open up <a href="http://localhost:9294/">the application</a> and give it a whirl! Hopefully this tutorial has given you a good idea of how to structure client-side CoffeeScript applications. For your next steps, I recommend checking out a JavaScript/CoffeeScript MVC framework like <a href="http://documentcloud.github.com/backbone/">Backbone</a> or <a href="http://spinejs.com">Spine</a>, They'll provide a basic MVC structure for you, freeing you up to build awesome web applications.</p>

<h2>Bonus - 30 second deployment with Heroku</h2>

<p><a href="http://heroku.com/">Heroku</a> is an incredibly awesome web host that manages all the servers and scaling for you, letting you get on with the exciting stuff (building awesome JavaScript applications). You'll need an account with Heroku for this tutorial to work, but the great news is that their basic plan is completely free. While traditionally a Ruby host, Heroku have recently released their Cedar stack, which includes Node support.</p>
Expand Down
3 changes: 1 addition & 2 deletions coffeescript/07_the_bad_parts.html
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,7 @@ <h2>Strict mode</h2>
<p>Most of the changes strict mode introduces pertain to JavaScript's syntax:</p>

<ul>
<li>Errors on duplicate property names</li>
<li>Errors on duplicate function argument names</li>
<li>Errors on duplicate property and function argument names</li>
<li>Errors on incorrect use of the <code>delete</code> operator</li>
<li>Access to <code>arguments.caller</code> &amp; <code>arguments.callee</code> throws an error (for performance reasons)</li>
<li>Using the <code>with</code> operator will raise a syntax error</li>
Expand Down
53 changes: 41 additions & 12 deletions coffeescript/all.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ <h1>What is CoffeeScript?</h1>

<h2>Initial setup</h2>

<p>One of the easiest ways to initially play around with the library is to use it right inside the browser. Navigate to <a href="http://coffeescript.org">http://coffeescript.org</a> and click on the <em>Try CoffeeScript</em> tab. The site uses a browser version of the CoffeeScript compiler, converting any CoffeeScript typed inside the left panel, to JavaScript in the right panel.</p>
<p>One of the easiest ways to initially play around with the library is to use it right inside the browser. Navigate to <a href="http://coffeescript.org">http://coffeescript.org</a> and click on the <em>Try CoffeeScript</em> tab. The site uses a browser version of the CoffeeScript compiler, converting any CoffeeScript typed inside the left panel to JavaScript in the right panel.</p>

<p>You can also convert JavaScript back to CoffeeScript using the <a href="http://js2coffee.org/">js2coffee</a> project, especially useful when migration JavaScript projects to CoffeeScript.</p>

Expand All @@ -57,7 +57,7 @@ <h2>Initial setup</h2>
&lt;/script&gt;
</code></pre>

<p>Obviously, in production, you don't want to be interpreting CoffeeScript at runtime, as it'll slow things up for your clients, so CoffeeScript offers a <a href="http://nodejs.org">Node.js</a> compiler to pre-process CoffeeScript files.</p>
<p>Obviously, in production, you don't want to be interpreting CoffeeScript at runtime as it'll slow things up for your clients. Instead CoffeeScript offers a <a href="http://nodejs.org">Node.js</a> compiler to pre-process CoffeeScript files.</p>

<p>To install it, first make sure you have a working copy of the latest stable version of <a href="http://nodejs.org">Node.js</a>, and <a href="http://npmjs.org/">npm</a> (the Node Package Manager). You can then install CoffeeScript with npm:</p>

Expand Down Expand Up @@ -206,7 +206,7 @@ <h3>Function arguments</h3>

<pre><code>trigger = (events...) -&gt;
events.splice(1, 0, this)
this.parent.trigger.apply(events)
this.constructor.trigger.apply(events)
</code></pre>

<h3>Function invocation</h3>
Expand Down Expand Up @@ -332,7 +332,13 @@ <h2>Flow control</h2>
<p><span class="csscript"></span></p>

<pre><code>if true is 1
"Type coercion fixed!"
"Type coercion fail!"
</code></pre>

<p>As an alternative to <code>is not</code>, you can use <code>isnt</code>.</p>

<pre><code>if true isnt true
alert "Opposite day!"
</code></pre>

<p>You may have noticed in the examples above, that CoffeeScript is converting <code>==</code> operators into <code>===</code> and <code>!=</code> into <code>!==</code>. This is one of my favorite features to the language, and yet one of the most simple. What's the reasoning behind this? Well frankly JavaScript's type coercion is a bit odd, and its equality operator coerces types in order to compare them, leading to some confusing behaviors and the source of many bugs. There's a longer discussing on this topic in chapter 7.</p>
Expand Down Expand Up @@ -958,7 +964,7 @@ <h2>And/or</h2>
<pre><code>hash or= {}
</code></pre>

<p>If hash evaluates to <code>false</code>, then it's set to an empty object. It's important to note here that this expression also recognizes <code>0</code>, <code>""</code> and <code>[]</code> as false. If that isn't your intention, you'll need to use CoffeeScript's existential operator, which only gets activated if <code>hash</code> is <code>undefined</code> or <code>null</code>:</p>
<p>If hash evaluates to <code>false</code>, then it's set to an empty object. It's important to note here that this expression also recognizes <code>0</code>, <code>""</code> and <code>null</code> as false. If that isn't your intention, you'll need to use CoffeeScript's existential operator, which only gets activated if <code>hash</code> is <code>undefined</code> or <code>null</code>:</p>

<p><span class="csscript"></span></p>

Expand Down Expand Up @@ -1146,7 +1152,7 @@ <h2>Server side support</h2>

<p>Using Cake for CoffeeScript compilation is fine for static sites, but for dynamic sites we might as well integrate CoffeeScript compilation into the request/response cycle. Various integration solutions already exist for the popular backend languages and frameworks, such as <a href="http://rubyonrails.org/">Rails</a> and <a href="https://www.djangoproject.com/">Django</a>.</p>

<p>When it comes to Rails 3, CoffeeScript support comes via <a href="https://github.com/sstephenson/sprockets">Sprockets &amp; the asset pipeline</a>. Add your CoffeeScript files under <code>app/assets/javascripts</code>, and Rails is smart enough to pre-compile them when they're requested. JavaScript &amp; CoffeeScript files are concatenated and bundled using special comment directives, meaning you can fetch all of your application's JavaScript with one request. When it comes to production, Rails will write the compiled output to disk, ensuring it's cached and fast to serve.</p>
<p>When it comes to Rails 3.1, CoffeeScript support comes via <a href="https://github.com/sstephenson/sprockets">Sprockets &amp; the asset pipeline</a>. Add your CoffeeScript files under <code>app/assets/javascripts</code>, and Rails is smart enough to pre-compile them when they're requested. JavaScript &amp; CoffeeScript files are concatenated and bundled using special comment directives, meaning you can fetch all of your application's JavaScript with one request. When it comes to production, Rails will write the compiled output to disk, ensuring it's cached and fast to serve.</p>

<p>Other Ruby options include Rack servers such as 37signal's <a href="http://pow.cx/">Pow</a> and Joshua Peek's <a href="http://josh.github.com/nack/">Nack</a>, both highly recommended if your application doesn't need Rail's other features and associated overhead.</p>

Expand Down Expand Up @@ -1277,7 +1283,8 @@ <h2>Stitch it up</h2>
"dependencies": {
"coffee-script": "~1.1.2",
"stitch": "~0.3.2",
"express": "~2.5.0"
"express": "~2.5.0",
"eco": "1.1.0-rc-1"
}
}
</code></pre>
Expand Down Expand Up @@ -1323,15 +1330,15 @@ <h2>Stitch it up</h2>
&lt;/html&gt;
</code></pre>

<p>When the page loads, our <em>DOMContentLoaded</em> event callback is requiring the <code>app.coffee</code> script (which is automatically compiled), and invoking our <code>init()</code> function. That's all there is to it, we've got CommonJS modules up and running, as well as a HTTP server and CoffeeScript compiler. If, say, we wanted to include a module, it's just a case of calling <code>require()</code>.</p>
<p>When the page loads, our <em>DOMContentLoaded</em> event callback is requiring the <code>app.coffee</code> script (which is automatically compiled), and invoking our <code>init()</code> function. That's all there is to it, we've got CommonJS modules up and running, as well as a HTTP server and CoffeeScript compiler. If, say, we wanted to include a module, it's just a case of calling <code>require()</code>. Let's create a new class, <code>User</code>, and reference it from <code>app.coffee</code>:</p>

<p><span class="csscript"></span></p>

<pre><code># models/user.coffee
<pre><code># app/models/user.coffee
module.exports = class User
constructor: (@name) -&gt;

# app.coffee
# app/app.coffee
User = require("models/user")
</code></pre>

Expand Down Expand Up @@ -1389,9 +1396,32 @@ <h2>JavaScript templates</h2>

<p>Stitch will automatically compile our template and include it in <code>application.js</code>. Then, in our application's controllers we can require the template, like it was a module, and execute it passing any data required.</p>

<p><span class="csscript"></span></p>

<pre><code>require("views/users/show")(new User("Brian"))
</code></pre>

<p>Our <code>app.coffee</code> file should now look like this, rendering the template and appending it to the page when the document loads:</p>

<p><span class="csscript"></span></p>

<pre><code>User = require("models/user")

App =
init: -&gt;
template = require("views/users/show")
view = template(new User("Brian"))

# Obviously this could be spruced up by jQuery
element = document.createElement("div")
element.innerHTML = view
document.body.appendChild(element)

module.exports = App
</code></pre>

<p>Open up <a href="http://localhost:9294/">the application</a> and give it a whirl! Hopefully this tutorial has given you a good idea of how to structure client-side CoffeeScript applications. For your next steps, I recommend checking out a JavaScript/CoffeeScript MVC framework like <a href="http://documentcloud.github.com/backbone/">Backbone</a> or <a href="http://spinejs.com">Spine</a>, They'll provide a basic MVC structure for you, freeing you up to build awesome web applications.</p>

<h2>Bonus - 30 second deployment with Heroku</h2>

<p><a href="http://heroku.com/">Heroku</a> is an incredibly awesome web host that manages all the servers and scaling for you, letting you get on with the exciting stuff (building awesome JavaScript applications). You'll need an account with Heroku for this tutorial to work, but the great news is that their basic plan is completely free. While traditionally a Ruby host, Heroku have recently released their Cedar stack, which includes Node support.</p>
Expand Down Expand Up @@ -1821,8 +1851,7 @@ <h2>Strict mode</h2>
<p>Most of the changes strict mode introduces pertain to JavaScript's syntax:</p>

<ul>
<li>Errors on duplicate property names</li>
<li>Errors on duplicate function argument names</li>
<li>Errors on duplicate property and function argument names</li>
<li>Errors on incorrect use of the <code>delete</code> operator</li>
<li>Access to <code>arguments.caller</code> &amp; <code>arguments.callee</code> throws an error (for performance reasons)</li>
<li>Using the <code>with</code> operator will raise a syntax error</li>
Expand Down
Loading

0 comments on commit f9d48f3

Please sign in to comment.