JavaScript for Flex Devs
Upcoming SlideShare
Loading in...5
×
 

JavaScript for Flex Devs

on

  • 8,040 views

JavaScript for Flex Devs

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

Statistics

Views

Total Views
8,040
Views on SlideShare
1,706
Embed Views
6,334

Actions

Likes
9
Downloads
35
Comments
0

9 Embeds 6,334

http://aaronhardy.com 6319
http://webcache.googleusercontent.com 4
http://translate.googleusercontent.com 3
http://us-w1.rockmelt.com 2
http://prlog.ru 2
http://nodeslide.herokuapp.com 1
http://cloud.feedly.com 1
https://www.google.com 1
http://www.google.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • 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?
  • How to handle many templates.
  • MV* Application FrameworkNon-prescriptive1200 lines of code (with comments)Extensible
  • Like EventDispatcher
  • Like [Bindable] model
  • Like ArrayCollection
  • Similar to PropertyChangeEvent
  • Case Study: Update view when tweet is sent
  • Case Study: Update view when tweet is sent
  • Significance of this.el
  • Kevin Dangoor

JavaScript for Flex Devs JavaScript for Flex Devs Presentation Transcript

  • JavaScript
  • HELLO my name is @AARONIUS · AARONHARDY.COMSoftware Engineer, Adobe Digital Marketing Suite We enable management, measurement, execution, and optimization of digital advertising and marketing.
  • No hidden agenda
  • Single-Page Apps
  • TabBar CurrencyFormatter EventDispatcher List ArrayCollection DataGroupDragManager ToggleButtonBar Panel NumericStepper Slider ViewStack AccordionBindable DataGrid Effects
  • AccountInfo (Group) Header (Group) Menu (ToggleButtonBar) Main Biography(Application) (Group) Artist (Group) Similar Artists (List) Music Discography (ViewStack) (DataGroup) Discussion (DataGroup)
  • ? Links ? Basic Form ElementsDiv Image ? Bulleted Lists ? ? Span ?
  • <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>
  • • IDEs• MVC• Widgets/Components• Dependency management• DOM manipulation• Templating• Testing• Utilities• JavaScript + HTML + CSS
  • Quality ide
  • Libraries
  • Rolling your own
  • jquery underscore.js backbone.js requirejsAll MIT license (+ other options) and on GitHub
  • Learn Javascript
  • 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
  • Admit what you don’t knowThe key is to acknowledge from the start that youhave no idea how this will grow. When you acceptthat you don’t know everything, you begin todesign the system defensively.– Nicholas Zakas
  • Add "use strict"; before code or at beginning offunction 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
  • JSLint or JSHint.• Run in IDE.• Run on command line.• Run in build scripts.• Copy-paste into web interface.• Use flags for configuration.
  • 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.
  • Loose typing == more testing!• JsTestDriver• QUnit• Jasmine• Vows• …and bucket-loads more
  • jquery
  • • 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
  • Usage by Top Siteshttp://trends.builtwith.com/javascript/jQuery
  • • Performance-tuned servers• Allows browser to have more concurrent connections• Cross-site caching
  • Toolbox of array, object, and function manipulationutilities.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…
  • Old-schoolvar tweetTemplate = + <div> + <div style="float: left"> + <img src=" + avatar + "/> + </div> + <div style="margin-left: 60px"> + <p> + username + </p> + <p> + text + </p> + </div> + <div>;
  • 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
  • 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>
  • • Mustache.js• Handlebars.js• Jade• Eco• …and bucket-loads more.Underscore.js templating is one of the best (though not asfull-featured) and is a dependency of Backbone.js. You canuse any templating engine.
  • backbone
  • Object A passes a functionto object B and tellsobject B to call thefunction when Xoccurs. When Xoccurs, object B calls thefunction.
  • backbone.events
  • Dad:var baby = new Baby();var changeDeuceTrap = function() { baby.deuces = 0; baby.cakeHoleShut = true;};baby.on(turdDropped, changeDeuceTrap);Baby:this.trigger(turdDropped);
  • Mix into any object or classvar baby = new Baby();baby = _.extend(baby, Backbone.Events);baby.on(…);baby.trigger(…);
  • backbone.Model
  • Plain Old JavaScript Objectvar 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 valueschanges? It can’t!
  • Eventful Backbone.Modelvar 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});
  • Extending Backbone.Modelvar Book = Backbone.Model.extend({ …custom model logic…});var book = new Book({ title: A Tale of Two Cities, author: Charles Dickens, publisher: Chapman & Hall});
  • PersistenceHTTP Method URL ActionGET /books Retrieve all booksGET /books/10 Retrieve book with id == 10POST /books Add a bookPUT /books/10 Update book with id == 10DELETE /books/10 Delete book with id == 10
  • Persistence (save)var Book = Backbone.Model.extend({ urlRoot: /books});var book = new Book({title: The Tragedy of the Commons});book.save();
  • 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});
  • MODEL layersOpen characterOpenmagicWandOpen colorOpen infoOpen
  • And more…• Validation• Extracting native object• Determine which attributes have changed• And bucket-loads more…
  • backbone.collection
  • Plain Old JavaScript Array:var books = [book1, book2, book3, book4];How can another object know when an item is added orremoved from this array? It can’t!
  • 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);
  • Event Pass-throughvar 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});
  • Persistence (fetch)var Books = Backbone.Collection.extend({ model: Book, url: /books});var books = new Books();books.fetch();
  • Underscore mix-insvar titles = books.pluck(title);each(), reduce(), find(), filter(), reject(), shuffle(), without()and bucket-loads more!
  • And more…• Sorting• Resetting• Retrieving model by id or index• Custom loading and parsing• …and bucket-loads more!
  • Backbone view
  • Stats ModelTweetModel Tweet Tweet Tweet Collection Tweet Tweet Tweet Tweet
  • 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});
  • <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>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; }});
  • Backbone router
  • backbone extensions
  • requirejs
  • Must we be restricted to working inside a few monstrousspaghetti 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!
  • Old school// 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>
  • script8.js script4.js script3.js script1.jsscript2.js script10.js script7.jsscript9.js script5.js script6.js
  • ServerJS  CommonJS  Module  Async module definition (AMD)  RequireJS
  • book.jsdefine({ title: "My Sisters Keeper", publisher: "Atria"});bookshelf.jsdefine([ book], function(book) { return { listBook: function() { alert(book.title); } };});
  • index.html<!DOCTYPE html><html> <head> <title>RequireJS Example</title> <script data-main="js/main“ src="js/libs/require.js"></script> </head> <body/></html>main.jsrequire([ bookshelf], function(bookshelf) { bookshelf.listBook();});
  • templates/book.tpl.html<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>
  • book-view.jsdefine([ 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; } });});
  • bookshelf-view.jsdefine([ backbone, underscore, book-view], function(Backbone, _, BookView) { return Backbone.View.extend({ … create child book views as necessary … … new BookView() … });});
  • requirejs optimization
  • Thank you! @Aaroniusaaronhardy.com
  • encore(stuff I fit in if time allows)
  • 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();
  • 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)});
  • var DocumentView = Backbone.View.extend({ events: { "dblclick" : "open", "click .icon.doc" : "select", "mouseover .title .date" : "showTooltip" }, render: function() { ... }, open: function() { ... }, select: function() { ... }, showTooltip: function() { ... },});
  • <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>
  • <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>
  • 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();
  • Fragment Identifier• Using URLs in unintended ways• Dependent on JavaScript• Controversial• Used by many popular sitespushState aka HTML5 History• The bee’s knees• Allows changing of core url without changing pages• Long-term solution• Browser support lacking (guess which browser)