Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranรฎ)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
1 1
Let's now use the local storage API 2
2
in order to make the workout data 3
3
persist across multiple page reloads. 4
4
And let's start with a look at our flowchart 5
5
so that we can see exactly what we have to implement. 6
6
So basically the idea is that 7
7
whenever a new workout is added, 8
8
then all the workouts will be added to local storage. 9
9
And so local storage is basically a place in the browser, 10
10
where we can store data that will stay there 11
11
even after we close the page. 12
12
So basically the data is basically linked to the URL 13
13
on which we are using the application. 14
14
So, again whenever there is a new workout, 15
15
we will take the entire workouts array 16
16
and store it in local storage. 17
17
And then whenever the page loads, 18
18
so up here in this event, 19
19
then we will load all the workouts from the local storage, 20
20
and render them on the map and also on the list. 21
21
So just like we do it when a user submits a new workout. 22
22
And so like this, when you reload the page, 23
23
it will then appear 24
24
as if all the workouts you had previously 25
25
are still in the same place. 26
26
And hopefully this makes sense, 27
27
and so let's now get started, 28
28
and we will start with this part here. 29
29
So storing all the workouts in local storage, 30
30
and remember that happens 31
31
whenever the user creates a new workout. 32
32
And so we have to get started in the new workout method. 33
33
So down here, we need to add yet another point. 34
34
So set local storage to all workouts. 35
35
And here I'm actually gonna create yet another method, 36
36
so that we can keep this method here, 37
37
basically nice and clean. 38
38
So as you see, this new workout method here 39
39
is basically a bit of a method that does delegation. 40
40
So we do some stuff here, of course, 41
41
but then once we're done creating the actual object, 42
42
then down here, we delegate all kinds of functionality 43
43
to other methods like these ones. 44
44
And now I'll also create setLocalStorage. 45
45
So here I'm of course calling it already, 46
46
but now I will create it afterwards. 47
47
So setLocalStorage and once again, 48
48
let's add it here at the end. 49
49
And this one doesn't need any parameters 50
50
because we will simply get the workouts 51
51
from the workout property. 52
52
And so this is how we use the local storage API. 53
53
And I say API because local storage is, once again, 54
54
an API that the browser provides for us 55
55
and that we can use. 56
56
So localStorage.setItem, 57
57
and then we have to give it a name, so workouts, 58
58
and then the second argument 59
59
needs to be a string that we want to store 60
60
and which will be associated with this key here. 61
61
So basically local storage is a simple key value store, 62
62
and so we need a key which is this one here, 63
63
and we need a simple value, 64
64
which must also be a string. 65
65
But we can convert an object to a string 66
66
by doing this. 67
67
So JSON.stringify. 68
68
So this is another new one, all right. 69
69
But we can use this method here 70
70
to convert any object in JavaScript to a string. 71
71
And so what we want to convert 72
72
is this.workouts, like this. 73
73
And that's actually it already. 74
74
With this, we are setting all the workouts to local storage. 75
75
Now, I just want to mention that local storage 76
76
is a very simple API. 77
77
And so it is only advised to use 78
78
for small amounts of data, all right. 79
79
That's because local storage is blocking, 80
80
and for now you don't know what blocking actually means 81
81
but it is something that's very bad, 82
82
and we will learn why that is 83
83
actually in the next section. 84
84
But for now, what matters here is 85
85
that you shouldn't use local storage 86
86
to store large amounts of data, 87
87
because that will surely slow down your application. 88
88
But anyway, let's already test this out, 89
89
because we actually have a way 90
90
of seeing this data in the browser. 91
91
So let's add something here. 92
92
Okay. 93
93
So everything worked fine. 94
94
So now let's go here to this application tab, 95
95
and then here on the left side 96
96
you have this local storage tab, all right. 97
97
And if we click this arrow here, and then here, 98
98
well, then actually it should be here already. 99
99
Well, let's see if we have everything correctly set up. 100
100
So we have setLocalStorage, then setItem 101
101
and here everything looks correct. 102
102
And here, I believe we're also correctly calling it, 103
103
setLocalStorage. 104
104
So this should work. 105
105
So let's simply try it again here. 106
106
(clicking) 107
107
(typing) Okay. 108
108
Ah, and now you saw it appearing here, right. 109
109
So we have the key of workout and then the value. 110
110
And the value is basically now this string here. 111
111
So, actually here it looks like an object, 112
112
because apparently JavaScript 113
113
somehow then converts it back to an object, 114
114
but actually it is stored as a string, 115
115
here in this workouts key. 116
116
So you see that we have this single workout 117
117
that we currently have, 118
118
but of course, if we add another one, 119
119
then now we got this bigger string here. 120
120
And so it now contains these two objects. 121
121
And so like this, the local storage 122
122
always is gonna be updated. 123
123
So it's up to date, according to the data 124
124
that we have in our application. 125
125
Great. 126
126
And now all we have to do 127
127
is to then actually show the data back here 128
128
on the list and the map once we reload the page. 129
129
So let me actually show that to you 130
130
because here in the application, 131
131
as you see the local storage is still there. 132
132
And so now we will make use of this 133
133
by then displaying that data back in our application. 134
134
So remember when we want to do that, 135
135
it is right here in the constructor, right. 136
136
Because this is where we have all the code 137
137
that is executed right when the application loads. 138
138
So let's add that here. 139
139
And I'm gonna start with some comments here. 140
140
(typing) 141
141
Handlers, 142
142
then get user's position, 143
143
and then get data from local storage. 144
144
And so again, 145
145
I will now call a method that I'm going to create later. 146
146
So getLocalStorage. 147
147
And so let's now go ahead and create this method 148
148
down here in the end. 149
149
(clicking) (typing) 150
150
And so now, here we do the opposite. 151
151
So localStorage.getItem. 152
152
And now we simply have to pass in the key. 153
153
So basically the identifier of our local storage item, 154
154
because we could set multiple items. 155
155
So we could set everything all for application. 156
156
So for example, if we wanted, 157
157
we could store everything that's in the application 158
158
in local storage. 159
159
We would just have to define one key for each of them, 160
160
and then we could use that key 161
161
to basically retrieve it back. 162
162
(clicking) (typing) 163
163
Alright, so let's now store this data. 164
164
And so here, we can then see it for the first time. 165
165
So now as the page loads, 166
166
it should display this data to us 167
167
in the console. 168
168
And, well, it's nowhere to be found. 169
169
Let's reload here maybe again. 170
170
So something must be wrong, now, 171
171
and it's called workouts. 172
172
And here you go, all right. 173
173
So you see that indeed, it is this big string. 174
174
And so now we want to convert this string 175
175
back to the objects. 176
176
And so, basically we need to use the opposite 177
177
of JSON.stringify which is JSON.parse. 178
178
So let's try that again. 179
179
And now indeed we get an array 180
180
with some real objects in there, all right. 181
181
Now there's still a problem with this, 182
182
but more about that a little bit later, 183
183
because all the relevant data 184
184
that we need for now is actually in there. 185
185
So now let's do something with that data. 186
186
And the first thing that we should actually do 187
187
is to check if there is actually some data. 188
188
So when there is nothing in local storage, 189
189
then of course the data will be, like undefined. 190
190
So in that case, we don't want to do anything. 191
191
So let's use another guard clause here and say, 192
192
if there is no data then simply return. 193
193
But anyway, let's keep going. 194
194
And so what we want to do with this data, 195
195
which is basically our array of workouts, 196
196
is to restore our workouts array. 197
197
So we can say, this.workouts 198
198
should be equal to the data that we just read. 199
199
So, keep in mind that this method here 200
200
is gonna be executed right in the very beginning. 201
201
And so at that point, 202
202
the workouts array is always gonna be empty. 203
203
But if we already had some data in the local storage, 204
204
then, we will simply set that workouts array 205
205
to the data that we had before. 206
206
And so essentially we are restoring the data here 207
207
across multiple reloads of the page. 208
208
Okay, and so now let's take all these workouts 209
209
and render them in the list. 210
210
So this.workouts, 211
211
and so we want to do something 212
212
for each of the workouts. 213
213
And so we loop over this array, 214
214
but we don't want to create a new array. 215
215
And so forEach is perfect for this. 216
216
Then now, I'm gonna call each of them work. 217
217
And so, now I can do this.renderWorkout 218
218
the current workout. 219
219
And so now it becomes really, really helpful 220
220
that we have all the logic 221
221
of rendering a workout in the sidebar 222
222
here nicely inside of this method, right. 223
223
Because, imagine that we had all this code here, 224
224
inside of this method here, 225
225
so the new workout method, right. 226
226
So if we did all of that here, 227
227
then now we would have to copy that code 228
228
or we would have to refactor it. 229
229
But instead, you can start to get into the habit 230
230
of exporting functionality into its own methods 231
231
or its own functions. 232
232
And so then it is very easy to reuse them, 233
233
such as we are doing now with renderWorkout. 234
234
Right. 235
235
So here, all we do is to call renderWorkout 236
236
that we already had written before. 237
237
So let's now test this, 238
238
and right now, 239
239
we should already get the two workouts there, 240
240
and indeed, here they are. 241
241
So these are the two ones that we had created previously. 242
242
And so we see that it did indeed now persist across loads. 243
243
Now, we also need to add them here on the map. 244
244
And so for that, 245
245
we are going to use our renderWorkout marker method 246
246
that we also already have. 247
247
And let's start by actually putting it here, 248
248
just so I can show you 249
249
that it's actually not gonna work. 250
250
But then it becomes easier to explain 251
251
why it doesn't work. 252
252
So let's see. 253
253
And so here we get, 254
254
"Cannot read property 'addlayer' of undefined." 255
255
So indeed, we get an error 256
256
when we try to add this first workout 257
257
also to the map. 258
258
So let's go back and think why that is. 259
259
Well, once again, remember that this method here 260
260
is executed right at the beginning, 261
261
so right after the page loaded. 262
262
And so we are trying to add this marker to the map 263
263
right at the beginning. 264
264
However, at this point, 265
265
the map has actually not yet been loaded. 266
266
And so essentially, 267
267
we are trying to add a marker, 268
268
let's say where that is. 269
269
So we are trying to add this marker to the map, 270
270
which is this one here, 271
271
which isn't yet defined at this point. 272
272
And so once again, this is a first glimpse 273
273
into the nature of asynchronous JavaScript, 274
274
which we will talk about in the next section. 275
275
But what matters here is that you grasp this idea 276
276
that the map is not yet created 277
277
right at the beginning 278
278
when the application is first loaded, right. 279
279
It takes some time. 280
280
So, first the position of the user 281
281
needs to beget using geolocation, 282
282
so this one here. 283
283
And then after that, 284
284
the map has also to be loaded. 285
285
So there's a lot of stuff that has to happen 286
286
before we can actually render any markers on the map. 287
287
So instead of trying to render the markers, 288
288
right at the very beginning, 289
289
we should only do that 290
290
once the map has been loaded. 291
291
And so we can put that logic 292
292
right here in this method of load map, okay. 293
293
So here at the very end, basically. 294
294
So let's get the code from down here. 295
295
So I will get all of this, 296
296
but I will then only keep this part, all right. 297
297
So let's copy this. 298
298
And so here we will not render the markers, 299
299
so only the workout on the sidebar list. 300
300
And then it is here. 301
301
So, yeah. 302
302
Right here in load map, 303
303
this is where we will then render the markers, 304
304
because at this point, 305
305
the map is, of course, already available. 306
306
And so with this, it should be working, okay. 307
307
But make sure that you really understand 308
308
why we have to call this method here 309
309
and not right in the beginning. 310
310
So, let's see what happens now, 311
311
and we didn't get any error and yeah. 312
312
So now we have the two markers 313
313
right where I had put them previously. 314
314
And now let's just add another one right here. 315
315
All right. 316
316
And now if I reload the page, 317
317
then indeed, there is the marker, 318
318
and this one and, of course, all the other ones as well. 319
319
Beautiful. 320
320
So this is great. 321
321
And our application is now essentially finished. 322
322
I just want to show you one problem that we have now. 323
323
And that has to do with local storage. 324
324
So, remember that when I click here 325
325
on one of these workouts, 326
326
it will move the map to the workout, 327
327
and so that's gonna be fine, 328
328
but what also happens is that this clicks property 329
329
is gonna be increased by using the click method 330
330
that is inherited from the workout class. 331
331
But watch what happens now as I try to do that. 332
332
And so we get workout.click is not a function. 333
333
So, why do you think that is? 334
334
Well, let's try to take a look at the objects 335
335
that we get back from local storage. 336
336
So that's this one here. 337
337
And I know that right now 338
338
we have a ton of console.logs here, 339
339
so we should get rid of them at some point, 340
340
but anyway, for now let's take a look 341
341
at the objects that we basically have right now. 342
342
And so this is currently also the data 343
343
that is in this .workouts, right? 344
344
Now, if we take a look at this, 345
345
then here everything works okay. 346
346
But now if we take a look at the prototype chain, 347
347
you see that now it's no longer an object 348
348
of the type of running, 349
349
and also not of the type of workout, right. 350
350
So the entire prototype chain that we had before is gone. 351
351
So contrast that to one of these objects. 352
352
So again, the data is fine, 353
353
but here, we actually have the prototype with calcPace, 354
354
and then that has the click entities, 355
355
that description methods in the workout prototype, right. 356
356
So, the problem here is that basically, 357
357
when we converted our objects to a string, 358
358
and then back from the string to objects, 359
359
we lost the prototype chain. 360
360
And so these new objects here 361
361
that we recovered from the local storage 362
362
are now just regular objects. 363
363
They are now no longer objects 364
364
that were created by the running 365
365
or by the cycling class. 366
366
And so therefore, 367
367
they will not be able to inherit 368
368
any of their methods. 369
369
And so in the end, 370
370
that's the reason why workout.click 371
371
is now not a function anymore. 372
372
So, again, because the object now no longer has it 373
373
in its prototype. 374
374
So you see that this is just the regular methods 375
375
that are available on any object, all right. 376
376
So this can be a big problem 377
377
when you work with local storage 378
378
and object oriented programming 379
379
like we are doing here. 380
380
Now to fix this problem, we could go ahead 381
381
and restore the object right here. 382
382
So, in our getLocalStorage, 383
383
we could now loop over this data here, 384
384
and then restore the objects 385
385
by creating a new object using the class, 386
386
based on the data that is coming here from local storage. 387
387
But that's a little bit of work 388
388
and so we're not gonna do that here. 389
389
And so instead what I will do 390
390
is to simply disable the functionality 391
391
of counting the clicks. 392
392
So remember that when I first introduced this method here, 393
393
I told you that one of the reasons for it 394
394
is that I also wanted to show you something 395
395
in the next lecture. 396
396
And so that's exactly here, 397
397
what I wanted to show you. 398
398
So basically, that objects coming from local storage 399
399
will not inherit all the methods 400
400
that they did before. 401
401
All right. 402
402
And so with that, we are basically done. 403
403
Let's just get rid of some of these console.logs here, 404
404
because it's not really a good practice 405
405
to have them in the final code. 406
406
So we can have maybe one while we're developing, 407
407
but then at some point it simply clutters, 408
408
like our entire console workout. 409
409
And so that's not helpful. 410
410
And here again. 411
411
And you see that here 412
412
we still have all of these workouts, of course. 413
413
Now actually to finish, 414
414
I want to create a quick and easy way 415
415
to delete all of these workouts at once, 416
416
at least from local storage. 417
417
And so let's go back here, 418
418
and basically add a method 419
419
to the public interface of this class 420
420
for the first time. 421
421
So this class is a little bit unusual, 422
422
because right now, we don't have any public method. 423
423
So there's no public interface. 424
424
But now we will create a reset method here, 425
425
which we can then use out here 426
426
or even in the console. 427
427
And so, actually that's what we will do, 428
428
so using it in a console. 429
429
So what I want to do in this one here 430
430
is to basically remove this workouts item 431
431
from local storage. 432
432
And so besides setting and getting items, 433
433
we can also remove items based on the key. 434
434
All right. 435
435
And with this we removed our workouts 436
436
from the local storage, 437
437
and now we can then reload the page programmatically. 438
438
And so then the application will look completely empty. 439
439
And we can do this with location.reload. 440
440
And location is basically a big object 441
441
that contains a lot of methods 442
442
and properties in the browser. 443
443
And so one of the methods 444
444
is the ability to reload the page. 445
445
So, let's try that now. 446
446
And as I said, I will do that in the console. 447
447
So let's go actually back to our code 448
448
just to see where we can use it. 449
449
So, we are creating the app object 450
450
and then storing it in app, right. 451
451
And so we have access to this variable here, 452
452
of course, in the console. 453
453
So let's take a look at that actually. 454
454
And you'll see that indeed, 455
455
here we have these private fields, 456
456
and then we have all of these methods here 457
457
in the prototype. 458
458
And so one of them is of course, reset. 459
459
And so let's do that. 460
460
So reset. 461
461
And yeah, it worked. 462
462
So our application is back to being empty now 463
463
so that we can add some more realistic data 464
464
if we wanted to. 465
465
(typing) 466
466
For example like this, 467
467
or maybe we went cycling right here, 468
468
which is a really nice location. 469
469
And here, let's say we took two hours 470
470
and gained 500 meters, all right. 471
471
And now, of course, 472
472
everything is back to working here 473
473
because we got rid of that click method. 474
474
We still have some logins here to the console, 475
475
but, never mind, that's not a problem. 476
476
All right. 477
477
But what matters here 478
478
is that our application is now feature complete. 479
479
We implemented everything from our flowchart. 480
480
Right. 481
481
So everything is done here. 482
482
And so at this point, the final architecture 483
483
of our application looks like this. 484
484
So I have all of the methods here 485
485
that we implemented in the app class, 486
486
and also for workout, running and cycling. 487
487
Now, I'm not gonna go over this here now, 488
488
but it's a good idea 489
489
for you to actually check it out, 490
490
to get a really good idea 491
491
of how the different methods 492
492
call each other in our application. 493
493
So this arrows that you see here 494
494
are basically methods calling other methods. 495
495
All right. 496
496
And that's it, that's our application, 497
497
I hope that you liked it 498
498
and that you had as much fun as I had building it. 499
499
So this was a really great experience, 500
500
and now before we actually finish the section, 501
501
let's have one more final lecture, 502
502
where I will give you some suggestions 503
503
of how to improve this application even more. 504
504
So let's go there right now.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.