Slide 1

Slide 1 text

JavaScript taking seriously James Cox @th3james UNEP-WCMC

Slide 2

Slide 2 text

Why?

Slide 3

Slide 3 text

Apps > Pages

Slide 4

Slide 4 text

Apps... - Faster, more responsive - Fewer resource requests - Better UX =>

Slide 5

Slide 5 text

Apps... :-) Users - Faster, more responsive - Fewer resource requests - Better UX =>

Slide 6

Slide 6 text

Websites used to look like this:

Slide 7

Slide 7 text

Then this happened

Slide 8

Slide 8 text

Then this happened ... in 2004

Slide 9

Slide 9 text

It’s 2011

Slide 10

Slide 10 text

It’s 2011 Web Apps are mature

Slide 11

Slide 11 text

It’s 2011 Web Apps are mature And we should be building them

Slide 12

Slide 12 text

A Whole Bunch of Awesome HTML5 pushState Canvas CSS3 WebGL V8

Slide 13

Slide 13 text

Modernizr.js For when you don’t have the awesome

Slide 14

Slide 14 text

JavaScript Because you don’t have a choice

Slide 15

Slide 15 text

Probably the most common language in the world:

Slide 16

Slide 16 text

Probably the most common language in the world: Worth Learning

Slide 17

Slide 17 text

Most people don’t bother People use JavaScript because they have to, and expect it to work like

Slide 18

Slide 18 text

Most people don’t bother Unfortunately... People use JavaScript because they have to, and expect it to work like

Slide 19

Slide 19 text

JavaScript is not treating it as such is a recipe for pain

Slide 20

Slide 20 text

The Bad Parts JavaScript was written in 10 days Consequentially, it has some pretty serious flaws...

Slide 21

Slide 21 text

The Bad Parts Dependency on global variables

Slide 22

Slide 22 text

The Bad Parts Dependency on global variables No block scope

Slide 23

Slide 23 text

The Bad Parts Dependency on global variables No block scope Prototypal inheritance is unintuitive to OO programmers

Slide 24

Slide 24 text

The Bad Parts Dependency on global variables No block scope Prototypal inheritance is unintuitive to OO programmers Many other small problems which you expect from a language written in 10 days

Slide 25

Slide 25 text

The Good Parts Thankfully, JavaScript also has some seriously good parts

Slide 26

Slide 26 text

Great implementation of functions The Good Parts

Slide 27

Slide 27 text

Great implementation of functions Object Literal notation (JSON) The Good Parts

Slide 28

Slide 28 text

Great implementation of functions Object Literal notation (JSON) Loosely typed The Good Parts

Slide 29

Slide 29 text

Great implementation of functions Object Literal notation (JSON) Loosely typed Prototypal inheritance The Good Parts

Slide 30

Slide 30 text

Learn The Good Parts

Slide 31

Slide 31 text

... It’s shorter than the definitive guide

Slide 32

Slide 32 text

Common Pitfalls

Slide 33

Slide 33 text

Avoiding Globals //Create a global variable var MYAPP = {}; //Put globals into it MYAPP.map = new Map()

Slide 34

Slide 34 text

Function scope, not block scope var hat; // This is global function() { for (var i = 0, il = 10; i < il; i++) { // boat is not limited to the block.. var boat = ‘great’; } // i, il and boat are still in scope here... } // ... but only hat remains here

Slide 35

Slide 35 text

Define all vars at beginning of their scope function() { // Define ALL your vars here var i, il, boat; for (i = 0, il = 10; i < il; i++) { boat = ‘great’; } }

Slide 36

Slide 36 text

Closure var closureExample = (function() { var mcHammer = "Can't touch this"; return { hammerTime: function () { mcHammer = 'Stop! Hammer time'; }, hammerSay: function () { alert(mcHammer); } }; }()); closureExample.mcHammer; //Will throw an error closureExample.hammerSay();// “Can’t touch this” closureExample.hammerTime(); closureExample.hammerSay();// “Stop! Hammer time

Slide 37

Slide 37 text

Prototypal Inheritance Every Object has a prototype from which it inherits Default is Object.prototype

Slide 38

Slide 38 text

Objects inherit from other objects: Should be simple! Unfortunately, JavaScript’s tries to make this as unintuitive as possible by using a pseudoclassical pattern :-| No Classes

Slide 39

Slide 39 text

Pseudoclassical behaviour using ‘new’ // New vehicle object var Vehicle = function (color) { this.color = color; }; // Augment the prototype with a function Vehicle.prototype.getColor = function () { alert(“I’m “ + this.color); }; // Make an instance var vehicle = new Vehicle(‘Red’); vehicle.getColor(); // “I’m Red”

Slide 40

Slide 40 text

var Car = function(color) { this.color = color; this.noise = ‘Vroom!’; } Car.prototype = new Vehicle(); Car.prototype.describe = function () { alert(‘The ‘ + this.color + ‘ car goes ’ + this.noise); } var car = new Car(‘purple’); car.describe(); // The purple car goes Vroom! car.getColor(); // I’m purple

Slide 41

Slide 41 text

Don’t do it like this! The new keyword sucks It’s clumsy to use and forgetting the ‘new’ prefix when calling a constructor is easy to do and hard to debug Instead...

Slide 42

Slide 42 text

Use functions to create objects with closure Much cleaner that the pseudoclassical pattern Closure ensures more robust objects

Slide 43

Slide 43 text

var vehicle = function(spec) { // Define that and private instance variables var that, aPrivateVariable; // Initialise that as an object that = {}; // Create privileged methods var getColor = function () { alert("I’m " + spec.color); }; that.getColor = getColor; // Return our created object return that; }; var myVehicle = vehicle({color:'red'});

Slide 44

Slide 44 text

var car = function(spec) { spec.noise = spec.noise || 'Vroom!'; // initialise 'that' as a vehicle, // thereby inheriting from it var that = vehicle(spec); var describe = function () { alert('The ' + spec.color + ' car goes ' + spec.noise); }; that.describe = describe; return that; } var myCar = car({color:'purple'});

Slide 45

Slide 45 text

CoffeeScript

Slide 46

Slide 46 text

JavaScript without the bad parts CoffeeScript

Slide 47

Slide 47 text

JavaScript without the bad parts Super readable, Ruby-like syntax CoffeeScript

Slide 48

Slide 48 text

JavaScript without the bad parts Super readable, Ruby-like syntax Compiles to fast, high quality, human readable JavaScript CoffeeScript

Slide 49

Slide 49 text

There are some skeptics

Slide 50

Slide 50 text

But! Even if you’re not ready to use CoffeeScript in your app,

Slide 51

Slide 51 text

But! Even if you’re not ready to use CoffeeScript in your app, it’s still a great way to improve your JavaScript

Slide 52

Slide 52 text

Play with the interpreter at http://jashkenas.github.com Prototype your code in CoffeeScript, learn best practices from the generated output

Slide 53

Slide 53 text

Backbone.js

Slide 54

Slide 54 text

“The Wilkinson Sword to JavaScript’s bare razor” @tokumin

Slide 55

Slide 55 text

No more spaghetti heaps of jQuery selectors and callback functions

Slide 56

Slide 56 text

MVC* = Organised *kinda

Slide 57

Slide 57 text

Models Reuse your existing application models

Slide 58

Slide 58 text

Models Reuse your existing application models Stores your data and the logic to manipulate it

Slide 59

Slide 59 text

Models Reuse your existing application models Stores your data and the logic to manipulate it Should be pretty familiar!

Slide 60

Slide 60 text

Song = Backbone.Model.extend({ defaults: {playCount: 0}, initialize: function(){ // Setup the model here }, displayName: function (){ // Use .get to get properties this.get(‘artist’) + ‘: ‘ + this.get(‘track’); }, play: function () { //Use .set to set properties this.set({playCount: this.get(‘playCount’) + 1}); } }); song = new Song({artist: ‘The Fall’, track: ‘Barmy’});

Slide 61

Slide 61 text

Collections var Album = Backbone.Collection.extend({ model: Song }); var song1 = new Song({ name: "One Touch", artist: "LCD Soundsystem" }); var song2 = new Song({ name: "Song 2", artist: "Blur" }); var compilation = new Album([song1, song2]);

Slide 62

Slide 62 text

Speak JSON JSON is what your app should be serving

Slide 63

Slide 63 text

Speak JSON JSON is what your app should be serving Super easy to initialise Backbone/Javascript objects: SomeCollection = new Collection({JSON DATA})

Slide 64

Slide 64 text

Speak JSON JSON is what your app should be serving Super easy to initialise Backbone/Javascript objects: Much more reusable than pre-rendered HTML SomeCollection = new Collection({JSON DATA})

Slide 65

Slide 65 text

Speak JSON JSON is what your app should be serving Super easy to initialise Backbone/Javascript objects: Much more reusable than pre-rendered HTML Build a platform! SomeCollection = new Collection({JSON DATA})

Slide 66

Slide 66 text

Views AlbumView = Backbone.View.extend({ initialize: function(){ // Setup the view }, render: function(){ // Visualise something return this; } }); var av = new AlbumView({ collection: Compilation });

Slide 67

Slide 67 text

initialise: function() { // Create the template from the DOM element this.template = _.template($('#album_template').html()) }, render: function() { // Render to this.el with a templating language $(this.el).html(this.template(this.collection.toJSON())); } <ul> <% for (var i = 0; i < songs.length; i++){ %> <li><% employeeList[i].get(‘name’); %></li> <% } %> </ul> Templating

Slide 68

Slide 68 text

Events Where the real magic happens

Slide 69

Slide 69 text

Bind DOM events to view methods AlbumView = Backbone.View.extend({ events: { // bind events to methods ‘click .addSong’: ‘addSong’ }, addSong: { // Talk to our collections/model song_name = prompt("Song name?") song_model = new Song({ name: song_name }) } })

Slide 70

Slide 70 text

Bind Collection/Model events to view.render methods AlbumView = Backbone.View.extend({ initialize: { ... this.collection.bind('reset', this.render) this.collection.bind('add', this.render) this.collection.bind('remove', this.render) ... } }

Slide 71

Slide 71 text

Views automatically update to reflect changes

Slide 72

Slide 72 text

Views automatically update to reflect changes Powerful stuff!

Slide 73

Slide 73 text

Router Connect routes up to app initialisation Provides browser history support and linkable, bookmarkable, shareable URLs

Slide 74

Slide 74 text

MyApp = Backbone.Router.extend({ routes: { '/': 'index', '/:id/': 'show' }, initialize: function() { // Do any app wide stuff }, index: function() { if (typeof(window.MYAPP.currentView) !== 'undefined') // Close any existing view //Create a collection myCollection = new Collection({some JSON}) //Create a view window.MYAPP.currentView = new CollectionView({collection: myCollection}) $('#container').html(window.MYAPP.currentView.render().el); } });

Slide 75

Slide 75 text

// Create the app myApp = new MyApp(); // Fire up the history Backbone.history.start({pushState:true}); // Trigger a history event myApp.navigate('/' + model.get(‘id’), true)

Slide 76

Slide 76 text

Backbone.js Recap Organised

Slide 77

Slide 77 text

Backbone.js Recap Organised Speaks JSON

Slide 78

Slide 78 text

Backbone.js Recap Organised Speaks JSON Event driven

Slide 79

Slide 79 text

Backbone.js Recap Organised Speaks JSON Event driven URL and browser history aware

Slide 80

Slide 80 text

Next Steps

Slide 81

Slide 81 text

PJAX Load HTML from your server without page reload Great for top level tab navigation

Slide 82

Slide 82 text

BDD for JavaScript describe("Jasmine", function() { it("makes testing JavaScript awesome!", function() { expect(yourCode).toBeLotsBetter(); }); });

Slide 83

Slide 83 text

Require.js Load JavaScript files as modules, asynchronously

Slide 84

Slide 84 text

Big Recap! Web Apps => Awesome Learn JavaScript => You don’t have a choice Backbone.js => Make large JS projects manageable

Slide 85

Slide 85 text

Thanks! James Cox @th3james UNEP-WCMC