Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Single Page Web    ApplicationsCoffeeScript + Backbone.js + Jasmine BDD             @pirelenito        github.com/pireleni...
Who am I?
What can you expect?• What I am doing?• Why is CoffeeScript so awesome?• The era before Backbone;• Fix browser spaghetti c...
Assumptions• You know your Javascript;• and your JQuery;• You developed for the web before.
What I am doing?
Fullscreen MapGeo CRUDsNo refreshes
Fullscreen MapGeo CRUDsNo refreshesCoffeeScriptBackbone.js
Fullscreen Map            Geo CRUDs            No refreshes            CoffeeScript            Backbone.js     JSONRest AP...
Why is CoffeeScript so      awesome?
I like to choose my        tools!
I can to that on the       Server!
Browser?Javascript Only!
Browser?Javascript Only!NO MOAR!
Too error-prone.
Semicolon insertionreturn     return {{             a: 10   a: 10   };};
Semicolon insertionreturn ;   return {{             a: 10   a: 10   };};
Global variablesfunction messWithGlobal() {  a = 10;}
Global variablesfunction messWithGlobal() {  a = 10;}messWithGlobal();alert(a);
Global variablesfunction messWithGlobal() {  a = 10;}messWithGlobal();alert(a);
Global variablesfunction messWithGlobal() {  a = 10;}messWithGlobal();alert(a);function messWithGlobal() {  var a = 10;}
}  square = function(x) {     return x * x;  };  list = [1, 2, 3, 4, 5];  math = {     root: Math.sqrt,   Too verbose!    ...
Awesome platform.
“I Think Coffeescript is   clearly good stuff”                       Douglas Crockford             Javascript Programming ...
Remember this?return     return {{             a: 10   a: 10   };};
Coffeescript:return       return a: 10  a: 10
Coffeescript:return       return a: 10  a: 10  It has no semicolon!
How it fixes globals?
Never write var again! messWithGlobal = ->   a = 10
Never write var again! messWithGlobal = ->   a = 10messWithGlobal = function() {   var a;   return a = 10;};
Compiles with scopea = 10
Compiles with scopea = 10(function() {  var a;  a = 10;}).call(this);
You want global?           Go explicit!window.messWithGlobal = ->  a = 10
You want global?           Go explicit!window.messWithGlobal = ->  a = 10(function() {  window.messWithGlobal = function()...
Functions as callbacks$(.button).click(function() {  return alert(clicked!);});
Functions as callbacks$(.button).click(function() {  return alert(clicked!);});$(.button).click -> alert clicked!
Block by identation if (somethingIsTrue) {   complexMath = 10 * 3; }
Block by identation if (somethingIsTrue) {   complexMath = 10 * 3; } if somethingIsTrue   complexMath = 10 * 3
Classesclass MyClass  attribute: value  constructor: ->    @objectVariable = Dude  myMethod: ->    # this.objectVariable  ...
Classesclass MyClass  attribute: value  constructor: ->    @objectVariable = Dude  myMethod: ->    # this.objectVariable  ...
Compiled class:(function() {  var MyClass;  MyClass = (function() {    MyClass.prototype.attribute = value;    function My...
Rangeslist = [1..5]
Rangeslist = [1..5]var list;list = [1, 2, 3, 4, 5];
Expressions!vehicles = for i in [1..3]  "Vehicle#{i}"
Expressions!vehicles = for i in [1..3]  "Vehicle#{i}"vehicles[Vehicle1, Vehicle2, Vehicle3]
More awesomeness...number = -42 if oppositemath =  square:   (x) -> x * xrace = (winner, runners...) ->  print winner, run...
Don’t use --bare
Namespaces are coolclass namespace(views).MyView
Namespaces are coolclass namespace(views).MyViewnew oncast.views.MyView()
Namespaces are coolclass namespace(views).MyViewnew oncast.views.MyView()@.namespace = (name) ->  @.oncast ||= {}  return ...
No more hidden bugs on my client code!
CoffeeScript will makeyou a better Javascript     programer.
The era before  Backbone.
Rails did the rendering           Rails        Coffeescript
Rails did the rendering                           Rails$(.new).load "/cars/new", prepare                       Coffeescript
Rails did the rendering                           Rails$(.new).load "/cars/new", prepare                       Coffeescript
Rails did the rendering                           Rails                                      <form>                       ...
Rails did the rendering                           Rails                                      <form>                       ...
Advantages• Simple;• Used tools we knew;• i18n.
Coffeescript ActionsActionActivationHandler    One active at timeEditRefAction         ListRefAction      ...
Mapped an action onour Rail’s Controller
Action Abstraction• Would handle the ‘remote’ rendering;• Initialize the rich components on the  DOM;• JQuery heavy.
Problems?
One Action at a time!
Difficult to keep thinks        in sync.
Difficult to keep thinks        in sync.   No real state on the browser.
Slow (web 1.0)
“Not surprisingly, were finding  ourselves solving similar   problems repeatedly.”                                         ...
Fix browser spaghetticode with Backbone.
Why Backbone?
Gives enough structure
Very lightweight
Easy to get started!
Why not GWT(for instance)?
Doesn’t hide the DOM You are doing real web development.
Works nicely with CoffeeScript  Inheritance. https://github.com/documentcloud/backbone/blob/master/test/model.coffee
Works nicely with  CoffeeScript   Inheritance.class Car extends Backbone.Model    https://github.com/documentcloud/backbon...
Ok, but what is it?
Four Abstractions• Collection;• Model;• Router;• View;
Models / Collectionsclass Reference extends Backbone.Model  urlRoot: "/references"
Models / Collectionsclass Reference extends Backbone.Model  urlRoot: "/references"class References extends Backbone.Collec...
Fetch Collection# creates a new collectionreferences = new References# fetch data asynchronouslyreferences.fetch()
Fetch Collection# creates a new collectionreferences = new References# fetch data asynchronouslyreferences.fetch()        ...
Model attributes
Model attributes# get reference with id 1reference = references.get 1
Model attributes# get reference with id 1reference = references.get 1# get the name property of the modelname = reference....
Model attributes# get reference with id 1reference = references.get 1# get the name property of the modelname = reference....
Model attributes# get reference with id 1reference = references.get 1# get the name property of the modelname = reference....
Why use model.set ?reference.set name: new name
Events!reference.bind change, (name)-> alert name
Events!reference.bind change, (name)-> alert namereference.set name: new name
Events!reference.bind change, (name)-> alert namereference.set name: new name
Viewsclass SaveButtonView extends Backbone.View  className: save-button  tagName: div  events:    click: _click  render: -...
Viewsclass SaveButtonView extends Backbone.View  className: save-button  tagName: div  events:    click: _click  render: -...
Viewsclass SaveButtonView extends Backbone.View  className: save-button  tagName: div  events:    click: _click  render: -...
Viewsclass SaveButtonView extends Backbone.View  className: save-button  tagName: div  events:    click: _click  render: -...
Viewsclass SaveButtonView extends Backbone.View  className: save-button  tagName: div  events:    click: _click  render: -...
Viewsclass SaveButtonView extends Backbone.View  className: save-button  tagName: div  events:    click: _click  render: -...
Using a View
Using a View# creates a new instance of the viewview = new SaveButtonView()
Using a View# creates a new instance of the viewview = new SaveButtonView()# render itview.render()
Using a View# creates a new instance of the viewview = new SaveButtonView()# render itview.render()# append the content of...
‘Events’ is the magic     element!
‘Events’ is the magic     element!   They will keep you in sync!
View   Model
Click!View     Model
Click!         event changes the modelView                               Model
Click!           model.set name: new name         event changes the modelView                               Model
Click!           model.set name: new name         event changes the modelView                               Model         ...
Click!               model.set name: new name            event changes the modelView                                  Mode...
Routersclass ReferencesRouter extends Backbone.Router  routes:    references: index  initialize: (options)->    @listPanel...
Routersclass ReferencesRouter extends Backbone.Router  routes:    references: index  initialize: (options)->    @listPanel...
Routersclass ReferencesRouter extends Backbone.Router  routes:    references: index  initialize: (options)->    @listPanel...
This is just the basics!
Lessons Learned
DOM is not always  your friend!
DOM is not always         your friend!# will be 0 unless it is attached to the# document$(@el).height()
Always do       view.render()        Before$(.some-div).html view.el
Always return this.
Always return this.new SaveButtonView().highlight().render().el
Routers should only      route!
Routers should only         route!index: ->  @listPanelView.renderReferences()
You don’t need anAction abstraction!!!
The View will represent one model/collection       forever!
Broken events# append the views element to the document$(.div).append view.el# remove it$(.div).empty# add it again$(.div)...
Collection.getOrFetchclass Posts extends Backbone.Collection  url: "/posts"  getOrFetch: (id) ->    if @get(id)      post ...
View.fetchBackbone.View::fetch = (options={})->  return @ unless (@collection || @model) _(options).extend   complete: => ...
View.fetchBackbone.View::fetch = (options={})->  return @ unless (@collection || @model) _(options).extend   complete: => ...
Lazy fetchingclass LazyFetchView extends Backbone.View  render: ->    if @model.isFullyFetched()      # if the data is rea...
Be professional: with   Jasmine BDD.
Why Jasmine?
BDD
BDDrspec like!
given a delete button viewwhen the user clicks the viewthen it should delete the model
Jasmine:              given a delete button view              when the user clicks the view              then it should de...
describe DeleteButton, -> context when the user clicks the view, =>   it should delete the model
describe DeleteButton, -> context when the user clicks the view, =>   it should delete the model, =>     expect(@model.del...
describe DeleteButton, -> context when the user clicks the view, =>   it should delete the model, =>     expect(@model.del...
describe DeleteButton, ->  beforeEach =>    @model = new Backbone.Model    @deleteButton = new DeleteButton(model: @model)...
describe DeleteButton, ->  beforeEach =>    @model = new Backbone.Model    @deleteButton = new DeleteButton(model: @model)...
describe DeleteButton, ->  beforeEach =>    @model = new Backbone.Model    @deleteButton = new DeleteButton(model: @model)...
Run it headless!      Text       http://johnbintz.github.com/jasmine-headless-webkit/
http://tinnedfruit.com/2011/03/03/testing-backbone-apps-                  with-jasmine-sinon.html
Further reading• https://github.com/creationix/haml-js• https://github.com/fnando/i18n-js• http://documentcloud.github.com...
So long and thanks for      all the fish!         @pirelenito     github.com/pirelenito      about.me/pirelenito
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Upcoming SlideShare
Loading in …5
×

Single Page Web Applications with CoffeeScript, Backbone and Jasmine

37,386 views

Published on

Published in: Technology, Education
  • Dating direct: ♥♥♥ http://bit.ly/2Q98JRS ♥♥♥
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating for everyone is here: ♥♥♥ http://bit.ly/2Q98JRS ♥♥♥
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD FULL. BOOKS INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD FULL. BOOKS INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD FULL BOOKS INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... 1.DOWNLOAD FULL PDF EBOOK here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL EPUB Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL doc Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL PDF EBOOK here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL EPUB Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... 1.DOWNLOAD FULL doc Ebook here { https://tinyurl.com/y8nn3gmc } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Single Page Web Applications with CoffeeScript, Backbone and Jasmine

  1. 1. Single Page Web ApplicationsCoffeeScript + Backbone.js + Jasmine BDD @pirelenito github.com/pirelenito #tdc2011
  2. 2. Who am I?
  3. 3. What can you expect?• What I am doing?• Why is CoffeeScript so awesome?• The era before Backbone;• Fix browser spaghetti code with Backbone;• Be professional: with Jasmine BDD;
  4. 4. Assumptions• You know your Javascript;• and your JQuery;• You developed for the web before.
  5. 5. What I am doing?
  6. 6. Fullscreen MapGeo CRUDsNo refreshes
  7. 7. Fullscreen MapGeo CRUDsNo refreshesCoffeeScriptBackbone.js
  8. 8. Fullscreen Map Geo CRUDs No refreshes CoffeeScript Backbone.js JSONRest API Ruby on Rails
  9. 9. Why is CoffeeScript so awesome?
  10. 10. I like to choose my tools!
  11. 11. I can to that on the Server!
  12. 12. Browser?Javascript Only!
  13. 13. Browser?Javascript Only!NO MOAR!
  14. 14. Too error-prone.
  15. 15. Semicolon insertionreturn return {{ a: 10 a: 10 };};
  16. 16. Semicolon insertionreturn ; return {{ a: 10 a: 10 };};
  17. 17. Global variablesfunction messWithGlobal() { a = 10;}
  18. 18. Global variablesfunction messWithGlobal() { a = 10;}messWithGlobal();alert(a);
  19. 19. Global variablesfunction messWithGlobal() { a = 10;}messWithGlobal();alert(a);
  20. 20. Global variablesfunction messWithGlobal() { a = 10;}messWithGlobal();alert(a);function messWithGlobal() { var a = 10;}
  21. 21. } square = function(x) { return x * x; }; list = [1, 2, 3, 4, 5]; math = { root: Math.sqrt, Too verbose! square: square, cube: function(x) { return x * square(x); } }; race = function() { var runners, winner; winner = arguments[0], runners = 2 <=arguments.length ? __slice.call(arguments,1) : []; return print(winner, runners); };
  22. 22. Awesome platform.
  23. 23. “I Think Coffeescript is clearly good stuff” Douglas Crockford Javascript Programming Style And Your Brain
  24. 24. Remember this?return return {{ a: 10 a: 10 };};
  25. 25. Coffeescript:return return a: 10 a: 10
  26. 26. Coffeescript:return return a: 10 a: 10 It has no semicolon!
  27. 27. How it fixes globals?
  28. 28. Never write var again! messWithGlobal = -> a = 10
  29. 29. Never write var again! messWithGlobal = -> a = 10messWithGlobal = function() { var a; return a = 10;};
  30. 30. Compiles with scopea = 10
  31. 31. Compiles with scopea = 10(function() { var a; a = 10;}).call(this);
  32. 32. You want global? Go explicit!window.messWithGlobal = -> a = 10
  33. 33. You want global? Go explicit!window.messWithGlobal = -> a = 10(function() { window.messWithGlobal = function() { var a; return a = 10; };}).call(this);
  34. 34. Functions as callbacks$(.button).click(function() { return alert(clicked!);});
  35. 35. Functions as callbacks$(.button).click(function() { return alert(clicked!);});$(.button).click -> alert clicked!
  36. 36. Block by identation if (somethingIsTrue) { complexMath = 10 * 3; }
  37. 37. Block by identation if (somethingIsTrue) { complexMath = 10 * 3; } if somethingIsTrue complexMath = 10 * 3
  38. 38. Classesclass MyClass attribute: value constructor: -> @objectVariable = Dude myMethod: -> # this.objectVariable @objectVariable
  39. 39. Classesclass MyClass attribute: value constructor: -> @objectVariable = Dude myMethod: -> # this.objectVariable @objectVariableobject = new MyClassobject.myMethod()object.objectVariable # Dudeobject.attribute
  40. 40. Compiled class:(function() { var MyClass; MyClass = (function() { MyClass.prototype.attribute = value; function MyClass() { this.objectVariable = Dude; } MyClass.prototype.myMethod = function() { return this.objectVariable; }; return MyClass; })();}).call(this);
  41. 41. Rangeslist = [1..5]
  42. 42. Rangeslist = [1..5]var list;list = [1, 2, 3, 4, 5];
  43. 43. Expressions!vehicles = for i in [1..3] "Vehicle#{i}"
  44. 44. Expressions!vehicles = for i in [1..3] "Vehicle#{i}"vehicles[Vehicle1, Vehicle2, Vehicle3]
  45. 45. More awesomeness...number = -42 if oppositemath = square: (x) -> x * xrace = (winner, runners...) -> print winner, runnersalert "I knew it!" if elvis?squares = (math.square num for num in list)
  46. 46. Don’t use --bare
  47. 47. Namespaces are coolclass namespace(views).MyView
  48. 48. Namespaces are coolclass namespace(views).MyViewnew oncast.views.MyView()
  49. 49. Namespaces are coolclass namespace(views).MyViewnew oncast.views.MyView()@.namespace = (name) -> @.oncast ||= {} return @.oncast[name] ||= {} if name return @.oncast
  50. 50. No more hidden bugs on my client code!
  51. 51. CoffeeScript will makeyou a better Javascript programer.
  52. 52. The era before Backbone.
  53. 53. Rails did the rendering Rails Coffeescript
  54. 54. Rails did the rendering Rails$(.new).load "/cars/new", prepare Coffeescript
  55. 55. Rails did the rendering Rails$(.new).load "/cars/new", prepare Coffeescript
  56. 56. Rails did the rendering Rails <form> <input name=name> ... </form>$(.new).load "/cars/new", prepare Coffeescript
  57. 57. Rails did the rendering Rails <form> <input name=name> ... </form>$(.new).load "/cars/new", prepare Coffeescript
  58. 58. Advantages• Simple;• Used tools we knew;• i18n.
  59. 59. Coffeescript ActionsActionActivationHandler One active at timeEditRefAction ListRefAction ...
  60. 60. Mapped an action onour Rail’s Controller
  61. 61. Action Abstraction• Would handle the ‘remote’ rendering;• Initialize the rich components on the DOM;• JQuery heavy.
  62. 62. Problems?
  63. 63. One Action at a time!
  64. 64. Difficult to keep thinks in sync.
  65. 65. Difficult to keep thinks in sync. No real state on the browser.
  66. 66. Slow (web 1.0)
  67. 67. “Not surprisingly, were finding ourselves solving similar problems repeatedly.” Henrik Joreteghttp://andyet.net/blog/2010/oct/29/building-a-single-page-app-with-backbonejs-undersc/
  68. 68. Fix browser spaghetticode with Backbone.
  69. 69. Why Backbone?
  70. 70. Gives enough structure
  71. 71. Very lightweight
  72. 72. Easy to get started!
  73. 73. Why not GWT(for instance)?
  74. 74. Doesn’t hide the DOM You are doing real web development.
  75. 75. Works nicely with CoffeeScript Inheritance. https://github.com/documentcloud/backbone/blob/master/test/model.coffee
  76. 76. Works nicely with CoffeeScript Inheritance.class Car extends Backbone.Model https://github.com/documentcloud/backbone/blob/master/test/model.coffee
  77. 77. Ok, but what is it?
  78. 78. Four Abstractions• Collection;• Model;• Router;• View;
  79. 79. Models / Collectionsclass Reference extends Backbone.Model urlRoot: "/references"
  80. 80. Models / Collectionsclass Reference extends Backbone.Model urlRoot: "/references"class References extends Backbone.Collection model: Reference url: /references Model Model Model Collection
  81. 81. Fetch Collection# creates a new collectionreferences = new References# fetch data asynchronouslyreferences.fetch()
  82. 82. Fetch Collection# creates a new collectionreferences = new References# fetch data asynchronouslyreferences.fetch() [{ id: 1 JSON name: "Paulos House", latitude: 10, longitude: 15 }]
  83. 83. Model attributes
  84. 84. Model attributes# get reference with id 1reference = references.get 1
  85. 85. Model attributes# get reference with id 1reference = references.get 1# get the name property of the modelname = reference.get name
  86. 86. Model attributes# get reference with id 1reference = references.get 1# get the name property of the modelname = reference.get name# change the name property of the modelreference.set name: new name
  87. 87. Model attributes# get reference with id 1reference = references.get 1# get the name property of the modelname = reference.get name# change the name property of the modelreference.set name: new name# save the model to the serverreference.save()
  88. 88. Why use model.set ?reference.set name: new name
  89. 89. Events!reference.bind change, (name)-> alert name
  90. 90. Events!reference.bind change, (name)-> alert namereference.set name: new name
  91. 91. Events!reference.bind change, (name)-> alert namereference.set name: new name
  92. 92. Viewsclass SaveButtonView extends Backbone.View className: save-button tagName: div events: click: _click render: -> $(@el).html "<input type=button value=Save></input>" return @ _click: -> @model.save()
  93. 93. Viewsclass SaveButtonView extends Backbone.View className: save-button tagName: div events: click: _click render: -> $(@el).html "<input type=button value=Save></input>" return @ _click: -> @model.save()
  94. 94. Viewsclass SaveButtonView extends Backbone.View className: save-button tagName: div events: click: _click render: -> $(@el).html "<input type=button value=Save></input>" return @ _click: -> @model.save()
  95. 95. Viewsclass SaveButtonView extends Backbone.View className: save-button tagName: div events: click: _click render: -> $(@el).html "<input type=button value=Save></input>" return @ _click: -> @model.save()
  96. 96. Viewsclass SaveButtonView extends Backbone.View className: save-button tagName: div events: click: _click render: -> $(@el).html "<input type=button value=Save></input>" return @ _click: -> @model.save()
  97. 97. Viewsclass SaveButtonView extends Backbone.View className: save-button tagName: div events: click: _click render: -> $(@el).html "<input type=button value=Save></input>" return @ _click: -> @model.save()
  98. 98. Using a View
  99. 99. Using a View# creates a new instance of the viewview = new SaveButtonView()
  100. 100. Using a View# creates a new instance of the viewview = new SaveButtonView()# render itview.render()
  101. 101. Using a View# creates a new instance of the viewview = new SaveButtonView()# render itview.render()# append the content of the view on the doc$(.some-div).html view.el
  102. 102. ‘Events’ is the magic element!
  103. 103. ‘Events’ is the magic element! They will keep you in sync!
  104. 104. View Model
  105. 105. Click!View Model
  106. 106. Click! event changes the modelView Model
  107. 107. Click! model.set name: new name event changes the modelView Model
  108. 108. Click! model.set name: new name event changes the modelView Model event changes the view
  109. 109. Click! model.set name: new name event changes the modelView Model event changes the view keeps everything in sync
  110. 110. Routersclass ReferencesRouter extends Backbone.Router routes: references: index initialize: (options)-> @listPanelView = options.listPanelView index: -> @listPanelView.renderReferences()
  111. 111. Routersclass ReferencesRouter extends Backbone.Router routes: references: index initialize: (options)-> @listPanelView = options.listPanelView index: -> @listPanelView.renderReferences()
  112. 112. Routersclass ReferencesRouter extends Backbone.Router routes: references: index initialize: (options)-> @listPanelView = options.listPanelView index: -> @listPanelView.renderReferences()
  113. 113. This is just the basics!
  114. 114. Lessons Learned
  115. 115. DOM is not always your friend!
  116. 116. DOM is not always your friend!# will be 0 unless it is attached to the# document$(@el).height()
  117. 117. Always do view.render() Before$(.some-div).html view.el
  118. 118. Always return this.
  119. 119. Always return this.new SaveButtonView().highlight().render().el
  120. 120. Routers should only route!
  121. 121. Routers should only route!index: -> @listPanelView.renderReferences()
  122. 122. You don’t need anAction abstraction!!!
  123. 123. The View will represent one model/collection forever!
  124. 124. Broken events# append the views element to the document$(.div).append view.el# remove it$(.div).empty# add it again$(.div).append view.el View events (click, change) will no longer work.
  125. 125. Collection.getOrFetchclass Posts extends Backbone.Collection url: "/posts" getOrFetch: (id) -> if @get(id) post = @get id else post = new Post { id : id } @add post post.fetch() post http://bennolan.com/2011/06/10/backbone-get-or-fetch.html
  126. 126. View.fetchBackbone.View::fetch = (options={})-> return @ unless (@collection || @model) _(options).extend complete: => @removeLoading() @renderLoading() (@collection || @model).fetch options return @
  127. 127. View.fetchBackbone.View::fetch = (options={})-> return @ unless (@collection || @model) _(options).extend complete: => @removeLoading() @renderLoading() (@collection || @model).fetch options return @ view.fetch()
  128. 128. Lazy fetchingclass LazyFetchView extends Backbone.View render: -> if @model.isFullyFetched() # if the data is ready we render it $(@el).html ... else # otherwise we fetch the data # rendering the loading indicator @fetch() return @
  129. 129. Be professional: with Jasmine BDD.
  130. 130. Why Jasmine?
  131. 131. BDD
  132. 132. BDDrspec like!
  133. 133. given a delete button viewwhen the user clicks the viewthen it should delete the model
  134. 134. Jasmine: given a delete button view when the user clicks the view then it should delete the modeldescribe DeleteButtonView, -> context when the user clicks the view, => it should delete the model
  135. 135. describe DeleteButton, -> context when the user clicks the view, => it should delete the model
  136. 136. describe DeleteButton, -> context when the user clicks the view, => it should delete the model, => expect(@model.delete).toHaveBeenCalledOnce()
  137. 137. describe DeleteButton, -> context when the user clicks the view, => it should delete the model, => expect(@model.delete).toHaveBeenCalledOnce() http://sinonjs.org/ https://github.com/froots/jasmine-sinon
  138. 138. describe DeleteButton, -> beforeEach => @model = new Backbone.Model @deleteButton = new DeleteButton(model: @model) context when the user clicks the view, => it should delete the model, => expect(@model.delete).toHaveBeenCalledOnce()
  139. 139. describe DeleteButton, -> beforeEach => @model = new Backbone.Model @deleteButton = new DeleteButton(model: @model) context when the user clicks the view, => beforeEach => sinon.spy @model, delete it should delete the model, => expect(@model.delete).toHaveBeenCalledOnce()
  140. 140. describe DeleteButton, -> beforeEach => @model = new Backbone.Model @deleteButton = new DeleteButton(model: @model) context when the user clicks the view, => beforeEach => sinon.spy @model, delete @deleteButton.render() $(@deleteButton.el).click() it should delete the model, => expect(@model.delete).toHaveBeenCalledOnce()
  141. 141. Run it headless! Text http://johnbintz.github.com/jasmine-headless-webkit/
  142. 142. http://tinnedfruit.com/2011/03/03/testing-backbone-apps- with-jasmine-sinon.html
  143. 143. Further reading• https://github.com/creationix/haml-js• https://github.com/fnando/i18n-js• http://documentcloud.github.com/underscore/• https://github.com/velesin/jasmine-jquery
  144. 144. So long and thanks for all the fish! @pirelenito github.com/pirelenito about.me/pirelenito

×