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

Spine

Avatar for Alex MacCaw Alex MacCaw
October 04, 2011

 Spine

JavaScript MVC Framework

Avatar for Alex MacCaw

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)