Define a Router

A Backbone router defines navigation paths among views.

  1. In the final <script> block, define the application router by extending Backbone.StackRouter.

    1app.Router = Backbone.StackRouter.extend({});

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

We've Moved

Welcome to the new home of the Mobile SDK Developer Guide! For now, the Japanese guide can be found in PDF form.