SlideShare a Scribd company logo
SINGLE PAGE APPS
      WITH
BACKBONE.JS & RAILS
      Prateek Dayal
     SupportBee.com
HOW I LEARNED TO STOP
      WORRYING
 AND LOVE JAVSCRIPT!
BUT I LOVE JQUERY!
VANILLA JQUERY IS GREAT
 FOR A SIMPLE WEBSITE
BUT YOU WANT TO BUILD A
SINGLE PAGE APPLICATION
Single Page Web Apps with Backbone.js and Rails
Unless you’re a really fastidious coder, some sort of
library to help structure large-scale JavaScript
applications is important -- it’s far too easy to
degenerate into nested piles of jQuery callbacks, all
tied to concrete DOM elements.

                                      Jeremy Ashkenas
;)
COMPLEX SINGLE PAGE APPS
         HAVE
Single Page Web Apps with Backbone.js and Rails
• All   of the client logic in Javascript
• All   of the client logic in Javascript

• Updates     to many parts of the UI on changes to
 data
• All   of the client logic in Javascript

• Updates     to many parts of the UI on changes to
 data

• Templating     on the client side
TO NOT GO CRAZY
BUILDING IT, YOU NEED
Single Page Web Apps with Backbone.js and Rails
•A   MVC like pattern to keep the code clean
•A   MVC like pattern to keep the code clean

•Atemplating language like HAML/ERB to easily
render view elements
•A   MVC like pattern to keep the code clean

•Atemplating language like HAML/ERB to easily
render view elements

•A   better way to manage events and callbacks
•A   MVC like pattern to keep the code clean

•Atemplating language like HAML/ERB to easily
render view elements

•A   better way to manage events and callbacks

•A   way to preserver browser’s back button
•A   MVC like pattern to keep the code clean

•A templating language like HAML/ERB to easily
 render view elements

•A   better way to manage events and callbacks

•A   way to preserver browser’s back button

• Easy Testing   :)
FORTUNATELY, THERE IS HELP!
SproutCore
Cappuccino
BUT THEY ARE BIG
AND HAVE A
LEARNING CURVE
Single Page Web Apps with Backbone.js and Rails
Single Page Web Apps with Backbone.js and Rails
• 3.9   kb packed and gzipped
• 3.9   kb packed and gzipped

• Only   dependency is underscore.js
• 3.9   kb packed and gzipped

• Only   dependency is underscore.js

• You    need jQuery or Zepto for Ajax
• 3.9   kb packed and gzipped

• Only   dependency is underscore.js

• You    need jQuery or Zepto for Ajax

• Annotated    source code
MVC
MODELS, VIEWS &
 COLLECTIONS
Single Page Web Apps with Backbone.js and Rails
MODELS
MODELS


• Data   is represented as Models
MODELS


• Data   is represented as Models

• Can   be Created, Validated, Destroyed & Persisted on Server
MODELS


• Data   is represented as Models

• Can   be Created, Validated, Destroyed & Persisted on Server

• Attribute   changes trigger a ‘change’ event
SB.Models.TicketSummary = Backbone.Model.extend({
  id: null,
  subject: null,
  name: 'ticket',
});
COLLECTIONS
COLLECTIONS

•A   collection of models
COLLECTIONS

•A   collection of models

• Triggers   events like add/remove/refresh
COLLECTIONS

•A   collection of models

• Triggers   events like add/remove/refresh

• Can   fetch models from a given url
COLLECTIONS

•A   collection of models

• Triggers   events like add/remove/refresh

• Can   fetch models from a given url

• Can keep the models sorted if you define a comparator
 function
SB.Collections.TicketList = Backbone.Collection.extend({
  model: SB.Models.TicketSummary,

  url: "/tickets",
  name: "tickets",

   initialize: function(models, options){
     // Init stuff if you want
   }
});
VIEWS
VIEWS



• They   are more like Rails’ Controllers
VIEWS



• They   are more like Rails’ Controllers

• Responsiblefor instantiating Collections and binding events
 that update the UI
SB.Views.TicketListView = Backbone.View.extend({

  tagName: 'ul',

  initialize: function(){

    this.ticketList = new SB.Collections.TicketList;

    _.bindAll(this, 'addOne', 'addAll');


    this.ticketList.bind('add', this.addOne);

    this.ticketList.bind('refresh', this.addAll);

    this.ticketList.bind('all', this.render);


    this.ticketList.fetch();

  },

  addAll: function(){

    this.ticketList.each(this.addOne);
  },

   addOne: function(ticket){

    var view = new SB.Views.TicketSummaryView({model:ticket});

    $(this.el).append(view.render().el);
   }
});
SB.Views.TicketSummary = Backbone.View.extend({

 
     
 
 
 
 
 
 
 
 
  initialize: function(){

 _.bind(this, 'render');

 if(this.model !== undefined){

      this.model.view = this;

 }
  },

 events: {

 'click': 'openTicket'
 },

 openTicket: function(){

 window.location = "#ticket/" + this.model.id;
 },

  render: function(){

 $(this.el).html(SB.Views.Templates['tickets/summary']
(this.model.toJSON()));

 return this;
  }

 
    
 
 
 
 
 
 
 
 
});
HANDLEBARS!
{{#ticket}}
  <div class="listing-cell name">
   <p>{{nameOrEmail requester}} ({{replies_count}})</p>
  </div>

  <div class="listing-cell subject">
    
 <a href="#{{id}}">
    
 {{#unread}}
    
 <b>{{subject}}</b>
    
 {{/unread}}
    
 {{^unread}}
    
 {{subject}}
    
 {{/unread}}
    
 </a>
  </div>
{{/ticket}}
URLS
URLS



• Collections   can have a url
URLS



• Collections   can have a url

• Models   can have a url or they can derive it from collection’s
 url
◦   create → POST   /collection
◦   read → GET   /collection[/id]
◦   update → PUT   /collection/id
◦   delete → DELETE   /collection/id
FINALLY, CONTROLLERS
Single Page Web Apps with Backbone.js and Rails
• Used   for setting up the routes
• Used   for setting up the routes

• You   can add new routes during runtime
SB.Controllers.AgentHome = Backbone.Controller.extend({
 routes: {

 "": "dashboard", // http://app_url

 ":id": "openTicket" // http://app_url#id
 },

    dashboard: function(){

      var view = new SB.Views.TicketListView;

      $("#ticket").hide();

      $("#list").html(view.el);

      $("#list").show();
    },

  openTicket: function(id){

 var view = new SB.Views.TicketView({model : new
SB.Models.Ticket({id : id})});

 $("#list").hide();

 $("#ticket").html(view.el);

 $("#ticket").show();
  }
});
window.controller = new SB.Controllers.AgentHome
Single Page Web Apps with Backbone.js and Rails
• Initiates   a new controller instance
• Initiates   a new controller instance

• which   matches the dashboard route
• Initiates   a new controller instance

• which   matches the dashboard route

• and   creates a instance of TicketListView
• Initiates   a new controller instance

• which   matches the dashboard route

• and   creates a instance of TicketListView

• and   a TicketList collection is created
Single Page Web Apps with Backbone.js and Rails
• TicketList
           collection fetches tickets and triggers the
 refresh event
• TicketList
           collection fetches tickets and triggers the
 refresh event

• Refresh handler renders a TicketSummary view for
 each ticket and adds it to the top level element
Single Page Web Apps with Backbone.js and Rails
• Every Ticket   Summary row has an onclick handler
• Every Ticket   Summary row has an onclick handler

• which   changes to url to #ticket_id
• Every Ticket   Summary row has an onclick handler

• which   changes to url to #ticket_id

• which   matches the openTicket route
SERVER SIDE
ActiveRecord::Base.include_root_in_json = false
Single Page Web Apps with Backbone.js and Rails
• Youcan use as_json to customize the json
 responses
• Youcan use as_json to customize the json
 responses

• Or   you can use Restfulie
• Youcan use as_json to customize the json
 responses

• Or   you can use Restfulie

• Restfulie   lets you easily put links in representations
 too
collection(@items, :root => "items") do |items|
    items.link "self", items_url

      items.members do |m, item|
          m.link :self, item_url(item)
          m.values { |values|
              values.name   item.name
          }
      end
end
NOT JUST FOR API BACKED
        MODELS
//window.AgentHomeController = new SB.Controllers.AgentHome;
window.mainView = new SB.Views.Main;
mainView.screens.add(new SB.Models.Screen({
  title: 'Dashboard',
  href: '#dashboard',
  listings: [

 {

 
       title: 'New Tickets',

 
       url: '/tickets?label=unanswered&replies=false'

 },

 {

 
       title: 'Ongoing Tickets',

 
       url: '/tickets?label=unanswered&replies=true'

 },

 {

 
       title: 'Starred Tickets',

 
       url: '/tickets?starred=true'

 }
   ]
}));
TESTING
JASMINE FTW!
beforeEach(function(){
   var ticket = new SB.Models.TicketSummary({id: 1,

 
     
 
 
 
 
 
 
 
 
 subject: "A Ticket",

 
     
 
 
 
 
 
 
 
 
 replies_count: 0,

 
     
 
 
 
 
 
 
 
 
 requester: {id : 1,

 
     
 
 
 
 
 
 
 
 
 email: 'requester@example.com',

 
     
 
 
 
 
 
 
 
 
 name: 'Requester',

 
     
 
 
 
 
 
 
 
 
 thumbnail: 'thumbnail-url'}

 
     
 
 
 
 
 
 
 
 
 });
   this.view = new SB.Views.TicketSummary({model: ticket});
   this.view.render();
});

it("should render a ticket summary correctly", function(){
   expect($(this.view.el)).toHaveText(/A Ticket/);
   expect($(this.view.el)).toHaveText(/Requester/);
});

it("should change the url on click", function(){
   var currentLoc = window.location.toString();
   $(this.view.el).click();
   expect(window.location.toString()).toBe(currentLoc + "ticket#1");
});
SINON FOR MOCKS/STUBS
beforeEach(function(){
  this.server = sinon.fakeServer.create();
  this.server.respondWith("GET", "/tickets_url_mock_server",

 
     
 
 
 
       [200, { "Content-Type": "application/json" },

 
     
 
 
 
 
 '{"tickets":[{"id": 1, "subject": "Ticket 1"},{"id": 2, "subject":
"Ticket 2"}]}'

 
     
 
 
 
 ]);
});

it("should instantiate view when tickets are fetched", function(){

  var viewMock = sinon.mock(SB.Views);

  viewMock.expects("TicketSummary").once().returns(new Backbone.View);
  viewMock.expects("TicketSummary").once().returns(new Backbone.View);

  var view = new SB.Views.TicketList({url: "/tickets_url_mock_server"});

   this.server.respond();
   viewMock.verify();
   expect($(view.render().el).children().length).toBe(2);
});
QUESTIONS?

prateek@supportbee.com
     @prateekdayal

  http://supportbee.com

More Related Content

What's hot (19)

KEY
Templates
soon
 
PDF
Angular JS blog tutorial
Claude Tech
 
PDF
Turn your spaghetti code into ravioli with JavaScript modules
jerryorr
 
ZIP
Presentation.Key
guesta2b31d
 
PDF
Silex Cheat Sheet
Andréia Bohner
 
PPTX
SharePoint and jQuery Essentials
Mark Rackley
 
PDF
Why I Love JSX!
Jay Phelps
 
PPTX
UI-Router
Loc Nguyen
 
PDF
Rails 3 overview
Yehuda Katz
 
DOCX
How routing works in angular js
codeandyou forums
 
PDF
Curso Symfony - Clase 4
Javier Eguiluz
 
PDF
Resource and view
Papp Laszlo
 
PDF
Rails MVC by Sergiy Koshovyi
Pivorak MeetUp
 
PPT
jQuery Performance Rules
nagarajhubli
 
PDF
Applications: A Series of States
Trek Glowacki
 
PPTX
Paypal REST api ( Japanese version )
Yoshi Sakai
 
KEY
Jarv.us Showcase — SenchaCon 2011
Chris Alfano
 
PDF
AngularJS vs. Ember.js vs. Backbone.js
Mark
 
PDF
Architecture, Auth, and Routing with uiRouter
Christopher Caplinger
 
Templates
soon
 
Angular JS blog tutorial
Claude Tech
 
Turn your spaghetti code into ravioli with JavaScript modules
jerryorr
 
Presentation.Key
guesta2b31d
 
Silex Cheat Sheet
Andréia Bohner
 
SharePoint and jQuery Essentials
Mark Rackley
 
Why I Love JSX!
Jay Phelps
 
UI-Router
Loc Nguyen
 
Rails 3 overview
Yehuda Katz
 
How routing works in angular js
codeandyou forums
 
Curso Symfony - Clase 4
Javier Eguiluz
 
Resource and view
Papp Laszlo
 
Rails MVC by Sergiy Koshovyi
Pivorak MeetUp
 
jQuery Performance Rules
nagarajhubli
 
Applications: A Series of States
Trek Glowacki
 
Paypal REST api ( Japanese version )
Yoshi Sakai
 
Jarv.us Showcase — SenchaCon 2011
Chris Alfano
 
AngularJS vs. Ember.js vs. Backbone.js
Mark
 
Architecture, Auth, and Routing with uiRouter
Christopher Caplinger
 

Similar to Single Page Web Apps with Backbone.js and Rails (20)

PPTX
Backbonejs for beginners
Divakar Gu
 
PPTX
Backbone.js
VO Tho
 
PDF
Viking academy backbone.js
Bert Wijnants
 
ODP
Javascript frameworks: Backbone.js
Soós Gábor
 
PDF
Introduction to Backbone.js for Rails developers
AoteaStudios
 
PDF
Understanding backbonejs
Nick Lee
 
PPTX
Planbox Backbone MVC
Acquisio
 
PDF
Backbone.js
Ivano Malavolta
 
PPTX
Creating Single Page Web App using Backbone JS
Akshay Mathur
 
PDF
Backbone.js
Omnia Helmi
 
PDF
Backbone js
Rohan Chandane
 
PPTX
Writing HTML5 Web Apps using Backbone.js and GAE
Ron Reiter
 
PPTX
Taming that client side mess with Backbone.js
Jarod Ferguson
 
PPT
Backbone.js
Knoldus Inc.
 
KEY
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
PDF
Javascript MVC & Backbone Tips & Tricks
Hjörtur Hilmarsson
 
KEY
MVC on the server and on the client
Sebastiano Armeli
 
PPTX
Bacbkone js
Артём Курапов
 
PDF
MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...
jaxconf
 
KEY
Backbone.js
Chris Neale
 
Backbonejs for beginners
Divakar Gu
 
Backbone.js
VO Tho
 
Viking academy backbone.js
Bert Wijnants
 
Javascript frameworks: Backbone.js
Soós Gábor
 
Introduction to Backbone.js for Rails developers
AoteaStudios
 
Understanding backbonejs
Nick Lee
 
Planbox Backbone MVC
Acquisio
 
Backbone.js
Ivano Malavolta
 
Creating Single Page Web App using Backbone JS
Akshay Mathur
 
Backbone.js
Omnia Helmi
 
Backbone js
Rohan Chandane
 
Writing HTML5 Web Apps using Backbone.js and GAE
Ron Reiter
 
Taming that client side mess with Backbone.js
Jarod Ferguson
 
Backbone.js
Knoldus Inc.
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
Javascript MVC & Backbone Tips & Tricks
Hjörtur Hilmarsson
 
MVC on the server and on the client
Sebastiano Armeli
 
MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...
jaxconf
 
Backbone.js
Chris Neale
 
Ad

Recently uploaded (20)

PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
Complete JavaScript Notes: From Basics to Advanced Concepts.pdf
haydendavispro
 
PDF
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
Blockchain Transactions Explained For Everyone
CIFDAQ
 
PDF
Timothy Rottach - Ramp up on AI Use Cases, from Vector Search to AI Agents wi...
AWS Chicago
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
PPTX
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
PDF
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
PPTX
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
PPTX
UiPath Academic Alliance Educator Panels: Session 2 - Business Analyst Content
DianaGray10
 
PDF
Python basic programing language for automation
DanialHabibi2
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
PDF
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
PDF
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
Complete JavaScript Notes: From Basics to Advanced Concepts.pdf
haydendavispro
 
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Blockchain Transactions Explained For Everyone
CIFDAQ
 
Timothy Rottach - Ramp up on AI Use Cases, from Vector Search to AI Agents wi...
AWS Chicago
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
UiPath Academic Alliance Educator Panels: Session 2 - Business Analyst Content
DianaGray10
 
Python basic programing language for automation
DanialHabibi2
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
Ad

Single Page Web Apps with Backbone.js and Rails

  • 1. SINGLE PAGE APPS WITH BACKBONE.JS & RAILS Prateek Dayal SupportBee.com
  • 2. HOW I LEARNED TO STOP WORRYING AND LOVE JAVSCRIPT!
  • 3. BUT I LOVE JQUERY!
  • 4. VANILLA JQUERY IS GREAT FOR A SIMPLE WEBSITE
  • 5. BUT YOU WANT TO BUILD A SINGLE PAGE APPLICATION
  • 7. Unless you’re a really fastidious coder, some sort of library to help structure large-scale JavaScript applications is important -- it’s far too easy to degenerate into nested piles of jQuery callbacks, all tied to concrete DOM elements. Jeremy Ashkenas
  • 8. ;)
  • 11. • All of the client logic in Javascript
  • 12. • All of the client logic in Javascript • Updates to many parts of the UI on changes to data
  • 13. • All of the client logic in Javascript • Updates to many parts of the UI on changes to data • Templating on the client side
  • 14. TO NOT GO CRAZY BUILDING IT, YOU NEED
  • 16. •A MVC like pattern to keep the code clean
  • 17. •A MVC like pattern to keep the code clean •Atemplating language like HAML/ERB to easily render view elements
  • 18. •A MVC like pattern to keep the code clean •Atemplating language like HAML/ERB to easily render view elements •A better way to manage events and callbacks
  • 19. •A MVC like pattern to keep the code clean •Atemplating language like HAML/ERB to easily render view elements •A better way to manage events and callbacks •A way to preserver browser’s back button
  • 20. •A MVC like pattern to keep the code clean •A templating language like HAML/ERB to easily render view elements •A better way to manage events and callbacks •A way to preserver browser’s back button • Easy Testing :)
  • 28. • 3.9 kb packed and gzipped
  • 29. • 3.9 kb packed and gzipped • Only dependency is underscore.js
  • 30. • 3.9 kb packed and gzipped • Only dependency is underscore.js • You need jQuery or Zepto for Ajax
  • 31. • 3.9 kb packed and gzipped • Only dependency is underscore.js • You need jQuery or Zepto for Ajax • Annotated source code
  • 32. MVC
  • 33. MODELS, VIEWS & COLLECTIONS
  • 36. MODELS • Data is represented as Models
  • 37. MODELS • Data is represented as Models • Can be Created, Validated, Destroyed & Persisted on Server
  • 38. MODELS • Data is represented as Models • Can be Created, Validated, Destroyed & Persisted on Server • Attribute changes trigger a ‘change’ event
  • 39. SB.Models.TicketSummary = Backbone.Model.extend({ id: null, subject: null, name: 'ticket', });
  • 41. COLLECTIONS •A collection of models
  • 42. COLLECTIONS •A collection of models • Triggers events like add/remove/refresh
  • 43. COLLECTIONS •A collection of models • Triggers events like add/remove/refresh • Can fetch models from a given url
  • 44. COLLECTIONS •A collection of models • Triggers events like add/remove/refresh • Can fetch models from a given url • Can keep the models sorted if you define a comparator function
  • 45. SB.Collections.TicketList = Backbone.Collection.extend({ model: SB.Models.TicketSummary, url: "/tickets", name: "tickets", initialize: function(models, options){ // Init stuff if you want } });
  • 46. VIEWS
  • 47. VIEWS • They are more like Rails’ Controllers
  • 48. VIEWS • They are more like Rails’ Controllers • Responsiblefor instantiating Collections and binding events that update the UI
  • 49. SB.Views.TicketListView = Backbone.View.extend({ tagName: 'ul', initialize: function(){ this.ticketList = new SB.Collections.TicketList; _.bindAll(this, 'addOne', 'addAll'); this.ticketList.bind('add', this.addOne); this.ticketList.bind('refresh', this.addAll); this.ticketList.bind('all', this.render); this.ticketList.fetch(); }, addAll: function(){ this.ticketList.each(this.addOne); }, addOne: function(ticket){ var view = new SB.Views.TicketSummaryView({model:ticket}); $(this.el).append(view.render().el); } });
  • 50. SB.Views.TicketSummary = Backbone.View.extend({ initialize: function(){ _.bind(this, 'render'); if(this.model !== undefined){ this.model.view = this; } }, events: { 'click': 'openTicket' }, openTicket: function(){ window.location = "#ticket/" + this.model.id; }, render: function(){ $(this.el).html(SB.Views.Templates['tickets/summary'] (this.model.toJSON())); return this; } });
  • 52. {{#ticket}} <div class="listing-cell name"> <p>{{nameOrEmail requester}} ({{replies_count}})</p> </div> <div class="listing-cell subject"> <a href="#{{id}}"> {{#unread}} <b>{{subject}}</b> {{/unread}} {{^unread}} {{subject}} {{/unread}} </a> </div> {{/ticket}}
  • 53. URLS
  • 54. URLS • Collections can have a url
  • 55. URLS • Collections can have a url • Models can have a url or they can derive it from collection’s url
  • 56. create → POST   /collection ◦ read → GET   /collection[/id] ◦ update → PUT   /collection/id ◦ delete → DELETE   /collection/id
  • 59. • Used for setting up the routes
  • 60. • Used for setting up the routes • You can add new routes during runtime
  • 61. SB.Controllers.AgentHome = Backbone.Controller.extend({ routes: { "": "dashboard", // http://app_url ":id": "openTicket" // http://app_url#id }, dashboard: function(){ var view = new SB.Views.TicketListView; $("#ticket").hide(); $("#list").html(view.el); $("#list").show(); }, openTicket: function(id){ var view = new SB.Views.TicketView({model : new SB.Models.Ticket({id : id})}); $("#list").hide(); $("#ticket").html(view.el); $("#ticket").show(); } });
  • 62. window.controller = new SB.Controllers.AgentHome
  • 64. • Initiates a new controller instance
  • 65. • Initiates a new controller instance • which matches the dashboard route
  • 66. • Initiates a new controller instance • which matches the dashboard route • and creates a instance of TicketListView
  • 67. • Initiates a new controller instance • which matches the dashboard route • and creates a instance of TicketListView • and a TicketList collection is created
  • 69. • TicketList collection fetches tickets and triggers the refresh event
  • 70. • TicketList collection fetches tickets and triggers the refresh event • Refresh handler renders a TicketSummary view for each ticket and adds it to the top level element
  • 72. • Every Ticket Summary row has an onclick handler
  • 73. • Every Ticket Summary row has an onclick handler • which changes to url to #ticket_id
  • 74. • Every Ticket Summary row has an onclick handler • which changes to url to #ticket_id • which matches the openTicket route
  • 78. • Youcan use as_json to customize the json responses
  • 79. • Youcan use as_json to customize the json responses • Or you can use Restfulie
  • 80. • Youcan use as_json to customize the json responses • Or you can use Restfulie • Restfulie lets you easily put links in representations too
  • 81. collection(@items, :root => "items") do |items| items.link "self", items_url items.members do |m, item| m.link :self, item_url(item) m.values { |values| values.name item.name } end end
  • 82. NOT JUST FOR API BACKED MODELS
  • 83. //window.AgentHomeController = new SB.Controllers.AgentHome; window.mainView = new SB.Views.Main; mainView.screens.add(new SB.Models.Screen({ title: 'Dashboard', href: '#dashboard', listings: [ { title: 'New Tickets', url: '/tickets?label=unanswered&replies=false' }, { title: 'Ongoing Tickets', url: '/tickets?label=unanswered&replies=true' }, { title: 'Starred Tickets', url: '/tickets?starred=true' } ] }));
  • 86. beforeEach(function(){ var ticket = new SB.Models.TicketSummary({id: 1, subject: "A Ticket", replies_count: 0, requester: {id : 1, email: '[email protected]', name: 'Requester', thumbnail: 'thumbnail-url'} }); this.view = new SB.Views.TicketSummary({model: ticket}); this.view.render(); }); it("should render a ticket summary correctly", function(){ expect($(this.view.el)).toHaveText(/A Ticket/); expect($(this.view.el)).toHaveText(/Requester/); }); it("should change the url on click", function(){ var currentLoc = window.location.toString(); $(this.view.el).click(); expect(window.location.toString()).toBe(currentLoc + "ticket#1"); });
  • 88. beforeEach(function(){ this.server = sinon.fakeServer.create(); this.server.respondWith("GET", "/tickets_url_mock_server", [200, { "Content-Type": "application/json" }, '{"tickets":[{"id": 1, "subject": "Ticket 1"},{"id": 2, "subject": "Ticket 2"}]}' ]); }); it("should instantiate view when tickets are fetched", function(){ var viewMock = sinon.mock(SB.Views); viewMock.expects("TicketSummary").once().returns(new Backbone.View); viewMock.expects("TicketSummary").once().returns(new Backbone.View); var view = new SB.Views.TicketList({url: "/tickets_url_mock_server"}); this.server.respond(); viewMock.verify(); expect($(view.render().el).children().length).toBe(2); });
  • 89. QUESTIONS? [email protected] @prateekdayal http://supportbee.com

Editor's Notes

  • #2: Prateek Dayal, 4 years with Ruby on Rails, CoFounder SupportBee, A help desk Software for SME, like the ones using Basecamp, Also did Muziboo and run HackerStreet .. Will be talking about ... how many of you love js?\n
  • #3: As Douglas Crockford puts it, most widely installed language but most misunderstood or not understood at all. A lot of care for Rails but not so much for JS etc\n
  • #4: How many of you have used jQuery?\n
  • #5: If you have to select a few elements and show/hide them or apply a css property etc\n
  • #6: Something like Gmail. Incoming Emails affect multiple items in the view etc. \n
  • #7: \n
  • #8: Choosing a framework is like choosing Ruby on Rails. It gives you a set of conventions and a place to put things. A lot of good choices have been already made for you. \n
  • #9: Most of this talk is based on our experience of building SupportBee, The ticketing page is a single page app like gmail. The code is from SB\n
  • #10: \n
  • #11: Only communicate data with the server after being loaded. \n
  • #12: Only communicate data with the server after being loaded. \n
  • #13: Only communicate data with the server after being loaded. \n
  • #14: \n
  • #15: \n
  • #16: \n
  • #17: \n
  • #18: \n
  • #19: \n
  • #20: \n
  • #21: Created by Charles Jolley, Used in Mobile Me, iWork.com, In Strobe Inc\n
  • #22: Created by the founders of 280 North Inc. Used in GoMockingBird, Github Issues\n
  • #23: \n
  • #24: \n
  • #25: Done by Jeremy Ashkenas. He has also created coffeescript and jammit. Jammit and Backbone is part of the document cloud code. Basecamp mobile is built using Backbone\n
  • #26: \n
  • #27: \n
  • #28: \n
  • #29: \n
  • #30: \n
  • #31: \n
  • #32: You get a json of tickets and display it. And on clicking the ticket the url should be changed and ticket should be displayed\n
  • #33: \n
  • #34: \n
  • #35: \n
  • #36: Unlike a Rails&amp;#x2019; model, there is no inbuilt support for Associations yet\nYou can initialize values in the initialize method\nextend helps you setup the prototype chain so that you can again inherit from this model\n
  • #37: \n
  • #38: \n
  • #39: \n
  • #40: \n
  • #41: This is a collection of model SB.Models.TicketSummary\n
  • #42: \n
  • #43: \n
  • #44: Views also instantiate other views, which can render templates\n
  • #45: Event binding for click happens here\nRenders a handlebars&amp;#x2019; template\nThe model stores a reference to this view. This reference can be used to remove/update view on changes to the attribute\n
  • #46: \n
  • #47: Logicless template. Simple JSON parsing and if/else\nnameOrEmail is a helper function that you can register\n
  • #48: \n
  • #49: \n
  • #50: Models inherit their urls from collections. For example\n
  • #51: \n
  • #52: \n
  • #53: \n
  • #54: The openTicket route will be fired when the ticket is clicked\n
  • #55: \n
  • #56: \n
  • #57: \n
  • #58: \n
  • #59: \n
  • #60: The controller has already appended the top level element to the list element on the page and has made it visible. So when tickets are populated, they show up on the page\n
  • #61: The controller has already appended the top level element to the list element on the page and has made it visible. So when tickets are populated, they show up on the page\n
  • #62: \n
  • #63: \n
  • #64: \n
  • #65: \n
  • #66: Though you can keep this and add some parsing code to parse the json out on client side\n
  • #67: \n
  • #68: \n
  • #69: \n
  • #70: Look at Rest in Practice or Roy Fielding&amp;#x2019;s blog for more info\n
  • #71: \n
  • #72: \n
  • #73: \n
  • #74: \n
  • #75: \n
  • #76: \n
  • #77: \n
  • #78: \n