Pro Yearly is on sale from $80 to $50! »

Introducing Backbone.js

Introducing Backbone.js

Backbone.js fundamentals with models, collections, views and their interaction (change event - rendering), to really understand what's going and how it helps you manage JavaScript application complexity.

Demo code for this talk can be found at: https://github.com/toonketels/backbone-presentation-demo

Presented at:
* DrupalCampLeuven - 2013.09.15 - Leuven, Belgium
* Drupal User Group @ Wunderkraut - 2013.07.11 - Antwerp, Belgium
* DrupalJam - 2013.05.17 - Rotterdam, the Netherlands.

2aacf6307821d3301fac1f47a214307b?s=128

Toon Ketels

July 11, 2013
Tweet

Transcript

  1. / Toon Ketels @toonketels

  2. Drupal Developer backbone.js - d3.js - grunt.js @toonketels

  3. What is Backbone Models Collections Views Wrap up

  4. None
  5. Backbone.js gives structure to web applications by providing models with

    key- value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface. backbonejs.org
  6. structure models collections views connect to backend over JSON

  7. None
  8. angular.js ember.js spine.js knockout.js sammy.js

  9. None
  10. marionette.js chaplin.js vertebrae.js backbone boilerplate thorax

  11. underscore.js / lo-dash.js json2.js jQuery / Zepto

  12. None
  13. None
  14. the fundamental building blocks of backbone how they relate together

    how they help you structure your code
  15. How to use Backbone and Drupal Tutorial on building your

    first backbone app
  16. Let's focus on understanding the fundamentals, so we can hack

    existing apps, know were everything goes and don't curse backbone.js for all the complexity it adds, 'cause... it is making our lives easier.
  17. Committed and pushed to 8.x webchick

  18. n e w B a c k b o n

    e . M o d e l ( )
  19. None
  20. Models are the heart of any JavaScript application, containing the

    interactive data as well as a large part of the logic surrounding it: conversions, validation, computed properties, and access control. backbonejs.org/#Model
  21. An object to group data and functions related to the

    data together.
  22. node user post comment

  23. None
  24. v a r t o o n = n e

    w B a c k b o n e . M o d e l ( { n a m e : " T o o n K e t e l s " , a g e : 3 0 , j o b : " D e v e l o p e r " , b i o : " < p > S c r u m m a s t e r , b a c k e n d D r u p a l d e v e l o p e r . < / p > " , u i d : 7 5 4 4 } ) ;
  25. { _ c h a n g i n g

    : f a l s e , _ p e n d i n g : f a l s e , _ p r e v i o u s A t t r i b u t e s : { / * . . . * / } , _ a t t r i b u t e s : { / * . . . * / } , c h a n g e d : { / * . . . * / } , c i d : " c i d " } ;
  26. None
  27. t o o n . h a s ( '

    a g e ' ) ; t o o n . g e t ( ' a g e ' ) ; t o o n . e s c a p e ( ' b i o ' ) ;
  28. t o o n . s e t ( '

    a g e ' , 3 1 ) ; t o o n . c h a n g e d ; t o o n . p r e v i o u s A t t r i b u t e s ( ) ;
  29. Hey, I've changed!

  30. t o o n . o n ( ' c

    h a n g e ' , f u n c t i o n ( m o d e l ) { c o n s o l e . l o g ( ' c h a n g e d ' ) ; c o n s o l e . l o g ( m o d e l ) ; } ) ;
  31. t o o n . o n ( ' c

    h a n g e : a g e ' , f u n c t i o n ( m o d e l , v a l u e ) { c o n s o l e . l o g ( ' A g e h a s h a n g e d ' ) ; c o n s o l e . l o g ( m o d e l ) ; c o n s o l e . l o g ( v a l u e ) ; } ) ;
  32. None
  33. v a r P e r s o n =

    B a c k b o n e . M o d e l . e x t e n d ( { / / C u s t o m m e t h o d s } ) ; v a r t o o n = n e w P e r s o n ( { . . . } ) ;
  34. None
  35. v a r P e r s o n =

    B a c k b o n e . M o d e l . e x t e n d ( { i n i t i a l i z e : f u n c t i o n ( ) { c o n s o l e . l o g ( ' I r u n o n s t a r t u p ' ) ; } } ) ;
  36. v a r P e r s o n =

    B a c k b o n e . M o d e l . e x t e n d ( { d e f a u l t s : { c o u n t r y : " B e l g i u m " , p r o f e s s i o n : " A n a l y s t " } } ) ;
  37. v a r P e r s o n =

    B a c k b o n e . M o d e l . e x t e n d ( { v a l i d a t e : f u n c t i o n ( a t t r i b u t e s , o p t i o n s ) { i f ( t y p e o f a t t r i b u t e s . a g e ! = = " n u m b e r " ) { r e t u r n " A g e s h o u l d b e a n u m b e r " ; } } } ) ;
  38. t o o n . s e t ( '

    a g e ' , ' n o n e ' ) ; t o o n . i s V a l i d ( ) ; / / f a l s e t o o n . v a l i d a t i o n E r r o r ; / / " A g e s h o u l d b e a n u m b e r " t o o n . s e t ( ' a g e ' , ' n o n e ' , { v a l i d a t e : t r u e } ) ;
  39. v a r P e r s o n =

    B a c k b o n e . M o d e l . e x t e n d ( { i d A t t r i b u t e : ' u i d ' } ) ;
  40. v a r P e r s o n =

    B a c k b o n e . M o d e l . e x t e n d ( { i d A t t r i b u t e : ' u i d ' , u r l R o o t : ' u s e r ' } ) ;
  41. v a r t o o n = n e

    w P e r s o n ( { u i d : 1 } ) ; t o o n . f e t c h ( ) ; t o o n . s e t ( ' a g e ' , 3 1 ) ; t o o n . s a v e ( ) ;
  42. None
  43. Create a model Get/set attributes, previousAttributes Emit events Subclass Defaults

    Validate ID & url fetch & save
  44. Separation data/functionality Tie data related functions related together with the

    data No polling, get alerted on changes (events) Easy communication with server
  45. n e w B a c k b o n

    e . C o l l e c t i o n ( )
  46. None
  47. Collections are ordered sets of models. backbonejs.org/#Collection

  48. Users Latest articles Articles promoted to frontpage All pages All

    nodes
  49. Controls on a slideshow Main menu links Pager in search

    results
  50. None
  51. v a r C o w o r k e

    r s = B a c k b o n e . C o l l e c t i o n . e x t e n d ( { m o d e l : P e r s o n } ) ;
  52. v a r s o u r c e =

    [ { n a m e : " T o o n K e t e l s " , a g e : 3 0 , j o b : " D e v e l o p e r " , b i o : " < p > S c r u m m a s t e r , b a c k e n d D r u p a l d e v e l o p e r . < / p > " , u i d : 7 5 4 4 , i d : ' t k - 7 5 4 4 - c o r l ' } , { n a m e : " A n K a t r i e n " , a g e : 2 3 , c o u n t r y : " t h e N e t h e r l a n d s " , b i o : " < p > W o r k s i n G e r m a n y . L o v e s t o g a m b l e . < / p > " , u i d : 3 4 0 0 , i d : ' a k - 3 4 0 0 - c o r l ' } ,
  53. v a r c o w o r k e

    r s = n e w C o w o r k e r s ( s o u r c e ) ;
  54. { _ b y I d : O b j

    e c t , l e n g t h : 3 , m o d e l s : A r r a y [ 3 ] }
  55. None
  56. c o w o r k e r s .

    a t ( 1 ) ; c o w o r k e r s . g e t ( 4 1 0 ) ; c o w o r k e r s . w h e r e ( { c o u n t r y : " t h e N e t h e r l a n d s " } ) ;
  57. None
  58. v a r s o m e o n e

    = c o w o r k e r s . a t ( 1 ) ; c o w o r k e r s . r e m o v e ( s o m e o n e ) ;
  59. v a r n o o b = n e

    w P e r s o n ( { n a m e : " D r i e s G a a s t r a " , a g e : 1 9 , c o u n t r y : " t h e N e t h e r l a n d s " , j o b : " T h e m e r " , b i o : " < p > P l a y s w i t h c s s a n d j a v a s c r i p t a l l d a y l o n g . < / p > " , u i d : 9 0 1 6 , i d : ' d g - 9 0 1 6 - c o r l ' } ) ; c o w o r k e r s . a d d ( n o o b ) ;
  60. v a r C o w o r k e

    r s = B a c k b o n e . C o l l e c t i o n . e x t e n d ( { m o d e l : P e r s o n , c o m p a r a t o r : ' a g e ' } ) ;
  61. c o w o r k e r s .

    c o m p a r a t o r = f u n c t i o n ( m o d e l ) { r e t u r n m o d e l . g e t ( ' n a m e ' ) ; } c o w o r k e r s . s o r t ( ) ; c o w o r k e r s . c o m p a r a t o r = ' c o u n t r y ' ; c o w o r k e r s . s o r t ( ) ;
  62. Hey, I've been sorted!

  63. c o w o r k e r s .

    o n ( ' s o r t ' , f u n c t i o n ( m o d e l , v a l u e ) { / / . . . } ) ;
  64. c o w o r k e r s .

    o n ( ' c h a n g e : a g e ' , f u n c t i o n ( m o d e l , v a l u e ) { / / . . . } ) ;
  65. c o w o r k e r s .

    o n ( ' a l l ' , f u n c t i o n ( ) { c o n s o l e . l o g ( ' e v e n t e m i t t e d ' ) ; c o n s o l e . l o g ( a r g u m e n t s ) ; } ) ;
  66. v a r C o w o r k e

    r s = B a c k b o n e . C o l l e c t i o n . e x t e n d ( { m o d e l : P e r s o n , u r l : ' u s e r ' } ) ; v a r c o w o r k e r s = n e w C o w o r k e r s ( ) ; c o w o r k e r s . f e t c h ( { d a t a : { p a g e : 1 } } ) ;
  67. Create a collection Get models Add/remove models Sort Emit events

    Fetch entire collection from server
  68. Organize sets of models into groups Tie collection related functions

    together with the collection Emit events and aggregate events of models. We no longer need pointers to all the models Easy communication with server
  69. n e w B a c k b o n

    e . V i e w ( )
  70. None
  71. Views are objects which do two things: 1) display data

    (most of the time models) and 2) capture user interaction to trigger code.
  72. List of blogposts A blogpost A button to paginate

  73. None
  74. root DOM element node v a r v i e

    w = n e w B a c k b o n e . V i e w ( { e l : $ ( ' # m a i n ' ) } ) ;
  75. None
  76. v a r P e r s o n V

    i e w = B a c k b o n e . V i e w . e x t e n d ( { c l a s s N a m e : ' p e r s o n - v i e w ' , } ) ; v a r v i e w = n e w P e r s o n V i e w ( ) ;
  77. The view is just an empty div.

  78. v a r P e r s o n V

    i e w = B a c k b o n e . V i e w . e x t e n d ( { c l a s s N a m e : ' p e r s o n - v i e w ' , r e n d e r : f u n c t i o n ( ) { t h i s . $ e l . h t m l ( ' < h 2 > T o o n K e t e l s < / h 2 > ' ) ; r e t u r n t h i s ; } } ) ;
  79. A.K.A. How to insert it into the DOM?

  80. v a r v i e w = n e

    w P e r s o n V i e w ( ) ; $ ( ' # m a i n ' ) . a p p e n d ( v i e w . r e n d e r ( ) . e l ) ;
  81. Not the same old string every time again...

  82. v a r t o o n = n e

    w P e r s o n ( { n a m e : " T o o n K e t e l s " , a g e : 3 0 , j o b : " D e v e l o p e r " , b i o : " < p > S c r u m m a s t e r , b a c k e n d D r u p a l d e v e l o p e r . < / p > " , u i d : 7 5 4 4 , i d : ' t k - 7 5 4 4 - c o r l ' } ) ; v a r v i e w = n e w P e r s o n V i e w ( { m o d e l : t o o n } ) ;
  83. v a r P e r s o n V

    i e w = B a c k b o n e . V i e w . e x t e n d ( { ' c l a s s N a m e ' : ' p e r s o n - v i e w ' , r e n d e r : f u n c t i o n ( ) { v a r c o n t e n t = ' < h 2 > ' + t h i s . m o d e l . g e t ( ' n a m e ' ) + ' < / h 2 > ' ; t h i s . $ e l . h t m l ( c o n t e n t ) ; r e t u r n t h i s ; } } ) ;
  84. The model has changed, the view not.

  85. v a r P e r s o n v

    i e w = B a c k b o n e . V i e w . e x t e n d ( { ' c l a s s N a m e ' : ' p e r s o n - v i e w ' , i n i t i a l i z e : f u n c t i o n ( ) { t h i s . m o d e l . o n ( ' c h a n g e ' , t h i s . r e n d e r ) ; } , r e n d e r : f u n c t i o n ( ) { v a r c o n t e n t = ' < h 2 > ' + t h i s . m o d e l . g e t ( ' n a m e ' ) + ' < / h 2 > ' ; t h i s . $ e l . h t m l ( c o n t e n t ) ; r e t u r n t h i s ; } } ) ;
  86. t h i s . m o d e l

    . o n ( ' c h a n g e ' , t h i s . r e n d e r ) ; t h i s . l i s t e n T o ( t h i s . m o d e l , ' c h a n g e ' , t h i s . r e n d e r ) ;
  87. My eyes hurt, it's ugly!

  88. _ . t e m p l a t e

    ( )
  89. < s c r i p t t y p

    e = " t e x t / t e m p l a t e " i d = " p e r s o n - v i e w " > < / s c r i p t > < h 2 > < % = n a m e % > < / h 2 > < p > < s p a n c l a s s = " j o b " > < % = j o b % > < / s p a n > | < s p a n c l a s s = " c o u n t r y " < d i v c l a s s = " c o n t r o l s " > < s p a n c l a s s = ' m o r e ' > M o r e < / s p a n > < s p a n c l a s s < d i v c l a s s = " b i o h i d e " > < % = b i o % > < / d i v >
  90. v a r P e r s o n v

    i e w = B a c k b o n e . V i e w . e x t e n d ( { ' c l a s s N a m e ' : ' p e r s o n - v i e w ' , i n i t i a l i z e : f u n c t i o n ( ) { t h i s . l i s t e n T o ( t h i s . m o d e l , ' c h a n g e ' , t h i s . r e n d e r ) ; } , t e m p l a t e : _ . t e m p l a t e ( $ ( ' # p e r s o n - v i e w ' ) . h t m l ( ) ) , r e n d e r : f u n c t i o n ( ) { v a r c o n t e n t = t h i s . t e m p l a t e ( t h i s . m o d e l . t o J S O N ( ) ) ; t h i s . $ e l . h t m l ( c o n t e n t ) ; r e t u r n t h i s ; } } ) ;
  91. t e m p l a t e : _

    . t e m p l a t e ( $ ( ' # p e r s o n - v i e w ' ) . h t m l ( ) ) , v a r c o n t e n t = t h i s . t e m p l a t e ( t h i s . m o d e l . t o J S O N ( ) ) ;
  92. Views are also about capturing user intent, aren't they?

  93. e v e n t s

  94. v a r P e r s o n V

    i e w = B a c k b o n e . V i e w . e x t e n d ( { / / . . . e v e n t s : { ' c l i c k . m o r e ' : ' s h o w M o r e ' , ' c l i c k . l e s s ' : ' s h o w L e s s ' , ' c l i c k h 2 ' : ' g o T o D e t a i l ' , ' m o u s e o v e r ' : ' s t a r t H i g h l i g h t ' , ' m o u s e o u t ' : ' s t o p H i g h l i g h t ' } , s h o w M o r e : f u n c t i o n ( e v e n t ) { / / . . . } , s h o w L e s s : f u n c t i o n ( e v e n t ) {
  95. Person is selected. Selected is a "state", no?

  96. v a r P e r s o n V

    i e w = B a c k b o n e . V i e w . e x t e n d ( { / / . . . e v e n t s : { ' c l i c k h 2 ' : ' s e l e c t P e r s o n ' , / / . . . } , s e l e c t P e r s o n : f u n c t i o n ( e v e n t ) { i f ( t h i s . m o d e l . g e t ( ' s e l e c t e d ' ) ) { t h i s . m o d e l . s e t ( ' s e l e c t e d ' , f a l s e ) ; } e l s e { t h i s . m o d e l . s e t ( ' s e l e c t e d ' , t r u e ) ; } } ,
  97. Going back and forth

  98. User clicks `h2` title View calls `selectPerson` Function will toggle

    the `selected` attribute of the model Model emits `change` event Since the view's render function is tied to this event, `render` get's called Render takes the model's attributes (some of them were just updated) and displays itself with the updated values.
  99. What you get when data and representation are separate...

  100. < s c r i p t t y p

    e = " t e x t / t e m p l a t e " i d = " l i s t - v i e w " > < / s c r i p t > < t d > < % - t i t l e % > < t d > < t d > < s p a n c l a s s = " l a b e l l a b e l - i n f o " < % - s e l e c t e d % > < / s p a n > < / t d
  101. v a r T a b l e R o

    w V i e w = B a c k b o n e . V i e w . e x t e n d ( { t a g N a m e : ' t r ' , i n i t i a l i z e : f u n c t i o n ( ) { t h i s . l i s t e n T o ( t h i s . m o d e l , ' c h a n g e : s e l e c t e d ' , t h i s . r e n d e r ) ; t h i s . l i s t e n T o ( t h i s . m o d e l , ' c h a n g e : n a m e ' , t h i s . r e n d e r ) ; } , t e m p l a t e : _ . t e m p l a t e ( $ ( ' # t a b l e - r o w - v i e w ' ) . h t m l ( ) ) , r e n d e r : f u n c t i o n ( ) { v a r c o n t e n t = { s e l e c t e d : t h i s . m o d e l . g e t ( ' s e l e c t e d ' ) ? ' s e l e c t e d ' : ' ' , t i t l e : t h i s . m o d e l . g e t ( ' n a m e ' ) } ; t h i s . $ e l . h t m l ( t h i s . t e m p l a t e ( c o n t e n t ) ) ;
  102. 1. one model, two views 2. view updates itself 3.

    a different view updates the model
  103. Create a view Set its contents Insert it into the

    DOM Pass models so the content is dynamic Auto update its display when model changes Use templates Catch user interaction with "events" property
  104. All user interaction goes via Views, in its events hash

    Separate data (model) from display (view) allows us to have multiple displays Templates keep the views code tidy By binding to model change event, the view automatically gets updated.
  105. By binding to model change event, a view automatically gets

    updated. A view does not care who updates the model or how. One view can update the display of another view via a model, without even knowing it.
  106. None
  107. Models Collections Views

  108. None
  109. By binding to model change event, the view automatically gets

    updated. The view does not care who updates the model or how.
  110. None
  111. A view binds to the collections change event to automatically

    updated itself. A view does not care who updates the collection or how. One view can update the display of another view via a collection, without even knowing it.
  112. None
  113. None