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
So let's now render new workouts 2
2
in the sidebar of our user interface. 3
3
And so what I mean with rendering 4
4
is to basically create a list item like this 5
5
for each workout. 6
6
All right? 7
7
So each workout here contains this like short description, 8
8
containing the type of the workout and then the date 9
9
and actually that's also exactly 10
10
what we get here in the popup. 11
11
And then, of course, we have all the relevant data 12
12
of the workout in case. 13
13
And so let's now go back and do that 14
14
and here we are still in the newWorkout method. 15
15
And so down here is where we're gonna render the workout. 16
16
However, just like before, 17
17
we are actually gonna create a new method, 18
18
which is gonna be called renderWorkout. 19
19
And here I'm seeing that I forgot the underscore. 20
20
Like this. 21
21
And so now let's create renderWorkout 22
22
and so this function will also take in an object 23
23
of a workout. 24
24
All right, and so here, 25
25
all we have to do now is to call this method. 26
26
So renderWorkout and then pass in the workout 27
27
and so with this, we delegated this functionality 28
28
to this method and so let's now start working on it. 29
29
And so what we're gonna do here 30
30
is basically some DOM manipulation. 31
31
So we're gonna create some markup. 32
32
So basically some HTML 33
33
and then we will insert that into the DOM 34
34
whenever there is a new workout. 35
35
And so let's actually get the code right here 36
36
from the HTML and I already have it here commented out. 37
37
So let's actually go up a little bit more. 38
38
So you see that we actually have a ul, 39
39
which stands for unordered list called workout. 40
40
Then in there, the first child is actually a form. 41
41
Okay, and only after that, 42
42
we then start adding these list items 43
43
with the class of workout. 44
44
Now, the first one here is a workout for running. 45
45
And then the second one is a workout for cycling. 46
46
All right? 47
47
So let's basically take what both of them have in common, 48
48
which is basically this first part here, 49
49
which is the distance in kilometers 50
50
and also the duration. 51
51
So these are the same 52
52
but then on running, here we have the pace 53
53
in minutes per kilometer, 54
54
while here, we have kilometers per hour, 55
55
which is the speed 56
56
and here, of course, we have the elevation gain, 57
57
which has this emoji here, 58
58
while here we have these steps per minute. 59
59
And so let's start by taking the HTML here 60
60
that is common to both workouts 61
61
and then after that, we will implement this remaining part 62
62
of both running and cycling. 63
63
So I'm copying it 64
64
and so then here, let's create const html 65
65
and then as always, 66
66
we are gonna use a template literal for this 67
67
because they're really amazing, 68
68
they're really actually perfect 69
69
for doing this kind of stuff. 70
70
Okay. 71
71
So this indentation looks about right. 72
72
Of course, it would work just the same 73
73
as it was before but this then looks a bit nicer 74
74
because it follows the natural structure of HTML. 75
75
Okay, and now all we have to is to replace everything here 76
76
with the real data. 77
77
And let's start with the easy parts. 78
78
So this one here is, of course, the distance. 79
79
And so let's add workout.distance. 80
80
And then down here, we have workout.duration. 81
81
Dot duration. 82
82
Then up here, we actually also have the id 83
83
and so here we once again have this custom data attribute, 84
84
which in this case, I called data-id. 85
85
And remember that we use data properties like this one 86
86
to usually build a bridge 87
87
between the user interface and the data that we have 88
88
in our application. 89
89
And so in a future video, 90
90
this one here will become very important. 91
91
But for now, let's simply add the id here, 92
92
just like before, so workout.id. 93
93
Then next up, here we need to specify whether the workout 94
94
is a running or a cycling workout 95
95
because it's this class here 96
96
that will then give the list item that green 97
97
or that orange border. 98
98
So remember, that is stored at workout.name. 99
99
Then here, we have this emoji here, which is for running 100
100
but for cycling, we have this other one. 101
101
So this guy on the bicycle. 102
102
And I hope that you can see these emojis 103
103
just as well as I can here in the video 104
104
because I know that, I think on some systems, 105
105
this doesn't really work. 106
106
But in that case, that's of course, no problem. 107
107
It doesn't really matter if you can see the emoji or not. 108
108
But anyway, what I'm gonna do here 109
109
is to use the turnary operator 110
110
to check whatever the runner here 111
111
should be displayed or the cycler. 112
112
So that's easy. 113
113
Workout.name and then we just need to test 114
114
if it is running. 115
115
So if it is, then we want basically this to be the output 116
116
and otherwise, this cycler. 117
117
And here I need to close that 118
118
and that's actually it. 119
119
So one more time, the turnary operator 120
120
is super important. 121
121
So as you see, we are still using the fundamentals 122
122
that we learned right in the very, very first section. 123
123
So I said back then that they were important 124
124
and indeed, they were. 125
125
Now, finally, here we have basically this description 126
126
of the workout. 127
127
And it is composed of the workout.name essentially 128
128
and then also the date but nicely formatted. 129
129
And the way that we're gonna generate this description 130
130
is by adding a new method on the workout, 131
131
which will then create a description 132
132
like this one immediately 133
133
when the workout gets actually generated. 134
134
Okay? 135
135
So as I was just saying, here in the workout, 136
136
I will create setDescription. 137
137
And so this is where we now need this array 138
138
that I gave you in the beginning 139
139
with these months. 140
140
So I didn't feel like writing it all out. 141
141
And so here it is. 142
142
And by the way, I have this comment here, 143
143
which is something that we can use 144
144
to tell Prettier, so that Prettier extension 145
145
that we are using to format our code, 146
146
so this comment here we can use whenever we want 147
147
to tell prettier to ignore the next line. 148
148
So let me see what happens if I take this out. 149
149
So then you see I have everything here line by line 150
150
and I don't like that. 151
151
And so this is much nicer in this case. 152
152
Okay. 153
153
But anyway, let's now set the description. 154
154
So this.description. 155
155
So the description will be based on the name 156
156
of the activity 157
157
and actually, I don't mean name, I mean type here. 158
158
And I believe that down there, 159
159
I used name instead of type. 160
160
So let's check that. 161
161
And ja, for some reason, I used name. 162
162
Hopefully, you didn't get too confused by that. 163
163
So of course, that is workout.type and not .name. 164
164
So it's the type that can be either running or cycling. 165
165
All right? 166
166
And so that's what we will use now here 167
167
to create the description. 168
168
So a new template literal 169
169
and then here we actually want 170
170
to make this type here uppercase. 171
171
So the first letter 172
172
and so we can take this.type, 173
173
the first character 174
174
and then toUppercase 175
175
and so this is nothing new. 176
176
We have done this many times before. 177
177
And then simply the rest 178
178
of this type. 179
179
So slice starting from position one. 180
180
So that is the type of the activity in uppercase on 181
181
and so now we want basically the month 182
182
and also the day. 183
183
So we know already that we have the date 184
184
of the workout in this.date 185
185
and then we can use getMonth on that. 186
186
And so remember that this will be here, 187
187
a number between zero and 11. 188
188
And so that's very nice for a zero-based array 189
189
because we can now essentially use this number here 190
190
to retrieve any value out of our month array. 191
191
So if getMonth returns zero, 192
192
then month at position zero is gonna be January 193
193
and the same is, of course, true for all the other months. 194
194
So this one here will give us the month 195
195
and then all we need is the day. 196
196
And so this.date.getDate. 197
197
And that should be it. 198
198
So now whenever a new object is created, 199
199
then automatically the description should be set. 200
200
And so here we now need to do, of course, 201
201
this.setDescription. 202
202
Now, right? 203
203
And in fact, it should not be here 204
204
but it should be down here in each of the child classes. 205
205
So why is that you might be asking? 206
206
Well, that's because that's the class 207
207
that contains the type that we need for this calculation. 208
208
Okay? 209
209
So we need to cut that from here 210
210
and actually calculate it in each of these. 211
211
And of course, this will work perfectly fine 212
212
because through the scope chain, 213
213
this constructor method will get access 214
214
to all the methods of the parent class. 215
215
And so, of course, that includes this one here. 216
216
And so then as the method is executed here, 217
217
it will also get access to the type. 218
218
And so this is the reason why we can use the type here, 219
219
even though it is not defined in this class 220
220
but only in the child class. 221
221
So again, we could not call this method 222
222
on a workout object 223
223
because that doesn't have a type. 224
224
But that's no problem anyway 225
225
because we never actually create new workout objects. 226
226
Now, all right, but with all that being said, 227
227
let's now come back here 228
228
and use this here. 229
229
So workout.description. 230
230
So that's the part that is common to both. 231
231
Now let's get the rest of it. 232
232
So all of this but this one is only for running. 233
233
So let's copy it 234
234
and now here after this part, 235
235
or actually here, we can now say if 236
236
workout.type 237
237
equals running, 238
238
then we want to add something to the HTML. 239
239
So html plus equal and then this code right here. 240
240
So give it a save. 241
241
Then here let's fix the indentation 242
242
or actually, it's good like this. 243
243
Well, actually it isn't. 244
244
So I'm just using multiple cursors 245
245
and yeah, that's better. 246
246
Just do the same thing here. 247
247
Okay. 248
248
And so now here, of course, we need to change it 249
249
to a let variable 250
250
because otherwise, we will not be able 251
251
to add anything to that string. 252
252
And so here, let's now write workout.pace 253
253
and then down here, 254
254
so that's workout.cadence. 255
255
Now, this value here is actually calculated by JavaScript. 256
256
And so the result of this calculation 257
257
might be some very weird number 258
258
and so let's simply round that to one decimal place. 259
259
So toFixed 260
260
and with just one decimal place. 261
261
Okay. 262
262
And now just copying this part. 263
263
So if it's cycling, then we want to get just this part. 264
264
So again, this is the common part. 265
265
This is the one that is different. 266
266
So again, add on to the already existing HTML string. 267
267
And then each time the indentation is a bit different, 268
268
don't have any idea why that is. 269
269
But now it is correct. 270
270
And here, this is probably the speed 271
271
and then here it is the elevationGain 272
272
so I guess that's just called elevation 273
273
but I'm not sure. 274
274
Let's just go back there. 275
275
So yeah, it's called elevationGain here. 276
276
We could have just called it elevation 277
277
because that's how it's called in other parts 278
278
of the application. 279
279
But nevermind, let's just leave it like this for now. 280
280
And here, this speed is also calculated by JavaScript. 281
281
So let's round this one as well. 282
282
And with this, we actually have the HTML generated. 283
283
Now all we need to do is to insert that HTML 284
284
into our DOM. 285
285
So where will we inject this HTML? 286
286
Well, let's take a look here at the parent element 287
287
and that is workouts. 288
288
However, as I mentioned before, 289
289
the first child of the workouts 290
290
is actually this form 291
291
and only the second element 292
292
should then become the first activity. 293
293
And therefore, we cannot simply attach 294
294
the new workout element 295
295
to this ul element 296
296
because we could either insert it as a first child 297
297
or as a last child. 298
298
But we don't want any of those options. 299
299
So instead, we will insert it close to this form 300
300
but basically insert it as a sibling element. 301
301
All right? 302
302
So again, I will take the form 303
303
and then that is where I'm gonna call 304
304
the insertAdjacentHTML method. 305
305
So form.insertAdjacentHTML 306
306
and then here, remember, 307
307
I have to choose between four strings 308
308
and so that's these four here. 309
309
And so the one I'm gonna choose is afterend 310
310
because this one will basically add the new element 311
311
as a sibling element at the end of the form. 312
312
So we discussed these strings before already. 313
313
So you can always go back there if necessary. 314
314
Okay. 315
315
And with this, I think we should be complete. 316
316
We already called it up here. 317
317
Right? 318
318
And so let's now actually try it. 319
319
So let's just reload here manually. 320
320
Okay. 321
321
And now let's just add a simple running 322
322
and now we get a problem. 323
323
So toUppercase is not a function. 324
324
And indeed, it isn't. 325
325
So it has to be UpperCase with the C uppercase. 326
326
So let's see now. 327
327
And again, just putting any numbers here 328
328
and there it is. 329
329
So here is our very first workout rendered 330
330
to the user interface. 331
331
So that's beautiful, really cool. 332
332
Let's now try this with cycling as well. 333
333
And yeah, it does appear here 334
334
and also it appears before the one 335
335
that we had previously. 336
336
And so that is the effect of choosing the afterend string 337
337
in the insertAdjacentHTML method. 338
338
All right, so that's amazing 339
339
but what we need to do next 340
340
is to then actually hide this form 341
341
whenever a new input here happens. 342
342
Right? 343
343
And so let's go do that now. 344
344
And so we need to go back here to our, well, where is that? 345
345
Here in the new workout. 346
346
So here we want to hide the form. 347
347
And so let's create yet another method, 348
348
which is gonna be called hide form. 349
349
So I can already copy or actually cut this one here 350
350
and call the method before I've written it. 351
351
So that's no problem. 352
352
So hideMap will be the name of this method. 353
353
And now let's actually create that. 354
354
And of course, it's not hideMap, it's hideForm. 355
355
So let's do it here right after showForm. 356
356
So that makes sense, right. 357
357
So hideForm. 358
358
So the first thing that we need to do 359
359
is to empty the inputs 360
360
and then we need to add this hidden class back on. 361
361
Now, right, so that's add 362
362
but as we will see in a second, 363
363
this is not yet gonna be enough. 364
364
But let's actually see what I mean here. 365
365
So did you see this animation here 366
366
that happened in the beginning? 367
367
Well, we will need to undo that here in a second. 368
368
So you see that this one here, 369
369
basically did slide up a little bit. 370
370
All right? 371
371
But that's not what we want. 372
372
So here in this version of the app, 373
373
let's see what happens. 374
374
So as the form appears, everything slides down here. 375
375
And now watch what happens as I hit Enter. 376
376
So you saw that? 377
377
Basically it looked as if that form 378
378
was replaced with this new activity here. 379
379
And so to do that, 380
380
it's not enough to simply add back the hidden class here 381
381
because that will then also trigger the animation. 382
382
So instead, we need to hide the form immediately first. 383
383
So form.style.display. 384
384
So we immediately need to set the display to none. 385
385
But then we will actually have to put it back 386
386
after the animation had finished. 387
387
So let's take a look here 388
388
at the form style actually 389
389
so I can show you what I mean. 390
390
Okay. 391
391
So this is the transition that I mean 392
392
and it is because of this one 393
393
that the hidden class has that animation of sliding. 394
394
So that's this transform here, all right? 395
395
So this animations happens over one second. 396
396
And the original value of the display property is grid. 397
397
And so what we will do now 398
398
is to basically after one second set this display 399
399
back to grid. 400
400
So that's kind of a dirty trick here 401
401
but in order to build the layout like this, 402
402
this is what we have to do. 403
403
And it's also a good time 404
404
to bring back or setTimeout function. 405
405
And remember that all that setTimeout does 406
406
is to call a certain callback function 407
407
after a certain time. 408
408
So let's use a simple arrow function here 409
409
to make it really simple. 410
410
So form.style.display 411
411
should be set to grid. 412
412
And this should happen after one second. 413
413
So 1,000 milliseconds 414
414
and so yeah, let's see now. 415
415
All right, so again you saw 416
416
that animation happening there 417
417
but now let's see if we get our desired result 418
418
and yes, there it is. 419
419
So indeed, we did now immediately hide the form 420
420
and then after one second, 421
421
we brought back the original display property. 422
422
And so all that's really left to do 423
423
is to basically add the same description 424
424
that we have here 425
425
to this popup. 426
426
And we will also add a nice emoji, 427
427
so this running guy for running 428
428
and then cycling, as you see here, for the cycling workouts. 429
429
Okay, and this code we can actually get from here. 430
430
So from renderWorkout, we already have this. 431
431
So where is the marker? 432
432
Ah, here it is. 433
433
So here is where we set the content 434
434
and so again, a template literal. 435
435
All right, so this is how we set the emoji 436
436
and then all we need now is the description 437
437
of the workout. 438
438
.description and that should be it. 439
439
All right, so that works beautifully 440
440
and now just for cycling, 441
441
and yes. 442
442
So here's the cycling emoji, 443
443
here's the description 444
444
and so this now works exactly as it does in our demo. 445
445
Great, so we are almost finished actually 446
446
with our application. 447
447
So let's take a look at our flowchart here. 448
448
And so what we're missing now 449
449
is to move the map to the workout location 450
450
whenever we click on one of the workouts 451
451
that we just created. 452
452
And so that's gonna be the topic of the next video.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.