Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spine

Alex MacCaw
October 04, 2011

 Spine

JavaScript MVC Framework

Alex MacCaw

October 04, 2011
Tweet

More Decks by Alex MacCaw

Other Decks in Programming

Transcript

  1. createBox(t, s): function{ return ['<div class="x-box-blue">', '<div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>',

    '<div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc"><h3>', t, '</h3>', s, '</div '<div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>', '</div>'].join(''); }, emailMultiple : function(){ " " if(!Aireo.multipleSelect()){ " " " return " " } " " var nodes = assetView.getSelectedNodes() " " var query_string = [] " " for(var i=0; i < nodes.length; i ++){ " " " var data = Aireo.lookup[nodes[i].id]; " " " if(data.is_folder){ " " " query_string.push('folders[]=' + data.id) " " " " } else { " " " query_string.push('assets[]=' + data.id) " " " } " " } " " Email.init(lc.multiple_file_folders, query_string.join('&'), '',true); " " }, " " emailSelected : function(e){ " " if(!Aireo.currentlySelectedObject){ " " " return; " " } " " if(Aireo.multipleSelect()){ " " " Aireo.emailMultiple() " " } else { " " if(Aireo.currentlySelectedObject){ " " " var data = Aireo.currentlySelectedObject; " " if(Aireo.currentlySelectedObject.type == 'folder'){ " " Email.init(data.name,data.id,'folders',false);" " " } " " else if(Aireo.currentlySelectedObject.type == 'asset') {" " " Email.init(data.name,data.id,'assets',false);" " " } " " }
  2. The Problem with JavaScript • No structure • No namespacing

    • No dependency management • No conventions • Poor JS implementations • Misunderstanding and ignorance
  3. MVC

  4. ?

  5. MVC

  6. 1.0

  7. Features • CoffeeScript (although not required) • MVC and ORM

    • Ajax and Local Storage • HTML5 History integration • Simple API • Excellent documentation
  8. class Task extends Spine.Model @configure "Task", "name", "done" @extend Spine.Model.Local

    @active: -> @select (item) -> !item.done @done: -> @select (item) -> !!item.done @destroyDone: -> rec.destroy() for rec in @done()
  9. class Task extends Spine.Model @configure "Task", "name", "done" @extend Spine.Model.Local

    @active: -> @select (item) -> !item.done @done: -> @select (item) -> !!item.done @destroyDone: -> rec.destroy() for rec in @done()
  10. class Task extends Spine.Model @configure "Task", "name", "done" @extend Spine.Model.Local

    @active: -> @select (item) -> !item.done @done: -> @select (item) -> !!item.done @destroyDone: -> rec.destroy() for rec in @done()
  11. @el

  12. <div class="item"> <input type="checkbox" <%- if @done: %>checked="checked"<% end %>>

    <span> <%= @name %> <a class="destroy"></a> </span> </div>
  13. <div class="item"> <input type="checkbox" <%- if @done: %>checked="checked"<% end %>>

    <span> <%= @name %> <a class="destroy"></a> </span> </div>
  14. <div class="item"> <input type="checkbox" <%- if @done: %>checked="checked"<% end %>>

    <span> <%= @name %> <a class="destroy"></a> </span> </div>
  15. <div class="item"> <input type="checkbox" <%- if @done: %>checked="checked"<% end %>>

    <span> <%= @name %> <a class="destroy"></a> </span> </div>
  16. class Tasks extends Spine.Controller events: 'click .item .destroy': 'destroy' constructor:

    -> Task.bind('refresh change', @render) render: => tasks = Task.all() @html require('views/tasks')(tasks) destroy: (e) -> task = $(e).item() task.destroy()
  17. class Tasks extends Spine.Controller events: 'click .item .destroy': 'destroy' constructor:

    -> Task.bind('refresh change', @render) render: => tasks = Task.all() @html require('views/tasks')(tasks) destroy: (e) -> task = $(e).item() task.destroy()
  18. class Tasks extends Spine.Controller events: 'click .item .destroy': 'destroy' constructor:

    -> Task.bind('refresh change', @render) render: => tasks = Task.all() @html require('views/tasks')(tasks) destroy: (e) -> task = $(e).item() task.destroy()
  19. class Tasks extends Spine.Controller events: 'click .item .destroy': 'destroy' constructor:

    -> Task.bind('refresh change', @render) render: => tasks = Task.all() @html require('views/tasks')(tasks) destroy: (e) -> task = $(e).item() task.destroy() 1. record is destroyed
  20. class Tasks extends Spine.Controller events: 'click .item .destroy': 'destroy' constructor:

    -> Task.bind('refresh change', @render) render: => tasks = Task.all() @html require('views/tasks')(tasks) destroy: (e) -> task = $(e).item() task.destroy() 1. record is destroyed 2. change callback is triggered
  21. class Tasks extends Spine.Controller events: 'click .item .destroy': 'destroy' constructor:

    -> Task.bind('refresh change', @render) render: => tasks = Task.all() @html require('views/tasks')(tasks) destroy: (e) -> task = $(e).item() task.destroy() 1. record is destroyed 2. change callback is triggered 3. tasks are re-rendered
  22. UX

  23. class ContactsCreate extends Panel # ... class ContactsList extends Panel

    constructor: -> super @addButton('Add Contact', @add) add: -> @navigate('/contacts/create', trans: 'right') class Contacts extends Spine.Controller constructor: -> super @list = new ContactsList @create = new ContactsCreate @routes '/contacts': (params) -> @list.active(params) '/contacts/create': (params) -> @create.active(params)
  24. class ContactsCreate extends Panel # ... class ContactsList extends Panel

    constructor: -> super @addButton('Add Contact', @add) add: -> @navigate('/contacts/create', trans: 'right') class Contacts extends Spine.Controller constructor: -> super @list = new ContactsList @create = new ContactsCreate @routes '/contacts': (params) -> @list.active(params) '/contacts/create': (params) -> @create.active(params)
  25. class ContactsCreate extends Panel # ... class ContactsList extends Panel

    constructor: -> super @addButton('Add Contact', @add) add: -> @navigate('/contacts/create', trans: 'right') class Contacts extends Spine.Controller constructor: -> super @list = new ContactsList @create = new ContactsCreate @routes '/contacts': (params) -> @list.active(params) '/contacts/create': (params) -> @create.active(params)
  26. class ContactsCreate extends Panel # ... class ContactsList extends Panel

    constructor: -> super @addButton('Add Contact', @add) add: -> @navigate('/contacts/create', trans: 'right') class Contacts extends Spine.Controller constructor: -> super @list = new ContactsList @create = new ContactsCreate @routes '/contacts': (params) -> @list.active(params) '/contacts/create': (params) -> @create.active(params)