Become a Web Dev Hipster

Narciso (NJ) Jaramillo
Principal Scientist, Web Platform and Authoring
nj@adobe.com
@notwebsafe

The evolution of AJAX

Classic vs. modern AJAX

JSON

JSON
{ "name": "Narciso Jaramillo", "birthday": "1932-10-05T03:52:12Z", "address": { "street": "123 Anywhere Place", "city": "Somewhere", zip: 92153 } }

Client-side templating

HTML
<script id=“blogPostTemplate” type=“text/x-handlebars-template”> <div class=“entry”> <h1>{{title}}</h1> <div class=“body”> {{body}} </div> </div> </script>
var source = $(‘#blogPostTemplate’).html();
var postTemplate = Handlebars.compile(source);
$.ajax(postURL, { 
  success: function(data) {
    // data = { title: "My Post", body: "..." }
    $(‘#postContent’).html(postTemplate(data));
  })
});
JavaScript

Frameworks and libraries

or, small is beautiful

"All-in-one" frameworks

  • Inheritance
  • Component model
  • UI widget set
  • MVC
  • Data access
  • Hide DOM complexity

Mix-and-match

Module loading
DOM manipulation, AJAX
CSS grid/lightweight components
Mobile UI components
Client-side templating
Lightweight MV(C)

MVC mini-frameworks

backbonejs.org | knockoutjs.com | angularjs.org

HTML5 for apps

or, simple APIs are simple

Local storage

localStorage.setItem("name", "Narciso Jaramillo");
// later...
var name = localStorage.getItem("name");
localStorage.removeItem("name");

App cache

HTML
<html manifest="example.appcache"> ... </html>
Manifest
CACHE MANIFEST # 2013-01-14:v1 index.html stylesheet.css images/logo.png scripts/main.js

is.gd/appcachetut

Web workers

main.js
var worker = new Worker('doWork.js'); worker.addEventListener('message', function(e) { console.log('Worker said: ', e.data); }, false); worker.postMessage('Hello World'); // Send data to our worker.
doWork.js
self.addEventListener('message', function(e) { self.postMessage('I heard: ' + e.data); }, false);

is.gd/webworkertut

Web sockets

var connection = new WebSocket("ws://echo.websocket.org/");
connection.onopen = function () {
  connection.send("Hello there");
};
connection.onmessage = function (e) {
  alert("Got message: " + e.data);
};

is.gd/websocketstut

The server side

Node.js: JS on the server

var http = require("http");

http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}).listen(8888);

"Everything runs in parallel, except your code"

nodebeginner.org | is.gd/nodeeventloop

Node.js: Not just for servers

npmjs.org

NoSQL data stores

redis.io | mongodb.org | couchdb.apache.org

Tools and resources

In-browser tools

Command-line tools

twitter.github.com/bower | gruntjs.com | yeoman.io

Unit testing

qunitjs.com | pivotal.github.com/jasmine | visionmedia.github.com/mocha

Languages that compile to JS

CoffeeScript
square = (x) -> x * x cube = (x) -> square(x) * x
JavaScript
var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; };
CoffeeScript
cubes = (math.cube num for num in list)
JavaScript
cubes = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = list.length; _i < _len; _i++) { num = list[_i]; _results.push(math.cube(num)); } return results; })();

coffeescript.org | typescriptlang.org

Documentation and other resources

Editors

github.com/adobe/brackets

Thanks!

is.gd/webdesignhipster
is.gd/webdevhipster
github.com/njx/presos

Built with reveal.js

Extras

JavaScript for Smarties

or, coding without a net

Classes

Objects

Functions

Prototypes

Objects

JavaScript
var myObject = { name: "Narciso Jaramillo", birthday: new Date(1932, 10, 5), address: { street: "123 Anywhere Place", city: "Somewhere", zip: 92153 } }; myObject.newProp = "some value";

Functions and closures

var fetchNewContent = function(url, container) {
  $.ajax(url, {
    success: function(data) {
      $(container).html(data);
    }
  });
}

Modules

Counter.countUp();
Counter.countUp();
Counter.getCount(); // 2
var Counter = (function() {
  var count = 1; // private
  
  return {
    countUp: function() {
      count++;
    },

    getCount: function() {
      return count;
    }
  };
})();

is.gd/jsnamespacing | is.gd/jsmoduleinfo | requirejs.org

"Methods": What is "this"?

var obj1 = { val: 100 },
    obj2 = { val: 200 };

function log() { 
  console.log(this.val); 
}
log(); // error: "val" is undefined
                    
obj1.log = obj2.log = log;

obj1.log(); // 100
obj2.log(); // 200

Beware of "this"

HTML
<input id="myButton" value="Click Me">
JavaScript
var myButton = { elt: document.getElementById("myButton"), value: "myValue", handleClick: function() { alert(this.value); }, init: function() { this.elt.onclick = this.handleClick; } }; myButton.init(); myButton.handleClick(); // works, this === myButton // but clicking on the button shows "Click Me" // because this === elt

Using "bind"

var myButton = {
  element: document.getElementById(‘myButton’),
  value: ‘myValue’,

  handleClick: function() {
    alert(this.value);
  }

  init: function() {
    this.element.onclick = this.handleClick.bind(this);
  }
};

j.mp/jsscope | is.gd/jsgarden

Trick for anonymous handlers

var myButton = {
  element: document.getElementById(‘myButton’),
  value: ‘myValue’,

  init: function() {
    var self = this;
    this.element.onclick = function() {
      alert(self.value);
    };
  }
};

j.mp/jsscope | is.gd/jsgarden

Prototypes

var Counter = function() {
  this.counter = 1;
};

Counter.prototype.countUp = function() {
  this.counter++;
};

Counter.prototype.getCount = function() {
  return this.counter;
};

var myCounter = new Counter();
myCounter.countUp();

j.mp/jsproto

Mixins

var debugMixin = {
  log: function () {
    console.log(this.toString());
  },
  alert: function () {
    alert(this.toString());
  }
};

var myObj = {
  // ...
};
$.extend(myObj, debugMixin);
myObj.log();

Code reuse across objects

Prototypes: j.mp/jsproto

Mixins: is.gd/jsmixins

Unit testing

QUnit
test("countUp adds 1", function() { Counter.reset(); Counter.countUp(); equal(Counter.getCount(), 1); } );
Jasmine
it("should add 1", function() { Counter.reset(); Counter.countUp(); expect(Counter.getCount()) .toBe(1); } );

qunitjs.com | pivotal.github.com/jasmine

CoffeeScript

CoffeeScript
square = (x) -> x * x cube = (x) -> square(x) * x
JavaScript
var cube, square; square = function(x) { return x * x; }; cube = function(x) { return square(x) * x; };
CoffeeScript
cubes = (math.cube num for num in list)
JavaScript
cubes = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = list.length; _i < _len; _i++) { num = list[_i]; _results.push(math.cube(num)); } return results; })();

Backbone: Lightweight MV(C)

var Todo = Backbone.Model.extend({
  defaults: {
    title: "empty todo..."
  }
});

var TodoView = Backbone.View.extend({
  initialize: function() {
    this.listenTo(this.model, "change", this.render);
  },
  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
  }
});
var myTodo = new Todo({ title: "Buy milk" });
var myTodoView = new TodoView({ model: myTodo });
$("#todolist").append(myTodoView.render().$el);
myTodo.set("title", "Buy lowfat milk"); // view will update

backbonejs.org | knockoutjs.com | angularjs.org