-
Notifications
You must be signed in to change notification settings - Fork 7
/
lecture2.html
477 lines (377 loc) · 34.1 KB
/
lecture2.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
<!DOCTYPE HTML>
<!--
Read Only by HTML5 UP
html5up.net | @n33co
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
<head>
<title>Backbone.js - Lecture 2</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<!--[if lte IE 8]><script src="css/ie/html5shiv.js"></script><![endif]-->
<script src="js/jquery.min.js"></script>
<script src="js/jquery.scrollzer.min.js"></script>
<script src="js/jquery.scrolly.min.js"></script>
<script src="js/skel.min.js"></script>
<script src="js/skel-layers.min.js"></script>
<script src="js/init.js"></script>
<noscript>
<link rel="stylesheet" href="css/skel.css" />
<link rel="stylesheet" href="css/style.css" />
<link rel="stylesheet" href="css/style-xlarge.css" />
</noscript>
<style>
.ac-caption {
margin: 5px 0px 10px 0px;
font-size: 13px;
text-align: center;
}
#header > nav ul li a {
padding: 0px;
font-size: 0.8em;
}
#one:before {
background-image: none;
height: 0em;
}
header.major h2 {
line-height: 1em;
}
</style>
<!--[if lte IE 8]><link rel="stylesheet" href="css/ie/v8.css" /><![endif]-->
</head>
<body>
<div id="wrapper">
<!-- Header -->
<section id="header" class="skel-layers-fixed">
<header>
<h1 id="logo"><a href="#">Backbone - Lecture 2</a></h1>
</header>
<nav id="nav">
<ul>
<li><a href="#one" class="active">Models, part 2</a></li>
<li><a href="#two">Views + Models</a></li>
<li><a href="#three">The Router</a></li>
<li><a href="#four">The History</a></li>
</ul>
<img src="http://www.avenuecode.com/wp-content/themes/ac-site/images/white-logo.png" alt="">
</nav>
<footer>
</footer>
</section>
<!-- Main -->
<div id="main">
<div class="container">
<img class="logo-big" src="./images/backbone.png">
</div>
<!-- One -->
<section id="one">
<div class="container">
<header class="major">
<h2>Models, part 2</h2>
</header>
<header>
<h4>Remote Model Syncing</h4>
</header>
<p align="justify">
The Backbone.js Models are compatible with the RESTful API pattern. That means it communicates with the server following these guidelines:
</p>
<ul>
<li>GET requests when reading data from the server;</li>
<li>POST requests when submiting new data to the server;</li>
<li>PUT requests when updating data on the server;</li>
<li>DELETE requests when submitting a delete command to the server.</li>
</ul>
<p align="justify">
That means Backbone.js applications are fully compatible with a Node.js <b>Express</b> server routing system. The Model analogous to the Node.js <b>paths</b> resides on the Model <b>urlRoot</b> attribute.
</p>
<header>
<h4>The Model fetch() method</h4>
</header>
<p align="justify">
Asynchronously fetching data from the server is a key feature to complex web applications. In order to do that on Backbone.js all we have to do is setting the appropriate <b>urlRoot</b> property on the model and make <b>fetch()</b> method call.
</p>
<p align="justify">
Then we can <b>listen to</b> its results, <b>parse</b> the retrieved data for making it fit our needs, and also <b>handle response errors</b>.
</p>
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #66d9ef">var</span> <span style="color: #a6e22e">UserModel</span> <span style="color: #f92672">=</span> <span style="color: #a6e22e">Backbone</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">Model</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">extend</span><span style="color: #f8f8f2">({</span>
<span style="color: #a6e22e">urlRoot</span><span style="color: #f92672">:</span> <span style="color: #e6db74">'/users/me'</span>
<span style="color: #f8f8f2">});</span>
<span style="color: #66d9ef">var</span> <span style="color: #a6e22e">model</span> <span style="color: #f92672">=</span> <span style="color: #66d9ef">new</span> <span style="color: #a6e22e">UserModel</span><span style="color: #f8f8f2">();</span>
<span style="color: #a6e22e">model</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">fetch</span><span style="color: #f8f8f2">();</span>
</pre></div>
<div class="ac-caption">A Model fetching a user profile information from the server.</div>
<header>
<h4>Exercise 5</h4>
</header>
<p align="justify">
In order to accomplish the next exercise, you will nedd your <b>node</b> server running. To start your server, open a console prompt, navigate to the server root directory and type:
</p>
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #a6e22e">grunt</span> <span style="color: #a6e22e">serverExpress</span>
</pre></div>
<div class="ac-caption">Start your node server.</div>
<p align="justify">
Your node server will connect to a remote <b>mongoDB</b> database. For it to work properly you should not be behind a VPN.
</p>
<ul class="feature-icons">
<li class="fa-bolt" style="width: inherit">If you use Windows and your server crashes upon running, you may have to delete the <b>node_modules</b> dir and run <b>npm install</b> again.
</ul>
<p align="justify">
With your server running, go to the <b>/login.html</b> url. Create a login for you using your <b>FULL NAME</b> and an email that you have previously registered for an avatar picture on the site <b><a href="http://gravatar.com" target="_blank">gravatar.com</a></b>.
</p>
<p align="justify">
Login with your chosen email and password, then open <b>excercise5.html</b>. Open a new script tag at the end of the document and create a model there that will retrieve you user data using <b>/users/me</b> as <b>urlRoot</b>. Your model should listen to its own <b>sync</b> event. Do a model fetch() and use the console to log the model attributes on your model initialize method and on your sync listener.
</p>
<p align="justify">
So far we have created Models with <b>default attributes</b>, with <b>data validation</b>, with <b>event listeners</b> and <b>data fetching</b> from the server. Before continuing, we are going to learn how to work this data received from the server.
</p>
<header>
<h4>The Model parse() method</h4>
</header>
<p align="justify">
Sometimes your application needs data in a format that differs from the one your server is ready to send and/or you don't have the access or the knowledge to make the changes you need on the server. Other times processing that data on the server to generate a proper response would increase your hosting costs.
</p>
<p align="justify">
In either case, the <b>parse()</b> method comes to the rescue! The parse method is called everytime your model makes a sucessful <b>fetch()</b> call, <b>AND CAN BE OPTIONALLY CALLED WHEN YOU DO A SET CALL AS WELL</b>.
</p>
<ul class="feature-icons">
<li class="fa-bolt" style="width: inherit">You can parse the model attributes every time you do a <b>set</b> by passing <b>{parse: true}</b> as an optional parameter to the <b>set</b> call.</li>
</ul>
<p align="justify">
The <b>parse</b> method receives the response data and returns the parsed response that will be set as the new model attributes. The default Model parse only passes the data forward, and we have to overwrite it when defining our Model class to make it fit our needs.
</p>
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #a6e22e">parse</span><span style="color: #f92672">:</span> <span style="color: #66d9ef">function</span><span style="color: #f8f8f2">(</span><span style="color: #a6e22e">resp</span><span style="color: #f8f8f2">,</span> <span style="color: #a6e22e">options</span><span style="color: #f8f8f2">)</span> <span style="color: #f8f8f2">{</span>
<span style="color: #66d9ef">return</span> <span style="color: #a6e22e">resp</span><span style="color: #f8f8f2">;</span>
<span style="color: #f8f8f2">}</span>
</pre></div>
<div class="ac-caption">The default <b>parse</b> just returns the response unchanged.</div>
<header>
<h4>Exercise 6</h4>
</header>
<p align="justify">
Follow the same procedures as in Exercise 5 to login into your local server.
</p>
<ol>
<li>Add a <b>parse</b> method on your model that breaks your name and create two new model attributes: <b>firstname</b> and <b>lastname</b>.</li>
<li>If you did not follow the instructions from Exercise 5 correctly and created your user with just a single name, have you <b>parse</b> method duplicate it into the model's <b>firstname</b> and <b>lastname</b> attributes.</li>
<li>Change the method used as the callback to you <b>sync</b> listener to receive three parameters: <b>model</b>, <b>response</b> and <b>options</b>. Log the three parameters on the console and identify each one's fields.</li>
</ol>
<p align="justify">
You should notice the callback to your <b>sync</b> event only fires after the model data was already parsed.
</p>
<header>
<h4>The Model idAttribute</h4>
</header>
<p align="justify">
As we are learning soon, for some RESTful actions (actually for most of them) the model have to provide its <b>idAttribute</b>. It may be in order to <b>read</b> or <b>update</b> a specific object from the server.
</p>
<p align="justify">
The server, however, not always send objects with an <b>id</b> attribute. The <b>mongoDB</b>, for example, identify its objects by a <b>_id</b> label. So we have two options:
</p>
<ul>
<li><b>parse</b> the server response deleting the <b>_id</b> attribute and setting it as <b>id</b> on the returned object.</li>
<li>change your Model's default <b>idAttribute</b> to be <b>_id</b> instead of <b>id</b>.</li>
</ul>
<p align="justify">
Which one is the best way to go? Oh life, so full of choices that we may or may not regret forever.
</p>
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #66d9ef">var</span> <span style="color: #a6e22e">UserModel</span> <span style="color: #f92672">=</span> <span style="color: #a6e22e">Backbone</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">Model</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">extend</span><span style="color: #f8f8f2">({</span>
<span style="color: #a6e22e">urlRoot</span><span style="color: #f92672">:</span> <span style="color: #e6db74">'/users/me'</span><span style="color: #f8f8f2">,</span>
<span style="color: #a6e22e">idAttribute</span><span style="color: #f92672">:</span> <span style="color: #e6db74">'_id'</span><span style="color: #f8f8f2">,</span>
<span style="color: #f8f8f2">...</span>
<span style="color: #f8f8f2">}</span>
</pre></div>
<div class="ac-caption">Changing the default Model's <b>idAttribute</b>.</div>
<header>
<h4>The Model sync() method</h4>
</header>
<p align="justify">
Sometimes your server is not so <b>RESTful</b> after all. Sometimes it would just not make sense. In either case, the <b>sync()</b> method can be customized to better suit your data persistence needs.
</p>
<p align="justify">
The <b>sync</b> function may be overridden globally as <b>Backbone.sync</b>, or at a finer-grained level, by adding a <b>sync</b> function to a Backbone <b>collection</b> or to an individual <b>model</b>.
</p>
<p align="justify">The default sync handler maps <b>CRUD</b> to <b>REST</b> like so:</p>
<ul>
<li><b>create → POST </b><tt>/urlRoot</tt></li>
<li><b>read → GET </b><tt>/urlRoot[/id]</tt></li>
<li><b>update → PUT </b><tt>/urlRoot/id</tt></li>
<li><b>patch → PATCH </b><tt>/urlRoot/id</tt></li>
<li><b>delete → DELETE </b><tt>/urlRoot/id</tt></li>
</ul>
<p align="justify">The <b>PATCH</b> request is just like the <b>PUT</b> request, but it only sends the changed data to the server. You can send a PATCH by passing <b>{patch:true}</b> as optional parameter when making a <b>model.save</b> call. It was added on <b>Backbone.js</b> version 0.9.9.</p>
<p align="justify">
Let's assume our server breaks the REST API on the route it defined to create a new instance on the database, so that we need to add a <b>/create</b> trail to the create object url. One way of doing that would be by customizing the <b>Backbone.sync</b> method as in the code below:
</p>
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #a6e22e">sync</span><span style="color: #f92672">:</span> <span style="color: #66d9ef">function</span><span style="color: #f8f8f2">(</span><span style="color: #a6e22e">method</span><span style="color: #f8f8f2">,</span> <span style="color: #a6e22e">model</span><span style="color: #f8f8f2">,</span> <span style="color: #a6e22e">options</span><span style="color: #f8f8f2">)</span> <span style="color: #f8f8f2">{</span>
<span style="color: #a6e22e">options</span> <span style="color: #f92672">||</span> <span style="color: #f8f8f2">(</span><span style="color: #a6e22e">options</span> <span style="color: #f92672">=</span> <span style="color: #f8f8f2">{});</span>
<span style="color: #66d9ef">switch</span> <span style="color: #f8f8f2">(</span><span style="color: #a6e22e">method</span><span style="color: #f8f8f2">)</span> <span style="color: #f8f8f2">{</span>
<span style="color: #66d9ef">case</span> <span style="color: #e6db74">'create'</span><span style="color: #f92672">:</span>
<span style="color: #a6e22e">options</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">url</span> <span style="color: #f92672">=</span> <span style="color: #66d9ef">this</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">urlRoot</span> <span style="color: #f92672">+</span> <span style="color: #e6db74">'/create'</span><span style="color: #f8f8f2">;</span>
<span style="color: #66d9ef">break</span><span style="color: #f8f8f2">;</span>
<span style="color: #66d9ef">case</span> <span style="color: #e6db74">'update'</span><span style="color: #f92672">:</span>
<span style="color: #66d9ef">break</span><span style="color: #f8f8f2">;</span>
<span style="color: #66d9ef">case</span> <span style="color: #e6db74">'delete'</span><span style="color: #f92672">:</span>
<span style="color: #66d9ef">break</span><span style="color: #f8f8f2">;</span>
<span style="color: #66d9ef">case</span> <span style="color: #e6db74">'read'</span><span style="color: #f92672">:</span>
<span style="color: #66d9ef">break</span><span style="color: #f8f8f2">;</span>
<span style="color: #f8f8f2">}</span>
<span style="color: #66d9ef">return</span> <span style="color: #a6e22e">Backbone</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">sync</span><span style="color: #f8f8f2">(</span><span style="color: #a6e22e">method</span><span style="color: #f8f8f2">,</span> <span style="color: #a6e22e">model</span><span style="color: #f8f8f2">,</span> <span style="color: #a6e22e">options</span><span style="color: #f8f8f2">);</span>
<span style="color: #f8f8f2">}</span>
</pre></div>
<div class="ac-caption">Remember this for the next exercises.</div>
<header>
<h4>The Model toJSON() method</h4>
</header>
<p align="justify">
Besides the RESTful API, our server may also differ from our application on the way it expects the data to be sent back. Remember when we changed the model on the <b>parse()</b> method? It may be necessary to change it back before sending it to the server.
</p>
<p align="justify">
For accomplishing that all we have to do is overwrite our Model's <b>toJSON()</b> method. When the Model data is going to be <b>serialized</b> to be sent back to the server on a <b>save()</b> call, for example, the data sent back will not be just the <b>model.attributes</b>, but the result of the <b>model.toJSON()</b>.
</p>
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #66d9ef">var</span> <span style="color: #a6e22e">TodoItem</span> <span style="color: #f92672">=</span> <span style="color: #a6e22e">Backbone</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">Model</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">extend</span><span style="color: #f8f8f2">({</span>
<span style="color: #a6e22e">toJSON</span><span style="color: #f92672">:</span> <span style="color: #66d9ef">function</span><span style="color: #f8f8f2">(){</span>
<span style="color: #66d9ef">return</span> <span style="color: #a6e22e">_</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">clone</span><span style="color: #f8f8f2">(</span><span style="color: #66d9ef">this</span><span style="color: #f8f8f2">.</span><span style="color: #a6e22e">attributes</span><span style="color: #f8f8f2">);</span>
<span style="color: #f8f8f2">}</span>
<span style="color: #f8f8f2">});</span>
</pre></div>
<div class="ac-caption">Default Model <b>toJSON</b> behavior.</div>
<p align="justify">
It is common to see the <b>toJSON</b> method be called to pass the model data to the <b>templating</b> function. This is done because while <b>toJSON</b> returns a <b>shallow copy</b> of the model's <b>attributes</b> value, passing <b>model.attributes</b> passes the real attributes forward.
</p>
<p align="justify">
But as long as our template is not changing the attributes we pass, we are free to send them as <b>model.attributes</b> to the template method and use the <b>toJSON</b> as it is really intended, Which is for the model data <b>serialization</b>.
</p>
<header>
<h4>Exercise 6-b</h4>
</header>
<p align="justify">
For this exercise, use the same <b>exercise6.html</b> file.
</p>
<ol>
<li>Override your model <b>toJSON</b> method to revert your model attributes back to what the server sent you (undo the <b>firstname</b> and <b>lastname</b> changes.</li>
</ol>
</div>
</section>
<section id="two">
<div class="container">
<header class="major">
<h2>Views + Models</h2>
</header>
<p align="justify">So far we only worked with <b>Views</b> and <b>Models</b> separately. It is time to join them to create our first <b>Backbone.js</b> application.
</p>
<p align="justify">We are goint to create a <b>ProfileView</b>, in order to display and edit our user data on the page DOM. This View will use a micro-template for rendering. On the next section we will prepare our <b>exercise7.html</b> to render our profile contents.
</p>
<p align="justify">First, <b>localize</b> the line below on your source code:
</p>
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #f92672"><</span><span style="color: #a6e22e">script</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">"text/template"</span> <span style="color: #a6e22e">id</span><span style="color: #f92672">=</span><span style="color: #e6db74">"profileTemplate"</span><span style="color: #f92672">><</span><span style="color: #960050; background-color: #1e0010">/script></span>
</pre></div>
<div class="ac-caption">This is our micro-templating tag.</div>
<p align="justify">Netx, fill that tag up with the following contents:</p>
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #f92672"><</span><span style="color: #a6e22e">div</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"column col-xs-12"</span> <span style="color: #a6e22e">id</span><span style="color: #f92672">=</span><span style="color: #e6db74">"main"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">div</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"col-sm-2"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">div</span> <span style="color: #a6e22e">id</span><span style="color: #f92672">=</span><span style="color: #e6db74">"myProfile"</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"panel panel-default"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">div</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"panel-thumbnail"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">img</span> <span style="color: #a6e22e">id</span><span style="color: #f92672">=</span><span style="color: #e6db74">"profilePicture"</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"img-responsive"</span>
<span style="color: #a6e22e">src</span><span style="color: #f92672">=</span><span style="color: #e6db74">"http://www.gravatar.com/avatar/.jpg?s=200"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/div></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">div</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"panel-body"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">p</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"lead"</span><span style="color: #f92672">><</span><span style="color: #960050; background-color: #1e0010">/p></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/div></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/div></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/div></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">div</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"col-sm-6"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">div</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"panel panel-default"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">div</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"panel-body"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">form</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">div</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"form-group"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">label</span> <span style="color: #66d9ef">for</span><span style="color: #f92672">=</span><span style="color: #e6db74">"name"</span><span style="color: #f92672">></span><span style="color: #a6e22e">Nome</span><span style="color: #f92672">:<</span><span style="color: #960050; background-color: #1e0010">/label></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">input</span> <span style="color: #a6e22e">id</span><span style="color: #f92672">=</span><span style="color: #e6db74">"name"</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">"text"</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"form-control"</span> <span style="color: #a6e22e">value</span><span style="color: #f92672">=</span><span style="color: #e6db74">""</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/div></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">div</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"form-group"</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">label</span> <span style="color: #66d9ef">for</span><span style="color: #f92672">=</span><span style="color: #e6db74">"email"</span><span style="color: #f92672">></span><span style="color: #a6e22e">Email</span><span style="color: #f92672">:<</span><span style="color: #960050; background-color: #1e0010">/label></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">input</span> <span style="color: #a6e22e">id</span><span style="color: #f92672">=</span><span style="color: #e6db74">"email"</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">"email"</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"form-control"</span> <span style="color: #a6e22e">value</span><span style="color: #f92672">=</span><span style="color: #e6db74">""</span><span style="color: #f92672">></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/div></span>
<span style="color: #f92672"><</span><span style="color: #a6e22e">button</span> <span style="color: #a6e22e">type</span><span style="color: #f92672">=</span><span style="color: #e6db74">"button"</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"btn btn-default"</span><span style="color: #f92672">></span><span style="color: #a6e22e">Salvar</span><span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/button></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/form></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/div></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/div></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/div></span>
<span style="color: #f92672"><</span><span style="color: #960050; background-color: #1e0010">/div></span>
</pre></div>
<div class="ac-caption">Actual template contents.</div>
<header>
<h4>Exercise 7-a</h4>
</header>
<p align="justify">
Continue working on <b>exercise7.html</b> to create your profile View. Follow the below steps:
</p>
<ol>
<li>Create a model with <b>urlRoot</b> = <b>'/users/me'</b>. Customize its <b>initialize</b> method so that it fetches its contents upon initialize.</li>
<li>Have the model <b>parse</b> its fetched contents to create artificial <b>firstname</b> and <b>lastname</b> attributes.</li>
<li>Create a View that uses the <b>undesrcore</b> templating engine to render its contents. The View should load the script tag you copied as the template source.</li>
<li>The view should append its template generated contents to the <b>#mainViewContainer</b> DOM element.</li>
<li>Create an <b>instance</b> of the View, and pass an <b>instance</b> of the Model on its constructor as the <b>model</b> parameter.</li>
</ol>
<p align="justify">
If you did everything right you endeed up with a View that shows this:
</p>
<img src="./images/exercise7-a.png">
<div class="ac-caption">This is what you should have by now.</div>
<p align="justify">
Our View is rendering but we still need to connect the <b>Model data</b> to the template. For doing so, identify on the template DOM where it should be appropriate to display the model attributes and add <b>underscore tags (<%= %>)</b> to the DOM.
</p>
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #f92672"><</span><span style="color: #a6e22e">p</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"lead"</span><span style="color: #f92672">><%=</span> <span style="color: #a6e22e">firstname</span> <span style="color: #f92672">%><</span><span style="color: #960050; background-color: #1e0010">/p></span>
</pre></div>
<div class="ac-caption">Example: display the firstname attribute on the p.class="lead".</div>
<p align="justify">
To display the profile picture, use the <b>md5</b> method by adding <b><%= md5( email ) %></b> right before the <b>.jpg</b> on the profile picture.
</p>
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #f92672"><</span><span style="color: #a6e22e">img</span> <span style="color: #a6e22e">id</span><span style="color: #f92672">=</span><span style="color: #e6db74">"profilePicture"</span> <span style="color: #66d9ef">class</span><span style="color: #f92672">=</span><span style="color: #e6db74">"img-responsive"</span>
<span style="color: #a6e22e">src</span><span style="color: #f92672">=</span><span style="color: #e6db74">"http://www.gravatar.com/avatar/<%= md5(email) %>.jpg?s=200"</span><span style="color: #f92672">></span>
</pre></div>
<div class="ac-caption">Gravatar picture rendering.</div>
<header>
<h4>Exercise 7-b</h4>
</header>
<p align="justify">
Finish adding the model data to the template and test its rendering.
</p>
<header>
<h4>Model save() + View render()</h4>
</header>
<p align="justify">
Our previous exercise rendered our model into the DOM. Now we are going to use the View <b>events</b> capabilities to edit the model and send it back to the server.
</p>
<header>
<h4>Exercise 7-c</h4>
</header>
<ol>
<li>Add an event filter on the View <b>events</b> property to catch the form <b>submit</b> event.</li>
<li>On the callback function, get the <b>event</b> as the first parameter and call <b>event.preventDefault</b>.</li>
<li>Update your model by using <b>set</b> with the form data.</li>
<li>Make sure the Model class has a <b>validate</b> method to check for the <b>name</b> and <b>email</b> attributes.</li>
<li>Display an error alert in case the validation fails.</li>
<li>After updating the model, call its <b>save</b> method.</li>
<li>Make the View <b>listen to</b> the model <b>sync</b> event and use its <b>render</b> method as the listener callback. For this, use the View's <b>listenTo</b> method.</li>
</ol>
<p align="justify">
The View display should update the name on the left panel when the model is saved. On the next section we will separate our View into one View for <b>displaying</b> and other for <b>editing</b> the profile.
</p>
</div>
</section>
</div>
<!-- Footer -->
<section id="footer">
<div class="container">
<ul class="copyright">
<li>© Avenue Code. All rights reserved.</li>
<li>Design: <a href="http://html5up.net">HTML5 UP</a></li>
</ul>
</div>
</section>
</div>
</body>
</html>