Define a Router

A Backbone router defines navigation paths among views. To learn more about routers, see What is a router?

  1. In the final <script> block, define the application router by extending Backbone.StackRouter.
    1app.Router = Backbone.StackRouter.extend({
    2
    3});

    For the remainder of this procedure, add all code in the extend({}) block.

  2. Because the app supports a search list page and a user page, add a route for each page inside a routes object. Also add a route for the main container page ("").
    1routes: {
    2    "": "list",
    3    "list": "list",
    4    "users/:id": "viewUser"
    5},
  3. Define an initialize() function that creates the search results collection and the search page and user page views.
    1initialize: function() {
    2    Backbone.Router.prototype.initialize.call(this);
    3
    4    // Collection behind search screen
    5    app.searchResults = new app.models.UserCollection();
    6
    7    app.searchPage = new app.views.SearchPage(
    8        {model: app.searchResults});
    9    app.userPage = new app.views.UserPage();
    10},
  4. Define the list() function for handling the only item in this route. Call slidePage() to show the search results page right away—when data arrives, the list redraws itself.
    1list: function() {
    2   app.searchResults.fetch();
    3   this.slidePage(app.searchPage);
    4},
  5. Define a viewUser() function that fetches and displays details for a specific user.
    1viewUser: function(id) {
    2    var that = this;
    3    var user = new app.models.User({Id: id});
    4    user.fetch({
    5        success: function() {
    6            app.userPage.model = user;
    7            that.slidePage(app.userPage);
    8        }
    9    });
    10}
  6. After saving the file, run the cordova prepare command.
  7. Run the application.

Example

You’ve finished! Here’s the entire application:

1<!DOCTYPE html>
2<html>
3<head>
4<title>Users</title>
5<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
6<link rel="stylesheet" href="css/styles.css"/>
7<link rel="stylesheet" href="css/ratchet.css"/>
8</head>
9
10<body>
11
12<div id="content"></div>
13<script src="js/jquery.min.js"></script>
14<script src="js/underscore-min.js"></script>
15<script src="js/backbone-min.js"></script>
16
17<!-- Local Testing -/->
18<script src="js/MockCordova.js"></script>
19<script src="js/cordova.force.js"></script>
20<script src="js/MockSmartStore.js"></script>
21<!-- End Local Testing -->
22
23<!-- Container -->
24<script src="cordova.js"></script>
25<!-- End Container -->
26
27<script src="js/force.js"></script>
28<script src="js/force+promise.js"></script>
29<script src="js/mobilesync.js"></script>
30<script src="js/fastclick.js"></script>
31<script src="js/stackrouter.js"></script>
32<script src="js/auth.js"></script>
33
34
35<!-- ----Search page template ---- -->
36<script id="search-page" type="text/template">
37  <header class="bar-title">
38    <h1 class="title">Users</h1>
39  </header>
40
41  <div class="bar-standard bar-header-secondary">
42    <input type="search" 
43     class="search-key" 
44     placeholder="Search"/>
45  </div>
46
47  <div class="content">
48    <ul class="list"></ul>
49  </div>
50</script>
51
52<!-- ---- User list item template ---- -->
53<script id="user-list-item" type="text/template">
54
55  <a href="#users/<%= Id %>" class="pad-right">
56    <img src="<%= SmallPhotoUrl %>" class="small-img" />
57    <div class="details-short">
58      <b><%= FirstName %> <%= LastName %></b><br/>
59      Title<%= Title %>
60    </div>
61  </a>
62</script>
63
64<!-- ---- User page template ---- -->
65<script id="user-page" type="text/template">
66  <header class="bar-title">
67    <a href="#" class="button-prev">Back</a>
68    <h1 class="title">User</h1>
69  </header>
70
71  <footer class="bar-footer">
72    <span id="offlineStatus"></span>
73  </footer>
74
75  <div class="content">
76    <div class="content-padded">
77      <img id="employeePic" 
78         src="<%= SmallPhotoUrl %>" class="large-img" />
79      <div class="details">
80        <b><%= FirstName %> <%= LastName %></b><br/>
81        <%= Id %><br/>
82        <% if (Title) { %><%= Title %><br/><% } %>
83        <% if (City) { %><%= City %><br/><% } %>
84        <% if (MobilePhone) { %> 
85           <a href="tel:<%= MobilePhone %>">
86           <%= MobilePhone %></a><br/><% } %>
87        <% if (Email) { %>
88           <a href="mailto:<%= Email %>">
89           <%= Email %></a><% } %>
90      </div>
91    </div>
92  </div>
93</script>
94
95<script>
96// ---- The Models ---- //
97// The User Model
98app.models.User = Force.SObject.extend({
99    sobjectType: "User",
100    fieldlist: ["Id", "FirstName", "LastName", "SmallPhotoUrl", 
101       "Title", "Email", "MobilePhone","City"]
102});
103
104// The UserCollection Model
105app.models.UserCollection = Force.SObjectCollection.extend({
106    model: app.models.User,
107    fieldlist: ["Id", "FirstName", "LastName", "SmallPhotoUrl", 
108        "Title"],
109
110    getCriteria: function() {
111        return this.key;
112    },
113
114    setCriteria: function(key) {
115        this.key = key;
116        this.config = {type:"soql", 
117                       query:"SELECT " 
118                        + this.fieldlist.join(",")  
119                        + " FROM User"
120                        + " WHERE Name like '" + key + "%'"
121                        + " ORDER BY Name "
122                        + " LIMIT 25 "
123                      };
124    }
125});
126
127
128// -------------------------------------------------- The Views ---------------------------------------------------- //
129
130app.views.SearchPage = Backbone.View.extend({
131
132    template: _.template($("#search-page").html()),
133
134    events: {
135        "keyup .search-key": "search"
136    },
137
138    initialize: function() {
139        this.listView = 
140            new app.views.UserListView(
141                {model: this.model});
142    },
143
144    render: function(eventName) {
145        $(this.el).html(this.template());
146        $(".search-key", this.el).val(this.model.getCriteria());
147        this.listView.setElement($("ul", this.el)).render();
148        return this;
149    },
150
151    search: function(event) {
152        this.model.setCriteria($(".search-key", this.el).val());
153        this.model.fetch();
154    }
155});
156
157app.views.UserListView = Backbone.View.extend({
158
159    listItemViews: [],
160
161    initialize: function() {
162        this.model.bind("reset", this.render, this);
163    },
164
165    render: function(eventName) {
166        _.each(this.listItemViews, 
167            function(itemView) {itemView.close(); });
168        this.listItemViews = 
169            _.map(this.model.models, function(model) {
170                 return new app.views.UserListItemView(
171                     {model: model}); });
172        $(this.el).append(_.map(this.listItemViews, 
173            function(itemView) {
174                return itemView.render().el;} ));
175        return this;
176    }
177});
178
179app.views.UserListItemView = Backbone.View.extend({
180
181    tagName: "li",
182    template: _.template($("#user-list-item").html()),
183
184    render: function(eventName) {
185        $(this.el).html(this.template(this.model.toJSON()));
186        return this;
187    },
188
189    close: function() {
190        this.remove();
191        this.off();
192    }
193});
194
195app.views.UserPage = Backbone.View.extend({
196
197    template: _.template($("#user-page").html()),
198
199    render: function(eventName) {
200        $(this.el).html(this.template(this.model.toJSON()));
201        return this;
202    }
203
204});
205
206
207// ----------------------------------------------- The Application Router ------------------------------------------ //
208
209app.Router = Backbone.StackRouter.extend({
210
211    routes: {
212        "": "list",
213        "list": "list",
214        "users/:id": "viewUser"
215    },
216
217    initialize: function() {
218        Backbone.Router.prototype.initialize.call(this);
219
220        // Collection behind search screen
221        app.searchResults = new app.models.UserCollection();
222
223        // We keep a single instance of SearchPage and UserPage
224        app.searchPage = new app.views.SearchPage(
225            {model: app.searchResults});
226        app.userPage = new app.views.UserPage();
227    },
228
229    list: function() {
230        app.searchResults.fetch();
231        // Show page right away
232        // List will redraw when data comes in
233        this.slidePage(app.searchPage);
234    },
235
236    viewUser: function(id) {
237        var that = this;
238        var user = new app.models.User({Id: id});
239        user.fetch({
240            success: function() {
241                app.userPage.model = user;
242                that.slidePage(app.userPage);
243            }
244        });
245    }
246});
247</script>
248</body>
249</html>