JavaScript for Flex Devs

80
JavaScript

description

JavaScript for Flex DevsPresented by Aaron Hardy (http://aaronhardy.com) at 360|Flex 2012 in Denver, CO.

Transcript of JavaScript for Flex Devs

Page 1: JavaScript for Flex Devs

JavaScript

Page 2: JavaScript for Flex Devs

Software Engineer, Adobe Digital Marketing Suite We enable management, measurement, execution, and

optimization of digital advertising and marketing.

HELLO my name is

@AARONIUS AARONHARDY.COM ·

Page 3: JavaScript for Flex Devs

No hidden agenda

Page 4: JavaScript for Flex Devs

Single-Page Apps

Page 5: JavaScript for Flex Devs

DataGrid

DataGroup

List

CurrencyFormatter TabBar

Slider Panel

Accordion ViewStack

ToggleButtonBar

EventDispatcher ArrayCollection

Bindable

NumericStepper

DragManager

Effects

Page 6: JavaScript for Flex Devs

Main (Application)

Header (Group)

AccountInfo (Group)

Music (ViewStack)

Artist (Group)

Menu (ToggleButtonBar)

Discography (DataGroup)

Discussion (DataGroup)

Biography (Group)

Similar Artists (List)

Page 7: JavaScript for Flex Devs

Basic Form Elements Div

Span

Links

? ?

? ?

? Image

?

Bulleted Lists

Page 8: JavaScript for Flex Devs

<html> <head> <script> buckets of vomit buckets of vomit buckets of vomit buckets of vomit buckets of vomit </script> </head> <body> buckets of vomit buckets of vomit buckets of vomit buckets of vomit buckets of vomit </body> </html>

Page 9: JavaScript for Flex Devs

• IDEs • MVC • Widgets/Components • Dependency management • DOM manipulation • Templating • Testing • Utilities • JavaScript + HTML + CSS

Page 10: JavaScript for Flex Devs

Quality ide

Page 11: JavaScript for Flex Devs

Libraries

Presenter
Presentation Notes
Is the product part of a larger suite? What is the rest of the suite using? How hard would it be for us to refactor to another library? Is it a fad or popular for good reason? What’s the community like? How open-source is it? What’s the learning curve? How easy is it to hire developers that want to work with it?
Page 12: JavaScript for Flex Devs

Rolling your own

Page 13: JavaScript for Flex Devs

jquery underscore.js

backbone.js requirejs

All MIT license (+ other options) and on GitHub

Page 14: JavaScript for Flex Devs

Learn Javascript

Page 15: JavaScript for Flex Devs

Never build large apps The secret to building large apps is NEVER build large apps. Break up your applications into small pieces. Then, assemble those testable, bite-sized pieces into your big application. – Justin Meyer

Page 16: JavaScript for Flex Devs

Admit what you don’t know

The key is to acknowledge from the start that you have no idea how this will grow. When you accept that you don’t know everything, you begin to design the system defensively. – Nicholas Zakas

Page 17: JavaScript for Flex Devs

Add "use strict"; before code or at beginning of function to help decrapify your code.

• Eliminates pitfalls by raising errors • Improves JS engine optimization • Prohibits syntax reserved for future JS versions * Won’t be used in examples to save slide space

Page 18: JavaScript for Flex Devs

JSLint or JSHint. • Run in IDE. • Run on command line. • Run in build scripts. • Copy-paste into web interface. • Use flags for configuration.

Page 19: JavaScript for Flex Devs

General community style: • Names of directories and files shall be lowercase and

hyphens shall be used to separate words. • Variable names shall be camelCase. • Classes (functions) to be instantiated shall start with a

capital letter. • Members intended to be private shall be prefixed with

an underscore.

Page 20: JavaScript for Flex Devs

Loose typing == more testing! • JsTestDriver • QUnit • Jasmine • Vows • …and bucket-loads more

Page 21: JavaScript for Flex Devs

jquery

Page 22: JavaScript for Flex Devs

• Not an application framework! • Abstracts the DOM

• Style • Position • Behavior • Animation • Creation/Removal

• AJAX requests • Utilities for objects, arrays, strings, etc. • “Framework” for UI widgets and utilities

Page 23: JavaScript for Flex Devs

Usage by Top Sites

http://trends.builtwith.com/javascript/jQuery

Page 24: JavaScript for Flex Devs

• Performance-tuned servers • Allows browser to have more concurrent connections • Cross-site caching

Page 25: JavaScript for Flex Devs

Toolbox of array, object, and function manipulation utilities.

var names = _.pluck( [{name: 'moe', age: 40}, {name: 'larry', age: 50}], 'name'); var person = _.extend({name: 'moe'}, {age: 50}); var uniques = _.union([1, 2, 3], [101, 2, 10], [2, 1]);

And bucket-loads more…

Page 26: JavaScript for Flex Devs

Old-school var tweetTemplate = '' + '<div>' + '<div style="float: left">' + '<img src="' + avatar + '"/>' + '</div>' + '<div style="margin-left: 60px">' + '<p>' + username + '</p>' + '<p>' + text + '</p>' + '</div>' + '<div>';

Page 27: JavaScript for Flex Devs

Old-school • HTML buried in logic (hard to re-skin) • Concatenation/escaping takes time and is error-prone • IDE might not code-hint or color-code properly • Boring and tedious

Page 28: JavaScript for Flex Devs

New-school <script type="text/template" id="tweet-template"> <div> <div style="float: left"> <img src="<%= avatar %>"/> </div> <div style="margin-left: 60px"> <p><%= username %></p> <p><%= text %></p> </div> </div> </script> <script> var tweet = {avatar: 'aaronius.jpg', alias: '@Aaronius', text: 'Honey roasted peanuts rock my sox.'}; var template = _.template($('#tweet-template').html()); var html = template(tweet); var element = $(html); </script>

Presenter
Presentation Notes
How to handle many templates.
Page 29: JavaScript for Flex Devs

• Mustache.js • Handlebars.js • Jade • Eco • …and bucket-loads more. Underscore.js templating is one of the best (though not as full-featured) and is a dependency of Backbone.js. You can use any templating engine.

Page 30: JavaScript for Flex Devs

backbone

Presenter
Presentation Notes
MV* Application Framework Non-prescriptive 1200 lines of code (with comments) Extensible
Page 31: JavaScript for Flex Devs

Object A passes a function to object B and tells object B to call the function when X occurs. When X occurs, object B calls the function.

Page 32: JavaScript for Flex Devs

backbone.events

Presenter
Presentation Notes
Like EventDispatcher
Page 33: JavaScript for Flex Devs

var baby = new Baby(); var changeDeuceTrap = function() { baby.deuces = 0; baby.cakeHoleShut = true; }; baby.on('turdDropped', changeDeuceTrap); Baby:

this.trigger('turdDropped');

Dad:

Page 34: JavaScript for Flex Devs

Mix into any object or class var baby = new Baby(); baby = _.extend(baby, Backbone.Events); baby.on(…); baby.trigger(…);

Page 35: JavaScript for Flex Devs

backbone.Model

Presenter
Presentation Notes
Like [Bindable] model
Page 36: JavaScript for Flex Devs

Plain Old JavaScript Object var book = { title: 'A Tale of Two Cities', author: 'Charles Dickens', genre: 'historical', publisher: 'Chapman & Hall' };

How can another object know when one of book’s values changes? It can’t!

Page 37: JavaScript for Flex Devs

Eventful Backbone.Model var book = new Backbone.Model({ title: 'A Tale of Two Cities', author: 'Charles Dickens', genre: 'historical', publisher: 'Chapman & Hall' }); book.on('change:genre', function(model, genre) { alert('genre for ' + model.get('title') + ' changed to ' + genre); }); book.set({genre: 'social criticism'});

Page 38: JavaScript for Flex Devs

Extending Backbone.Model var Book = Backbone.Model.extend({ …custom model logic… }); var book = new Book({ title: 'A Tale of Two Cities', author: 'Charles Dickens', publisher: 'Chapman & Hall' });

Page 39: JavaScript for Flex Devs

Persistence HTTP Method URL Action

GET /books Retrieve all books

GET /books/10 Retrieve book with id == 10

POST /books Add a book

PUT /books/10 Update book with id == 10

DELETE /books/10 Delete book with id == 10

Page 40: JavaScript for Flex Devs

Persistence (save) var Book = Backbone.Model.extend({ urlRoot: '/books' }); var book = new Book({title: 'The Tragedy of the Commons'}); book.save();

Page 41: JavaScript for Flex Devs

Persistence (fetch) var Book = Backbone.Model.extend({ urlRoot: '/books' }); var book = new Book({id: 2}); var fetchSuccess = function() { alert(book.get('title')); }; book.fetch({success: fetchSuccess});

Page 42: JavaScript for Flex Devs
Page 43: JavaScript for Flex Devs
Page 44: JavaScript for Flex Devs

MODEL layersOpen

characterOpen magicWandOpen

colorOpen infoOpen

Page 45: JavaScript for Flex Devs

And more… • Validation • Extracting native object • Determine which attributes have changed • And bucket-loads more…

Page 46: JavaScript for Flex Devs

backbone.collection

Presenter
Presentation Notes
Like ArrayCollection
Page 47: JavaScript for Flex Devs

Plain Old JavaScript Array: var books = [book1, book2, book3, book4];

How can another object know when an item is added or removed from this array? It can’t!

Page 48: JavaScript for Flex Devs

var goodEarth = new Backbone.Model(); var books = new Backbone.Collection(); books.on('add', function(book, books, options) { alert('Book ' + book.get('title') + ' added at index ' + options.at + '. ' + 'The collection now contains ' + books.length + ' models.'); }; books.on('remove', function(book, books, options) { alert('Book ' + book.get('title') + ' removed from index ' + options.index); } books.add(goodEarth); books.remove(goodEarth);

Page 49: JavaScript for Flex Devs

var books = new Backbone.Collection([taleOfTwoCities, goodEarth]); books.on('change:title', function(book, title) { alert('Book title changed from ' + book.previous('title') + ' to ' + title); }); goodEarth.set({title: 'Good Earth, The'});

Event Pass-through

Presenter
Presentation Notes
Similar to PropertyChangeEvent
Page 50: JavaScript for Flex Devs

Persistence (fetch) var Books = Backbone.Collection.extend({ model: Book, url: '/books' }); var books = new Books(); books.fetch();

Page 51: JavaScript for Flex Devs

Underscore mix-ins var titles = books.pluck('title');

each(), reduce(), find(), filter(), reject(), shuffle(), without() and bucket-loads more!

Page 52: JavaScript for Flex Devs

And more… • Sorting • Resetting • Retrieving model by id or index • Custom loading and parsing • …and bucket-loads more!

Page 53: JavaScript for Flex Devs

Backbone view

Page 54: JavaScript for Flex Devs
Page 55: JavaScript for Flex Devs
Presenter
Presentation Notes
Case Study: Update view when tweet is sent
Page 56: JavaScript for Flex Devs

Tweet Model

Tweet Collection

Tweet

Tweet

Tweet

Tweet

Tweet

Tweet

Stats Model

Presenter
Presentation Notes
Case Study: Update view when tweet is sent
Page 57: JavaScript for Flex Devs

var Tweet = Backbone.Model.extend({ …view logic… }); var TweetRow = Backbone.View.extend({ …view logic… }); var tweet = new Tweet({ avatar: 'aaronius.jpg', alias: '@Aaronius', text: 'Honey roasted peanuts rock my sox.' }); var row = new TweetRow({ model: tweet });

Page 58: JavaScript for Flex Devs

var TweetRow = Backbone.View.extend({ _template: _.template($('#tweet-row-template').html()), initialize: function() { this.render(); }, render: function() { this.$el.html(this._template(this.model.toJSON())); return this; } });

<script type="text/template" id="tweet-row-template"> <div style="float: left"><img src="<%= avatar %>"/></div> <div style="margin-left: 60px"> <p><%= username %></p> <p><%= text %></p> </div> </script>

Presenter
Presentation Notes
Significance of this.el
Page 59: JavaScript for Flex Devs

Backbone router

Page 60: JavaScript for Flex Devs

backbone extensions

Page 61: JavaScript for Flex Devs

requirejs

Page 62: JavaScript for Flex Devs

Must we be restricted to working inside a few monstrous spaghetti files? NO! Then why are they so prevalent? • “That’s the way JavaScript has been done in the past.” • “Loading many JavaScript files requires many HTTP

requests resulting in longer load times.” • “Dependency management is hard in JavaScript.” We can do better!

Page 63: JavaScript for Flex Devs

// What are the dependencies here!? // What if a new employee had to re-order for some reason!? <script src="script3.js"></script> <script src="script1.js"></script> <script src="script7.js"></script> <script src="script6.js"></script> <script src="script4.js"></script> <script src="script5.js"></script> <script src="script9.js"></script> <script src="script8.js"></script> <script src="script10.js"></script> <script src="script2.js"></script>

Old school

Page 64: JavaScript for Flex Devs

script4.js

script5.js script6.js script9.js

script10.js script7.js

script8.js script1.js

script2.js

script3.js

Page 65: JavaScript for Flex Devs

ServerJS CommonJS Module Async module definition (AMD) RequireJS

Presenter
Presentation Notes
Kevin Dangoor
Page 66: JavaScript for Flex Devs

define({ title: "My Sister's Keeper", publisher: "Atria" });

book.js

define([ 'book' ], function(book) { return { listBook: function() { alert(book.title); } }; });

bookshelf.js

Page 67: JavaScript for Flex Devs

<!DOCTYPE html> <html> <head> <title>RequireJS Example</title> <script data-main="js/main“ src="js/libs/require.js"></script> </head> <body/> </html>

index.html

require([ 'bookshelf' ], function(bookshelf) { bookshelf.listBook(); });

main.js

Page 68: JavaScript for Flex Devs

<span class="label">Title:</span> <span class="value"><%= title %></span><br/> <span class="label">Author:</span> <span class="value"><%= author %></span><br/> <span class="label">Genre:</span> <span class="value"><%= genre %></span>

templates/book.tpl.html

Page 69: JavaScript for Flex Devs

define([ 'backbone', 'underscore', 'text!templates/book.tpl.html' ], function(Backbone, _, template) { return Backbone.View.extend({ _template: _.template(template), initialize: function() { this.render(); }, render: function() { var nativeBook = this.model.toJSON(); var html = this._template(nativeBook); this.$el.html(html); return this; } }); });

book-view.js

Page 70: JavaScript for Flex Devs

define([ 'backbone', 'underscore', 'book-view' ], function(Backbone, _, BookView) { return Backbone.View.extend({ … create child book views as necessary … … new BookView() … }); });

bookshelf-view.js

Page 71: JavaScript for Flex Devs

requirejs optimization

Page 72: JavaScript for Flex Devs

Thank you!

@Aaronius aaronhardy.com

Page 73: JavaScript for Flex Devs

encore (stuff I fit in if time allows)

Page 74: JavaScript for Flex Devs

Persistence with custom url pattern: var Book = Backbone.Model.extend({ urlRoot: '/books', url: function() { return this.urlRoot + '?id=' + this.get('id'); } }) var book = new Book({id: 2}); book.fetch();

Page 75: JavaScript for Flex Devs

var App = Backbone.View.extend({ initialize: function() { this.render(); }, render: function() { var tweet = new Tweet({ avatar: 'avatar.jpg', username: '@Aaronius', text: 'Honey roasted peanuts rock my sox.' }); var row = new TweetRow({ model: tweet }); this.$el.append(row.$el); return this; } }); var app = new App({el: $('body')});

Page 76: JavaScript for Flex Devs

var DocumentView = Backbone.View.extend({ events: { "dblclick" : "open", "click .icon.doc" : "select", "mouseover .title .date" : "showTooltip" }, render: function() { ... }, open: function() { ... }, select: function() { ... }, showTooltip: function() { ... }, });

Page 77: JavaScript for Flex Devs

<script type="text/javascript"> $(function() { var AppRouter = Backbone.Router.extend({ routes: { "shirt/id/:id": "showShirt" }, showShirt: function(id) { alert('Show shirt with id ' + id); } }); var appRouter = new AppRouter(); Backbone.history.start(); }); </script> <a href="#shirt/id/5">Shirt with id of 5</a><br> <a href="#shirt/id/10">Shirt with id of 10</a><br> <a href="#shirt/id/15">Shirt with id of 15</a><br>

Page 78: JavaScript for Flex Devs

<script type="text/javascript"> $(function() { var AppRouter = Backbone.Router.extend({ routes: { ":product/:attribute/:value": "showProduct" }, showProduct: function(product, attribute, value) { alert('Show ' + product + ' where ' + attribute + ' = ' + value + '.'); } }); var appRouter = new AppRouter(); Backbone.history.start(); }); </script> <a href="#shoe/size/12">Size 12 shoes</a><br> <a href="#shirt/id/5">Shirt with id of 5</a><br> <a href="#hat/color/black">Black hats</a>

Page 79: JavaScript for Flex Devs

var AppRouter = Backbone.Router.extend({ routes: { ":product/:attribute/:value": "showProduct" } }); var MyView = Backbone.View.extend({ initialize: function(options) { options.router.on('route:showProduct', this._showProduct); } _showProduct: function(product, attribute, value) { alert('Update to show ' + product + ' where ' + attribute + ' = ' + value + '.'); } }); var appRouter = new AppRouter(); var view = new MyView({router: appRouter}); Backbone.history.start();

Page 80: JavaScript for Flex Devs

Fragment Identifier • Using URLs in unintended ways • Dependent on JavaScript • Controversial • Used by many popular sites pushState aka HTML5 History • The bee’s knees • Allows changing of core url without changing pages • Long-term solution • Browser support lacking (guess which browser)