1
00:00:01,390 --> 00:00:03,760
<v Instructor>So using the workout classes</v>

2
00:00:03,760 --> 00:00:05,270
that we just implemented,

3
00:00:05,270 --> 00:00:07,680
let's now finally implement the feature

4
00:00:07,680 --> 00:00:11,383
of creating a new workout from our user interface.

5
00:00:13,010 --> 00:00:16,423
And to start, let's take a look at our flowchart here.

6
00:00:17,842 --> 00:00:19,970
And so basically, this here is the action

7
00:00:19,970 --> 00:00:21,840
that we're interested in now

8
00:00:21,840 --> 00:00:24,800
so when the user submits a new workout.

9
00:00:24,800 --> 00:00:29,410
And so we already added this new workout method here

10
00:00:29,410 --> 00:00:32,850
as an event handler function for that event.

11
00:00:32,850 --> 00:00:35,290
And so what we want to happen now

12
00:00:35,290 --> 00:00:38,760
is to basically render the workout on the map,

13
00:00:38,760 --> 00:00:41,680
render the workout on the list

14
00:00:41,680 --> 00:00:44,803
and then this part here, we're gonna leave for later.

15
00:00:45,830 --> 00:00:48,260
So this one is the high level overview

16
00:00:48,260 --> 00:00:50,200
of what needs to happen.

17
00:00:50,200 --> 00:00:53,130
But actually, there's a lot more things involved

18
00:00:53,130 --> 00:00:55,070
than just these immediate actions

19
00:00:55,070 --> 00:00:57,730
that we see on the user interface.

20
00:00:57,730 --> 00:01:00,160
So actually, we're gonna leave the rendering here

21
00:01:00,160 --> 00:01:01,560
for the next video,

22
00:01:01,560 --> 00:01:03,033
because as I just said,

23
00:01:03,033 --> 00:01:05,490
there's actually a lot of other stuff

24
00:01:05,490 --> 00:01:08,453
that we have to do, now right?

25
00:01:09,670 --> 00:01:13,810
So as you see, we are back here at looking at the flowchart

26
00:01:13,810 --> 00:01:16,390
because now we are back to being interested

27
00:01:16,390 --> 00:01:18,680
what we actually need to implement,

28
00:01:18,680 --> 00:01:22,420
and not how to implement it, right?

29
00:01:22,420 --> 00:01:24,470
So the architecture here, again,

30
00:01:24,470 --> 00:01:26,870
is about how we implement it.

31
00:01:26,870 --> 00:01:29,560
And so it contains all of these different methods

32
00:01:29,560 --> 00:01:31,710
and these low level details,

33
00:01:31,710 --> 00:01:33,210
while the flowchart here

34
00:01:33,210 --> 00:01:35,860
is really more of a high level overview

35
00:01:35,860 --> 00:01:38,440
of what we want to implement.

36
00:01:38,440 --> 00:01:41,330
And so for now, we don't need the architecture anymore,

37
00:01:41,330 --> 00:01:44,573
because we already put everything into the code

38
00:01:44,573 --> 00:01:46,520
that we had here.

39
00:01:46,520 --> 00:01:48,120
Now, if you're really curious

40
00:01:48,120 --> 00:01:50,930
and want to spoil the experience,

41
00:01:50,930 --> 00:01:53,660
basically until the end of the section,

42
00:01:53,660 --> 00:01:55,440
then you can already take a look

43
00:01:55,440 --> 00:01:57,940
at the final architecture here

44
00:01:57,940 --> 00:01:59,910
but I'm not gonna do that.

45
00:01:59,910 --> 00:02:01,970
So I just want to now keep building

46
00:02:01,970 --> 00:02:06,490
the rest of the application as we go, okay?

47
00:02:06,490 --> 00:02:09,785
But anyway, since this is so high level here,

48
00:02:09,785 --> 00:02:13,450
let's actually go to the working demo application

49
00:02:13,450 --> 00:02:15,383
and see what exactly happens.

50
00:02:16,300 --> 00:02:17,593
So let's reload here.

51
00:02:18,920 --> 00:02:21,460
And so let's click just somewhere.

52
00:02:21,460 --> 00:02:25,400
And then you see, as we already know, the form opens,

53
00:02:25,400 --> 00:02:27,910
then we can input some data here

54
00:02:27,910 --> 00:02:31,440
and then our application needs to get this data,

55
00:02:31,440 --> 00:02:34,720
it needs to check if the data actually makes sense.

56
00:02:34,720 --> 00:02:36,820
And then we need to create a new object

57
00:02:36,820 --> 00:02:40,840
for this workout and render it right here

58
00:02:40,840 --> 00:02:43,760
and also on the map, of course.

59
00:02:43,760 --> 00:02:47,750
And then finally, after all that the form is also hidden.

60
00:02:47,750 --> 00:02:49,990
So everything I just said is gonna happen

61
00:02:49,990 --> 00:02:52,570
whenever we hit enter here.

62
00:02:52,570 --> 00:02:55,110
So you see, of course, the marker was created,

63
00:02:55,110 --> 00:02:56,860
it was rendered here,

64
00:02:56,860 --> 00:02:58,900
all the input data had to be checked,

65
00:02:58,900 --> 00:03:01,783
and a new running object was created.

66
00:03:02,710 --> 00:03:05,210
So for example, if we add another one,

67
00:03:05,210 --> 00:03:07,320
but without any data,

68
00:03:07,320 --> 00:03:10,310
then we are gonna get this alert.

69
00:03:10,310 --> 00:03:12,620
Or the same if we input any data

70
00:03:12,620 --> 00:03:14,710
that doesn't make much sense.

71
00:03:14,710 --> 00:03:17,720
For example, a negative number for the cadence,

72
00:03:17,720 --> 00:03:19,620
which is of course impossible.

73
00:03:19,620 --> 00:03:22,710
And so again, we get this error here.

74
00:03:22,710 --> 00:03:25,580
So input validation is an important part

75
00:03:25,580 --> 00:03:29,503
of creating any application that works with user inputs.

76
00:03:30,630 --> 00:03:33,883
And so let's now actually work on the function

77
00:03:33,883 --> 00:03:37,640
that is responsible for doing all of this.

78
00:03:37,640 --> 00:03:40,790
And for starters, I will basically document

79
00:03:40,790 --> 00:03:43,563
everything that we need to do here using comments.

80
00:03:44,550 --> 00:03:46,680
So first, we need to get data

81
00:03:48,270 --> 00:03:51,570
from the form, then we need to check

82
00:03:53,070 --> 00:03:55,453
if data is valid,

83
00:03:57,400 --> 00:03:59,163
then if it's running,

84
00:04:00,310 --> 00:04:04,343
so if the activity running, then create running object.

85
00:04:08,560 --> 00:04:11,050
And if the activity is cycling,

86
00:04:11,050 --> 00:04:14,463
then of course, create a cycling object.

87
00:04:17,310 --> 00:04:22,310
Then add the new object to the work out array.

88
00:04:24,370 --> 00:04:27,480
And so, yeah, instead of activity,

89
00:04:27,480 --> 00:04:29,533
let's actually call it work out here.

90
00:04:32,730 --> 00:04:34,293
Then we want to render,

91
00:04:35,220 --> 00:04:38,380
workout on map as a marker

92
00:04:38,380 --> 00:04:40,200
and finally, we want to render

93
00:04:41,540 --> 00:04:43,513
the new workout on the list.

94
00:04:44,910 --> 00:04:48,020
And finally also, we want to then hide the form

95
00:04:49,640 --> 00:04:51,993
and clear the input fields.

96
00:04:54,730 --> 00:04:57,910
So you see there's gonna be a lot of work.

97
00:04:57,910 --> 00:05:02,410
Let's put this one for now at least here,

98
00:05:02,410 --> 00:05:05,043
even though it's not gonna really work like this.

99
00:05:07,550 --> 00:05:12,550
But okay, so with this, we now have all the steps lined out

100
00:05:12,610 --> 00:05:14,383
and so let's get started.

101
00:05:15,810 --> 00:05:18,960
And we're gonna start by getting the data from the forum

102
00:05:18,960 --> 00:05:20,900
and starting with the type,

103
00:05:20,900 --> 00:05:24,773
and type is already stored at the variable input type.

104
00:05:25,770 --> 00:05:27,700
So that's all the way up here.

105
00:05:27,700 --> 00:05:29,863
Let's bring that down, actually.

106
00:05:31,640 --> 00:05:35,820
And we could even add these elements here

107
00:05:35,820 --> 00:05:39,550
basically as fields also inside of the application.

108
00:05:39,550 --> 00:05:42,190
But in this case, I prefer not to do that

109
00:05:42,190 --> 00:05:45,570
because then every time that we wanted to reference

110
00:05:45,570 --> 00:05:47,520
one of these elements,

111
00:05:47,520 --> 00:05:50,420
then we would always have to use like this .inputDistance,

112
00:05:51,330 --> 00:05:54,580
or duration, and so on and so forth.

113
00:05:54,580 --> 00:05:56,683
And I just don't really like that.

114
00:05:57,640 --> 00:06:00,490
But anyway, let's not take the values of input type,

115
00:06:00,490 --> 00:06:03,653
distance, duration, cadence and elevation.

116
00:06:06,030 --> 00:06:09,170
And these two here are not that straightforward

117
00:06:09,170 --> 00:06:11,513
but let's see that in a minute.

118
00:06:13,980 --> 00:06:15,817
So inputType.value.

119
00:06:19,216 --> 00:06:22,460
And so input type is actually a select element.

120
00:06:22,460 --> 00:06:26,810
But still, we get the value using the value property.

121
00:06:26,810 --> 00:06:28,260
Let me just show that to you.

122
00:06:29,380 --> 00:06:32,150
And so, yeah, here it is.

123
00:06:32,150 --> 00:06:34,580
And so each option has this value.

124
00:06:34,580 --> 00:06:37,130
And so for running, the value is running

125
00:06:37,130 --> 00:06:41,887
with the lowercase r, and for cycling the same, okay?

126
00:06:41,887 --> 00:06:44,030
And so again, the value will be

127
00:06:44,030 --> 00:06:46,280
whatever of these two is selected,

128
00:06:46,280 --> 00:06:48,560
and then we get this value here.

129
00:06:48,560 --> 00:06:50,773
And so that will be important in a minute.

130
00:06:53,290 --> 00:06:56,143
But anyway, let's not take the distance.

131
00:06:58,430 --> 00:07:02,070
So that's inputDistance.value

132
00:07:02,070 --> 00:07:05,330
and remember that this always comes as strings

133
00:07:05,330 --> 00:07:08,653
and so let's convert that immediately to a number.

134
00:07:10,960 --> 00:07:13,070
Then the duration.

135
00:07:13,070 --> 00:07:18,070
Let's do the same here, inputDuration.value.

136
00:07:19,720 --> 00:07:22,350
Now about the cadence and the elevation gain,

137
00:07:22,350 --> 00:07:23,930
we actually don't want to get them

138
00:07:23,930 --> 00:07:25,500
here right in the beginning.

139
00:07:25,500 --> 00:07:27,620
But the cadence, we only want to get

140
00:07:27,620 --> 00:07:29,440
if it is a running workout.

141
00:07:29,440 --> 00:07:30,500
And the elevation gain,

142
00:07:30,500 --> 00:07:34,000
we only want to get if it is a cycling workout,

143
00:07:34,000 --> 00:07:36,040
because that will then make it easier for us

144
00:07:36,040 --> 00:07:38,300
to validate the data.

145
00:07:38,300 --> 00:07:40,760
But more about that in a second.

146
00:07:40,760 --> 00:07:42,240
So for now, let's actually check

147
00:07:42,240 --> 00:07:44,523
what kind of workout we are dealing with.

148
00:07:45,580 --> 00:07:48,143
And so all we have to do is to check the type.

149
00:07:49,610 --> 00:07:50,823
And if it's running,

150
00:07:51,800 --> 00:07:54,886
then we want to get the cadence.

151
00:07:54,886 --> 00:07:57,330
So let's call that cadences as well

152
00:07:57,330 --> 00:08:02,330
and convert inputCadence.value to a number.

153
00:08:02,840 --> 00:08:05,563
But if we are dealing with cycling,

154
00:08:06,550 --> 00:08:08,153
then we want the elevation gain.

155
00:08:12,270 --> 00:08:13,470
So let's called this one

156
00:08:15,380 --> 00:08:20,303
elevation and here it's also called input elevation.

157
00:08:21,210 --> 00:08:25,400
Now okay, and so now let's check if the data is valid.

158
00:08:25,400 --> 00:08:26,830
And so we will not do that

159
00:08:26,830 --> 00:08:30,103
inside of each of these if statements.

160
00:08:31,030 --> 00:08:32,310
Now you might have noticed

161
00:08:32,310 --> 00:08:35,470
that I actually created two separate if statements here

162
00:08:35,470 --> 00:08:37,830
instead of an if else statement.

163
00:08:37,830 --> 00:08:41,160
And that's just something that you will see more and more

164
00:08:41,160 --> 00:08:42,830
in modern JavaScript.

165
00:08:42,830 --> 00:08:46,670
So the if else is not really that much used anymore.

166
00:08:46,670 --> 00:08:50,620
And I think that actually it looks a lot cleaner like this

167
00:08:50,620 --> 00:08:53,043
so to simply have two if statements.

168
00:08:54,490 --> 00:08:58,390
So anyway, let's not check if the data is valid.

169
00:08:58,390 --> 00:09:01,890
And what does it mean for the data to be valid?

170
00:09:01,890 --> 00:09:06,693
Well, first of all, each of them should be a number, right?

171
00:09:07,770 --> 00:09:09,623
And so let's do that.

172
00:09:11,670 --> 00:09:15,460
And here again, we will actually use a guard clause.

173
00:09:15,460 --> 00:09:17,910
So again, what a guard clause means

174
00:09:17,910 --> 00:09:20,610
is that we will basically check for the opposite

175
00:09:20,610 --> 00:09:23,410
of what we are originally interested in

176
00:09:23,410 --> 00:09:25,190
and if that opposite is true,

177
00:09:25,190 --> 00:09:28,050
then we simply return the function immediately.

178
00:09:28,050 --> 00:09:29,330
And so once again,

179
00:09:29,330 --> 00:09:32,810
this is a trait of more modern JavaScript.

180
00:09:32,810 --> 00:09:37,220
So kind of a trend that you will see in modern JavaScript.

181
00:09:37,220 --> 00:09:40,180
But anyway, let me show you what I mean here.

182
00:09:40,180 --> 00:09:42,733
So if the distance is not a number,

183
00:09:44,130 --> 00:09:47,163
and remember that for that, we use a Number.isFinite.

184
00:09:51,970 --> 00:09:55,570
So if the distance here is not a number,

185
00:09:55,570 --> 00:09:57,893
then we want to return immediately.

186
00:09:58,900 --> 00:10:00,240
So we want to return

187
00:10:00,240 --> 00:10:03,683
and then we can also do some other code here.

188
00:10:04,540 --> 00:10:05,943
So let's create an alert.

189
00:10:07,430 --> 00:10:12,430
So inputs have to be positive numbers.

190
00:10:13,412 --> 00:10:15,290
And so for now we check for numbers

191
00:10:15,290 --> 00:10:17,970
but we didn't yet check for positive.

192
00:10:17,970 --> 00:10:20,710
But let's leave that for a second.

193
00:10:20,710 --> 00:10:23,860
So we should already be able to test out

194
00:10:23,860 --> 00:10:25,623
if this if here is gonna work.

195
00:10:27,590 --> 00:10:29,930
So let's just see if our map appears here.

196
00:10:32,916 --> 00:10:34,870
And let's try to reload here.

197
00:10:34,870 --> 00:10:36,610
And for some reason, sometimes

198
00:10:36,610 --> 00:10:38,730
this takes a really long time.

199
00:10:38,730 --> 00:10:41,950
So sometimes while I was developing this application,

200
00:10:41,950 --> 00:10:44,590
I waited up to like two or three minutes

201
00:10:44,590 --> 00:10:46,920
and I don't know why that happens.

202
00:10:46,920 --> 00:10:50,190
But yeah, I hope that never happens for you.

203
00:10:50,190 --> 00:10:52,200
But in case you see long waiting times,

204
00:10:52,200 --> 00:10:54,393
that might be normal, all right?

205
00:10:55,970 --> 00:10:57,743
But now here it is.

206
00:10:58,812 --> 00:11:02,790
And so let's input some invalid distance.

207
00:11:02,790 --> 00:11:04,960
So like just any letter,

208
00:11:04,960 --> 00:11:07,893
and then we get inputs have to be positive numbers.

209
00:11:09,080 --> 00:11:11,700
So that is already working.

210
00:11:11,700 --> 00:11:14,923
And now we just need to do the same with the other inputs.

211
00:11:15,800 --> 00:11:18,943
So we want the same for the distance.

212
00:11:20,020 --> 00:11:21,643
So Number.isFinite.

213
00:11:24,920 --> 00:11:26,370
So actually, for duration

214
00:11:27,290 --> 00:11:32,290
and then the same thing for Number.isFinite cadence, okay?

215
00:11:38,090 --> 00:11:39,950
Now, this is actually not correct,

216
00:11:39,950 --> 00:11:44,590
because we don't want the and but instead, we want or.

217
00:11:44,590 --> 00:11:46,330
So this one here should happen

218
00:11:46,330 --> 00:11:50,130
whenever one of these three here is not a number

219
00:11:50,130 --> 00:11:54,610
and not when all of them are invalid numbers, right?

220
00:11:54,610 --> 00:11:56,963
And so that's exactly what or means.

221
00:11:58,560 --> 00:12:01,100
So if this one is an invalid number,

222
00:12:01,100 --> 00:12:06,100
or this one, or this one, then we can get this alert.

223
00:12:06,570 --> 00:12:10,020
And so the reason why we did this checking here

224
00:12:10,020 --> 00:12:13,710
inside of this if block

225
00:12:13,710 --> 00:12:16,350
is because if we did the same out here,

226
00:12:16,350 --> 00:12:20,320
then we would also want to check for the elevation, right?

227
00:12:20,320 --> 00:12:21,580
But as we know already,

228
00:12:21,580 --> 00:12:24,460
only one of the cadence and elevation

229
00:12:24,460 --> 00:12:26,710
can be defined at the same time,

230
00:12:26,710 --> 00:12:30,320
they cannot both be defined at the same time.

231
00:12:30,320 --> 00:12:31,860
And so performing this check

232
00:12:31,860 --> 00:12:34,830
would then be a little bit more difficult.

233
00:12:34,830 --> 00:12:39,410
So now we can go ahead and do the same thing down here.

234
00:12:39,410 --> 00:12:41,270
So in the cycling part,

235
00:12:41,270 --> 00:12:44,710
but let's actually refactor this code here already.

236
00:12:44,710 --> 00:12:47,120
And basically create a small function,

237
00:12:47,120 --> 00:12:49,630
which takes a number of arguments,

238
00:12:49,630 --> 00:12:51,800
and will then validate if all of them

239
00:12:51,800 --> 00:12:54,003
are numbers or not, okay?

240
00:12:56,350 --> 00:12:59,560
So basically, we wanted to work like this

241
00:12:59,560 --> 00:13:00,780
but we wanted to write this

242
00:13:00,780 --> 00:13:03,910
in a more clear and more beautiful

243
00:13:03,910 --> 00:13:07,623
so to say, way, all right?

244
00:13:08,460 --> 00:13:11,463
So let's create a very simple helper function here.

245
00:13:12,700 --> 00:13:14,793
And let me call it validInputs.

246
00:13:18,310 --> 00:13:20,490
So a very simple arrow function

247
00:13:20,490 --> 00:13:23,863
and this can take an arbitrary number of inputs.

248
00:13:27,450 --> 00:13:31,160
And remember that when we use rest parameters like this,

249
00:13:31,160 --> 00:13:32,373
then we get an array.

250
00:13:34,130 --> 00:13:36,110
So inputs is an array

251
00:13:36,110 --> 00:13:38,520
and we now want to loop over this array,

252
00:13:38,520 --> 00:13:42,470
and basically check if all of them are positive.

253
00:13:42,470 --> 00:13:45,360
Now there's actually already a predefined method

254
00:13:45,360 --> 00:13:48,760
in JavaScript, that is very helpful for that.

255
00:13:48,760 --> 00:13:53,253
So remember that we have a nice little method called every.

256
00:13:54,490 --> 00:13:56,890
And so let's use it here.

257
00:13:56,890 --> 00:13:59,140
And then I will quickly explain what it does.

258
00:14:00,250 --> 00:14:01,920
So the current input,

259
00:14:01,920 --> 00:14:06,920
and then Number.IsFinite, the current input.

260
00:14:09,110 --> 00:14:12,160
So basically, this will loop over the array,

261
00:14:12,160 --> 00:14:13,330
and then each of them,

262
00:14:13,330 --> 00:14:17,740
it will check whether the number is finite or not.

263
00:14:17,740 --> 00:14:20,100
And then in the end, the every method

264
00:14:20,100 --> 00:14:23,160
will only return true if this value here

265
00:14:23,160 --> 00:14:25,590
was true for all of them.

266
00:14:25,590 --> 00:14:28,000
So for all elements in the array.

267
00:14:28,000 --> 00:14:32,190
But if only one of these values here was not finite,

268
00:14:32,190 --> 00:14:34,480
so if the result here was false

269
00:14:34,480 --> 00:14:37,200
for one of the elements of the array,

270
00:14:37,200 --> 00:14:39,690
then every will return false.

271
00:14:39,690 --> 00:14:42,120
And so that will then be the return value

272
00:14:42,120 --> 00:14:44,710
of this arrow function, right?

273
00:14:44,710 --> 00:14:47,833
And so then here, we can replace all of this.

274
00:14:49,270 --> 00:14:53,290
And let's actually just comment it out.

275
00:14:53,290 --> 00:14:57,010
We cannot say if not validInputs,

276
00:14:57,010 --> 00:15:00,580
and then pass in the three that we're interested in.

277
00:15:00,580 --> 00:15:05,580
So distance, duration, and cadence.

278
00:15:06,880 --> 00:15:11,820
And again, here we are inverting the condition, right?

279
00:15:11,820 --> 00:15:14,010
So if all of these are numbers,

280
00:15:14,010 --> 00:15:17,050
then this here will become true, right?

281
00:15:17,050 --> 00:15:19,150
But whenever this is not true,

282
00:15:19,150 --> 00:15:21,260
then that's the case where we want to return

283
00:15:21,260 --> 00:15:25,250
from the function and show this alert Window, all right?

284
00:15:28,470 --> 00:15:29,770
So let's copy this

285
00:15:31,628 --> 00:15:36,150
and do the same here for the elevation like this.

286
00:15:37,386 --> 00:15:39,436
And here, I will get rid of the comments.

287
00:15:40,370 --> 00:15:42,810
And so this is the first check.

288
00:15:42,810 --> 00:15:44,990
But in fact, we also want to test

289
00:15:44,990 --> 00:15:47,240
if the numbers are positive,

290
00:15:47,240 --> 00:15:50,710
because otherwise, they don't make much sense.

291
00:15:50,710 --> 00:15:52,223
So let's reload here again.

292
00:15:53,960 --> 00:15:57,019
So right now, if I put a letter in any of these,

293
00:15:57,019 --> 00:16:00,880
then it's not gonna work, right?

294
00:16:00,880 --> 00:16:05,310
But if I put in a negative number of steps,

295
00:16:05,310 --> 00:16:07,830
then this is perfectly acceptable

296
00:16:07,830 --> 00:16:12,040
and we already get the marker here printed to the map.

297
00:16:12,040 --> 00:16:15,650
But in fact, we don't want this to be acceptable.

298
00:16:15,650 --> 00:16:18,040
So negative values should not be allowed

299
00:16:18,040 --> 00:16:20,170
for any of these three.

300
00:16:20,170 --> 00:16:22,080
But in the cycling, it should be allowed

301
00:16:22,080 --> 00:16:23,810
for the elevation gain.

302
00:16:23,810 --> 00:16:26,660
So here, we can, of course have a negative number,

303
00:16:26,660 --> 00:16:30,823
which happens when we go basically down a mountain, right?

304
00:16:31,990 --> 00:16:35,490
So that's simple as well,

305
00:16:35,490 --> 00:16:39,000
all you have to do is to check if these three values here

306
00:16:39,000 --> 00:16:43,000
are greater than zero, and the same for these two,

307
00:16:43,000 --> 00:16:44,363
but not for the elevation, okay?

308
00:16:45,970 --> 00:16:48,840
And so actually, to make this really cool,

309
00:16:48,840 --> 00:16:52,633
I will create another small helper function like this one.

310
00:16:53,570 --> 00:16:56,060
And it might be a good habit for you as well

311
00:16:56,060 --> 00:16:59,410
to get used to these small helper functions.

312
00:16:59,410 --> 00:17:02,290
So they're especially nice in these situations

313
00:17:02,290 --> 00:17:04,293
for testing complex conditions.

314
00:17:05,130 --> 00:17:06,961
So instead of writing all of this,

315
00:17:06,961 --> 00:17:10,660
and plus checking now for positive numbers,

316
00:17:10,660 --> 00:17:14,200
we can simply export that into one or two functions,

317
00:17:14,200 --> 00:17:16,053
which then do the job for us.

318
00:17:17,370 --> 00:17:21,160
So here, I'm gonna create a function called all positive,

319
00:17:21,160 --> 00:17:23,430
and this one is gonna be almost the same

320
00:17:23,430 --> 00:17:24,603
as the previous one.

321
00:17:25,490 --> 00:17:28,663
So it takes in an arbitrary amount of inputs.

322
00:17:32,250 --> 00:17:36,160
And then we will only return true if all of them

323
00:17:36,160 --> 00:17:38,320
are greater than zero.

324
00:17:38,320 --> 00:17:42,350
And so here the every method is very useful again.

325
00:17:42,350 --> 00:17:45,700
So input, and then here, we need some condition

326
00:17:45,700 --> 00:17:48,170
that returns true or false.

327
00:17:48,170 --> 00:17:51,733
And so that's input greater than zero.

328
00:17:53,100 --> 00:17:55,630
And so let's not use that here.

329
00:17:55,630 --> 00:17:57,692
And so we want basically,

330
00:17:57,692 --> 00:18:01,810
if all of the inputs are not valid,

331
00:18:01,810 --> 00:18:06,810
or if there is basically any number that is not positive.

332
00:18:06,840 --> 00:18:08,880
So if not all positive

333
00:18:10,980 --> 00:18:15,980
distance, duration, and cadence, all right?

334
00:18:18,770 --> 00:18:21,680
So in this case, we then want to get this alert

335
00:18:22,660 --> 00:18:27,660
and now here, let's do the same for the cycling.

336
00:18:30,150 --> 00:18:33,650
But here, we are only interested in distance and duration,

337
00:18:33,650 --> 00:18:37,563
because again, the elevation might very well be negative.

338
00:18:39,010 --> 00:18:41,720
So this is a little bit complex validation

339
00:18:41,720 --> 00:18:43,590
but that's no problem at all.

340
00:18:43,590 --> 00:18:46,670
That's why I spent some time here on this validation

341
00:18:46,670 --> 00:18:48,580
without any problem.

342
00:18:48,580 --> 00:18:50,720
Now, it would have been a little bit easier

343
00:18:50,720 --> 00:18:53,060
if we didn't have these different values

344
00:18:53,060 --> 00:18:56,433
of elevation and cadence for the two different workouts.

345
00:18:57,280 --> 00:19:00,790
But we do have it and yeah,

346
00:19:00,790 --> 00:19:03,040
so we have to solve that problem.

347
00:19:03,040 --> 00:19:07,060
And so I think it works really nice like this.

348
00:19:07,060 --> 00:19:10,330
Let me just check it out here one more time now

349
00:19:10,330 --> 00:19:13,130
with these negative values.

350
00:19:13,130 --> 00:19:15,560
So if we have a negative distance,

351
00:19:15,560 --> 00:19:20,560
then now indeed, we get the alert to accept for cycling.

352
00:19:22,580 --> 00:19:27,580
So let's remove that one, and two, two

353
00:19:27,670 --> 00:19:31,830
and two here minus two, but that still works.

354
00:19:31,830 --> 00:19:36,830
And so clearly, our validation logic here is just fine.

355
00:19:37,500 --> 00:19:41,513
Great, so next up, let's see what we have to do.

356
00:19:42,470 --> 00:19:47,150
So actually, we still have to finish these ones.

357
00:19:47,150 --> 00:19:48,830
So if the workout is running,

358
00:19:48,830 --> 00:19:50,800
then create a running object

359
00:19:50,800 --> 00:19:55,140
and otherwise, create a cycling object, now right?

360
00:19:55,140 --> 00:20:00,140
And then afterwards, push that object to the workout array.

361
00:20:00,320 --> 00:20:01,920
So add it to the array

362
00:20:01,920 --> 00:20:05,043
and for that, we're gonna use the push method as always.

363
00:20:06,730 --> 00:20:08,650
So let's start with this one here,

364
00:20:08,650 --> 00:20:12,660
right after this guard clause, all right?

365
00:20:12,660 --> 00:20:17,660
And so here, let's say, work out, should be a new running.

366
00:20:19,820 --> 00:20:23,590
And now let's see what we need for running.

367
00:20:23,590 --> 00:20:26,410
Or actually, we can probably just hover this

368
00:20:26,410 --> 00:20:28,680
and indeed, here we have two coordinates,

369
00:20:28,680 --> 00:20:32,900
distance, duration and cadence, all right.

370
00:20:32,900 --> 00:20:35,603
So where do we get the coordinates from?

371
00:20:36,900 --> 00:20:40,290
Well, we already know from the marker

372
00:20:40,290 --> 00:20:42,350
that they are right here.

373
00:20:42,350 --> 00:20:44,250
So in this.MapEvent.latitudelongitude.

374
00:20:46,530 --> 00:20:49,630
So we notice because we already used this data before

375
00:20:49,630 --> 00:20:52,460
to render a marker on the map.

376
00:20:52,460 --> 00:20:55,540
So let's get this one and paste it here

377
00:20:55,540 --> 00:20:56,883
as the first argument.

378
00:20:58,150 --> 00:21:02,193
But actually, this here is now gonna be an object.

379
00:21:03,570 --> 00:21:07,410
So we know that because here we use destructuring,

380
00:21:07,410 --> 00:21:11,850
to get the latitude and longitude out of that object.

381
00:21:11,850 --> 00:21:14,680
But up here, we said,

382
00:21:14,680 --> 00:21:16,280
so in the class definition,

383
00:21:16,280 --> 00:21:18,943
that indeed we want an array, right?

384
00:21:20,260 --> 00:21:25,260
So let's simply get this code from here, to up there.

385
00:21:27,250 --> 00:21:30,680
So here, and so basically create

386
00:21:30,680 --> 00:21:33,290
the latitude and longitude variables here

387
00:21:33,290 --> 00:21:35,620
based on this object.

388
00:21:35,620 --> 00:21:40,560
And so then here, we can define an array with.data.

389
00:21:40,560 --> 00:21:42,813
So lat and launch.

390
00:21:44,220 --> 00:21:47,540
So we already have our array of the coordinates

391
00:21:47,540 --> 00:21:49,320
just as expected.

392
00:21:49,320 --> 00:21:54,083
And then all we need is distance, duration and cadence.

393
00:21:57,120 --> 00:22:01,600
And then we can take this.activities,

394
00:22:01,600 --> 00:22:04,253
and I think we didn't even create that one yet.

395
00:22:05,460 --> 00:22:08,357
So that's up here.

396
00:22:08,357 --> 00:22:11,913
And now again, we could do it right here like this.

397
00:22:12,770 --> 00:22:15,430
So basically, the more classical way.

398
00:22:15,430 --> 00:22:20,430
So this.workouts would be an empty array.

399
00:22:22,610 --> 00:22:24,200
But again, in this project,

400
00:22:24,200 --> 00:22:28,213
I chose to already use the class fields specification.

401
00:22:29,120 --> 00:22:30,670
And so this will become part

402
00:22:30,670 --> 00:22:33,720
of standard JavaScript very soon.

403
00:22:33,720 --> 00:22:37,380
And so therefore, I can create a class field like this

404
00:22:37,380 --> 00:22:41,440
and I can even make it private, just like the other two.

405
00:22:41,440 --> 00:22:44,660
But this time, I actually already initialized it here

406
00:22:44,660 --> 00:22:47,500
to a new empty array.

407
00:22:47,500 --> 00:22:48,993
And so now we can take that.

408
00:22:50,170 --> 00:22:54,423
So here in new workout, we can say this.workouts.push

409
00:22:58,880 --> 00:23:00,453
this new workout.

410
00:23:02,320 --> 00:23:04,050
Now, we are gonna do

411
00:23:04,050 --> 00:23:07,053
basically the exact same thing down here.

412
00:23:07,900 --> 00:23:11,283
And so this here is something that always needs to happen.

413
00:23:12,230 --> 00:23:15,470
So in both cases, and so let's not repeat that,

414
00:23:15,470 --> 00:23:18,090
and instead, put it down here.

415
00:23:18,090 --> 00:23:21,350
But then we have the problem that this workout variable

416
00:23:21,350 --> 00:23:25,540
is defined here in this block scope, right?

417
00:23:25,540 --> 00:23:28,830
And so because of the scope chain, as we already know,

418
00:23:28,830 --> 00:23:32,880
this workout variable will then not be available outside

419
00:23:32,880 --> 00:23:35,920
of this block, right?

420
00:23:35,920 --> 00:23:38,470
But we want it outside of the block.

421
00:23:38,470 --> 00:23:40,870
So right here, and so therefore,

422
00:23:40,870 --> 00:23:43,203
we put it right here outside.

423
00:23:45,650 --> 00:23:47,053
So let's work out.

424
00:23:49,050 --> 00:23:51,923
And then here, we simply redefine that.

425
00:23:53,160 --> 00:23:54,770
And then let's simply take this

426
00:23:58,030 --> 00:23:59,930
and put it here again.

427
00:23:59,930 --> 00:24:03,223
But this time, of course, with a cycling,

428
00:24:04,140 --> 00:24:07,230
and then still the coordinates, distance, duration,

429
00:24:07,230 --> 00:24:10,763
but here the elevation, all right?

430
00:24:12,320 --> 00:24:15,490
The next step here is to actually render the workout

431
00:24:15,490 --> 00:24:18,870
on the map, all right?

432
00:24:18,870 --> 00:24:22,030
But before we do that, let's actually take a quick look

433
00:24:22,893 --> 00:24:27,570
at the console, and see our work out there.

434
00:24:27,570 --> 00:24:30,290
And so with that, we can already check

435
00:24:30,290 --> 00:24:33,060
if all of this that we have up here

436
00:24:33,060 --> 00:24:36,003
is already working, right?

437
00:24:38,020 --> 00:24:40,770
Okay, so let's wait for the map.

438
00:24:40,770 --> 00:24:44,910
And now let's click here and add a running.

439
00:24:44,910 --> 00:24:49,910
So five, and 25 with 170.

440
00:24:50,370 --> 00:24:54,023
And indeed, here we get our running object.

441
00:24:55,210 --> 00:24:57,020
So it has the coordinates

442
00:24:57,020 --> 00:24:59,800
and so this worked and of course,

443
00:24:59,800 --> 00:25:02,832
it has has all the other data as well.

444
00:25:02,832 --> 00:25:06,010
This ID is now corrected, as you see.

445
00:25:06,010 --> 00:25:08,590
And also the pace is calculated here,

446
00:25:08,590 --> 00:25:13,350
based on this input data, right?

447
00:25:13,350 --> 00:25:16,380
And so Indeed, the most complicated part

448
00:25:16,380 --> 00:25:20,290
of adding a new workout is already completed.

449
00:25:20,290 --> 00:25:21,980
So that's beautiful.

450
00:25:21,980 --> 00:25:24,093
Let's just try the same with cycling.

451
00:25:25,200 --> 00:25:27,263
Let's say 10 kilometers,

452
00:25:28,400 --> 00:25:31,023
in 10 minutes with 30 meters.

453
00:25:32,570 --> 00:25:35,020
Now, and I didn't even click anywhere on the map.

454
00:25:36,620 --> 00:25:39,173
Okay, and so that clearly means

455
00:25:39,173 --> 00:25:43,570
that we are still missing a step, which is to hide the form.

456
00:25:43,570 --> 00:25:47,640
But anyway, it simply took the coordinates from earlier

457
00:25:47,640 --> 00:25:51,393
and then it added all the correct data here as well.

458
00:25:52,970 --> 00:25:55,180
So indeed, it is now a cycling object,

459
00:25:55,180 --> 00:25:58,220
while before it was a running object.

460
00:25:58,220 --> 00:25:59,650
Let's just do that again here,

461
00:25:59,650 --> 00:26:01,133
but this time with clicking,

462
00:26:02,030 --> 00:26:03,680
so that I can show you something.

463
00:26:05,730 --> 00:26:08,510
All right so it still says workout

464
00:26:08,510 --> 00:26:10,700
and we're gonna fix that in the next video.

465
00:26:10,700 --> 00:26:13,170
But for now, what I want is the cycling,

466
00:26:13,170 --> 00:26:15,563
actually to have this orange border.

467
00:26:16,440 --> 00:26:19,183
So just like this one.

468
00:26:20,450 --> 00:26:24,343
All right, so orange is for cycling and green for running.

469
00:26:25,430 --> 00:26:27,923
And so let's quickly do that.

470
00:26:29,370 --> 00:26:33,000
So in our CSS, I think I showed you earlier

471
00:26:33,000 --> 00:26:36,410
that we have running pop up and cycling pop up.

472
00:26:36,410 --> 00:26:40,923
And these two values here are essentially simply the value

473
00:26:40,923 --> 00:26:42,803
of the input type.

474
00:26:43,660 --> 00:26:46,040
So this one here.

475
00:26:46,040 --> 00:26:50,800
And so here, we can simply do a template literal

476
00:26:53,080 --> 00:26:56,163
and then plug in the type here.

477
00:26:57,850 --> 00:27:00,430
And now actually, let's also export this here

478
00:27:00,430 --> 00:27:05,170
to its own method to make this add workout method here,

479
00:27:05,170 --> 00:27:07,810
a little bit cleaner, all right.

480
00:27:07,810 --> 00:27:11,163
So let's add down here, renderWorkoutMarker.

481
00:27:18,120 --> 00:27:20,463
Let's grab this code here.

482
00:27:24,477 --> 00:27:26,283
And so now all we need to do

483
00:27:26,283 --> 00:27:31,283
is to call this.renderWorkoutMarker.

484
00:27:31,990 --> 00:27:34,780
And here, we need to pass in the workout object

485
00:27:35,700 --> 00:27:39,110
because otherwise, it's not gonna work.

486
00:27:39,110 --> 00:27:42,350
I mean, right now, we don't even need to workout yet

487
00:27:42,350 --> 00:27:43,593
but later, we will.

488
00:27:45,000 --> 00:27:48,490
So we want to display some kind of data about the workout

489
00:27:48,490 --> 00:27:50,483
And so let's pass it in.

490
00:27:51,660 --> 00:27:53,080
So work out there.

491
00:27:53,080 --> 00:27:56,293
And here, let's actually call it work out as well.

492
00:27:58,250 --> 00:28:00,970
And so here, instead of displaying this,

493
00:28:00,970 --> 00:28:05,223
let's simply display workout.distance.

494
00:28:06,299 --> 00:28:08,230
Okay, just for now,

495
00:28:08,230 --> 00:28:10,440
just so we are actually using the workout

496
00:28:10,440 --> 00:28:12,063
here in this method, okay?

497
00:28:13,960 --> 00:28:15,330
You see that we are also using

498
00:28:15,330 --> 00:28:17,780
the this keyword in this method

499
00:28:17,780 --> 00:28:20,580
but actually, that's no problem in this case

500
00:28:20,580 --> 00:28:23,210
because here, we are actually calling this one here

501
00:28:23,210 --> 00:28:25,963
as a method of the this keyword.

502
00:28:27,020 --> 00:28:30,720
And besides that, we are also calling it ourselves.

503
00:28:30,720 --> 00:28:32,480
So it's not a callback function

504
00:28:32,480 --> 00:28:34,950
of any other function in JavaScript.

505
00:28:34,950 --> 00:28:38,260
And so therefore, the this keyword in this method here

506
00:28:38,260 --> 00:28:40,980
will still be the current object.

507
00:28:40,980 --> 00:28:43,963
And so no need to using bind in this case.

508
00:28:44,810 --> 00:28:47,790
And so finally, the last step is to actually render

509
00:28:47,790 --> 00:28:49,820
the workout on the list.

510
00:28:49,820 --> 00:28:52,860
And this one, I'm gonna leave for the next lecture,

511
00:28:52,860 --> 00:28:55,740
because this one is gonna take a little bit of time

512
00:28:55,740 --> 00:28:59,060
in order to format all the HTML correctly.

513
00:28:59,060 --> 00:29:00,850
So let's give this one a save.

514
00:29:00,850 --> 00:29:04,853
And so besides that, this one is basically complete.

515
00:29:05,730 --> 00:29:09,470
And so let's quickly check it out one more time,

516
00:29:09,470 --> 00:29:12,403
just to see the cycling pop up.

517
00:29:13,560 --> 00:29:15,063
So let's see right there,

518
00:29:15,063 --> 00:29:20,063
cycling 10, 10, 10 values don't matter.

519
00:29:21,160 --> 00:29:24,710
Oh, and here, we do actually have an error,

520
00:29:24,710 --> 00:29:28,120
which says that latitude is not defined.

521
00:29:28,120 --> 00:29:31,873
And so indeed, here it is not defined.

522
00:29:32,740 --> 00:29:35,330
So instead, this coordinate should of course,

523
00:29:35,330 --> 00:29:37,740
come from the workout itself.

524
00:29:37,740 --> 00:29:41,680
And so that itself is already a reason enough

525
00:29:41,680 --> 00:29:46,013
to pass in the workout argument here into this function.

526
00:29:47,580 --> 00:29:50,400
So now it becomes very important for the first time

527
00:29:50,400 --> 00:29:53,810
to have some data in the actual workout object.

528
00:29:53,810 --> 00:29:55,720
Because here we do need that

529
00:29:55,720 --> 00:29:57,750
in order to tell JavaScript

530
00:29:57,750 --> 00:30:00,149
or actually in order to tell leaflet

531
00:30:00,149 --> 00:30:04,520
where to display this marker, okay?

532
00:30:04,520 --> 00:30:08,300
So it's the data that's coming directly from the workout.

533
00:30:08,300 --> 00:30:11,440
And so now this should work.

534
00:30:11,440 --> 00:30:13,163
Or maybe it shouldn't.

535
00:30:14,700 --> 00:30:16,599
So I'm looking at this variable here.

536
00:30:16,599 --> 00:30:18,750
And right now the type is, of course,

537
00:30:18,750 --> 00:30:22,690
also no longer defined, right?

538
00:30:22,690 --> 00:30:25,280
So we get to type here from this one.

539
00:30:25,280 --> 00:30:27,170
But of course, this type variable

540
00:30:27,170 --> 00:30:29,853
is not gonna be available right here.

541
00:30:30,790 --> 00:30:33,210
So how do we fix that?

542
00:30:33,210 --> 00:30:36,090
Well, ideally, we should get the information,

543
00:30:36,090 --> 00:30:39,020
whether the current workout is of running,

544
00:30:39,020 --> 00:30:42,383
or of cycling, right from the workout object.

545
00:30:43,520 --> 00:30:46,050
And actually, that's a pretty good idea.

546
00:30:46,050 --> 00:30:48,810
And so let's add that value

547
00:30:48,810 --> 00:30:51,660
to the cycling and to the running.

548
00:30:51,660 --> 00:30:56,300
However, it doesn't make much sense to always pass that in.

549
00:30:56,300 --> 00:30:57,982
So we already know that running

550
00:30:57,982 --> 00:31:00,020
is always gonna be running

551
00:31:00,020 --> 00:31:03,400
and cycling is always gonna be cycling.

552
00:31:03,400 --> 00:31:08,313
And so we can simply add, basically, that type right here.

553
00:31:09,670 --> 00:31:10,793
And so let's do that.

554
00:31:12,020 --> 00:31:14,453
So again, we are defining a field here.

555
00:31:16,170 --> 00:31:20,030
So cycling, and so this value type

556
00:31:20,030 --> 00:31:22,760
will now be a property that's gonna be available

557
00:31:22,760 --> 00:31:24,283
on all the instances.

558
00:31:25,720 --> 00:31:28,640
Okay, so again, this would be the same thing

559
00:31:28,640 --> 00:31:33,640
as doing this.type equals cycling like this, okay?

560
00:31:37,344 --> 00:31:41,183
And now the same for running like this, all right?

561
00:31:46,613 --> 00:31:49,030
And then, so now we can use that here

562
00:31:49,030 --> 00:31:52,483
and we will actually also need that in some other places.

563
00:31:53,780 --> 00:31:56,563
And so this is indeed a good thing to have.

564
00:31:57,990 --> 00:32:01,250
So workout.type, and so now

565
00:32:01,250 --> 00:32:03,833
this will whether it be running or cycling.

566
00:32:05,290 --> 00:32:07,663
So let's test that now with cycling.

567
00:32:09,830 --> 00:32:11,830
So cycling, and then

568
00:32:14,030 --> 00:32:15,893
and we get another error.

569
00:32:17,030 --> 00:32:22,030
Okay, so it failed to execute appendChild on node,

570
00:32:23,640 --> 00:32:24,860
for some reason.

571
00:32:24,860 --> 00:32:26,730
But let's go back to that in a second.

572
00:32:26,730 --> 00:32:31,170
For now, I just want to see if actually, the type is there

573
00:32:31,170 --> 00:32:33,400
and indeed it is.

574
00:32:33,400 --> 00:32:36,250
So that's great already.

575
00:32:36,250 --> 00:32:38,032
Now let's just go back and see

576
00:32:38,032 --> 00:32:40,483
why this error here is happening.

577
00:32:42,920 --> 00:32:47,563
Well, there is no appendChild method anywhere here.

578
00:32:48,920 --> 00:32:52,053
Let's just set this here to something else.

579
00:32:53,660 --> 00:32:56,363
But that's probably not the problem anyway.

580
00:32:58,030 --> 00:32:59,970
So probably I shouldn't have changed anything

581
00:32:59,970 --> 00:33:03,040
because now the error message here will be gone

582
00:33:03,040 --> 00:33:04,693
and then I cannot read these,

583
00:33:08,688 --> 00:33:10,020
the stack trace there,

584
00:33:10,020 --> 00:33:14,473
which is what we call to that list of errors.

585
00:33:15,370 --> 00:33:19,500
Oh, but now it actually worked, all right.

586
00:33:19,500 --> 00:33:21,203
So the problem there was

587
00:33:21,203 --> 00:33:24,793
that we were actually probably passing in some value

588
00:33:24,793 --> 00:33:26,580
that was not a string

589
00:33:26,580 --> 00:33:28,940
and so therefore, for some reason,

590
00:33:28,940 --> 00:33:32,180
leaflet created some problem there.

591
00:33:32,180 --> 00:33:34,850
But anyway, we will take care of this string here

592
00:33:34,850 --> 00:33:35,943
in the next video.

593
00:33:36,870 --> 00:33:41,133
For now, I just want to create just a running one here.

594
00:33:42,300 --> 00:33:46,110
And so this time, it turns out to be green.

595
00:33:46,110 --> 00:33:49,053
And so indeed, here the type is now running.

596
00:33:50,810 --> 00:33:54,787
All right, so this was a very long video.

597
00:33:54,787 --> 00:33:57,240
And so let's finish it here.

598
00:33:57,240 --> 00:33:59,800
And as I already said in the next one,

599
00:33:59,800 --> 00:34:02,320
we will then finally render the workout

600
00:34:02,320 --> 00:34:04,223
also here on this sidebar.

