WEBVTT

1
00:00:01.380 --> 00:00:03.510
<v Jonas>So using the workout classes</v>

2
00:00:03.510 --> 00:00:05.280
that we just implemented,

3
00:00:05.280 --> 00:00:07.680
let's now finally implement the feature

4
00:00:07.680 --> 00:00:11.403
of creating a new workout from our user interface.

5
00:00:12.990 --> 00:00:16.563
And to start, let's take a look at our flowchart here.

6
00:00:17.670 --> 00:00:20.010
And so basically, this here is the action

7
00:00:20.010 --> 00:00:21.840
that we're interested in now.

8
00:00:21.840 --> 00:00:24.780
So when the user submits a new workout,

9
00:00:24.780 --> 00:00:29.400
and so we already added this new workout method here

10
00:00:29.400 --> 00:00:32.850
as an event handler function for that event.

11
00:00:32.850 --> 00:00:35.580
And so what we want to happen now is

12
00:00:35.580 --> 00:00:38.760
to basically render the workout on the map,

13
00:00:38.760 --> 00:00:41.670
render the workout on the list,

14
00:00:41.670 --> 00:00:44.793
and then this part here, we're gonna leave for later.

15
00:00:45.840 --> 00:00:48.240
So this one is the high level overview

16
00:00:48.240 --> 00:00:50.190
of what needs to happen,

17
00:00:50.190 --> 00:00:53.130
but actually, there's a lot more things involved,

18
00:00:53.130 --> 00:00:55.080
than just these immediate actions

19
00:00:55.080 --> 00:00:57.720
that we see on the user interface.

20
00:00:57.720 --> 00:01:00.180
So actually, we're gonna leave the rendering here

21
00:01:00.180 --> 00:01:03.300
for the next video because as I just said,

22
00:01:03.300 --> 00:01:05.490
there's actually a lot of other stuff

23
00:01:05.490 --> 00:01:08.463
that we have to do, all right?

24
00:01:09.660 --> 00:01:13.830
So as you see, we are back here at looking at the flowchart

25
00:01:13.830 --> 00:01:16.380
because now we are back to being interested

26
00:01:16.380 --> 00:01:18.660
what we actually need to implement,

27
00:01:18.660 --> 00:01:22.410
and not how to implement it, right?

28
00:01:22.410 --> 00:01:24.480
So the architecture here, again,

29
00:01:24.480 --> 00:01:26.403
is about how we implement it.

30
00:01:27.358 --> 00:01:29.550
And so it contains all of these different methods

31
00:01:29.550 --> 00:01:31.710
and these low-level details,

32
00:01:31.710 --> 00:01:34.140
while the flow chart here is really more

33
00:01:34.140 --> 00:01:38.430
of a high-level overview of what we want to implement.

34
00:01:38.430 --> 00:01:41.730
And so for now, we don't need the architecture anymore

35
00:01:41.730 --> 00:01:44.790
because we already put everything into the code

36
00:01:44.790 --> 00:01:46.530
that we had here.

37
00:01:46.530 --> 00:01:48.120
Now, if you're really curious

38
00:01:48.120 --> 00:01:52.410
and want to spoil the experience basically until the end

39
00:01:52.410 --> 00:01:55.440
of the section, then you can already take a look

40
00:01:55.440 --> 00:01:57.930
at the final architecture here.

41
00:01:57.930 --> 00:01:59.910
But I'm not gonna do that.

42
00:01:59.910 --> 00:02:02.430
So I just want to now keep building the rest

43
00:02:02.430 --> 00:02:06.510
of the application as we go, okay?

44
00:02:06.510 --> 00:02:10.170
But anyway, since this is so high level here,

45
00:02:10.170 --> 00:02:13.470
let's actually go to the working demo application

46
00:02:13.470 --> 00:02:15.393
and see what exactly happens.

47
00:02:16.290 --> 00:02:17.763
So let's reload here.

48
00:02:18.780 --> 00:02:21.480
And so let's click just somewhere,

49
00:02:21.480 --> 00:02:23.460
and then you'll see, as we already know,

50
00:02:23.460 --> 00:02:27.900
the form opens, then we can input some data here.

51
00:02:27.900 --> 00:02:31.440
And then our application needs to get this data,

52
00:02:31.440 --> 00:02:34.710
it needs to check if the data actually makes sense,

53
00:02:34.710 --> 00:02:38.160
and then we need to create a new object for this workout

54
00:02:38.160 --> 00:02:40.860
and render it right here,

55
00:02:40.860 --> 00:02:43.740
and also on the map, of course.

56
00:02:43.740 --> 00:02:46.080
And then finally, after all that,

57
00:02:46.080 --> 00:02:47.730
the form is also hidden.

58
00:02:47.730 --> 00:02:49.980
So everything I just said is gonna happen

59
00:02:49.980 --> 00:02:52.560
whenever we hit Enter here.

60
00:02:52.560 --> 00:02:55.110
So you see, of course, the marker was created,

61
00:02:55.110 --> 00:02:58.920
it was rendered here, all the input data had to be checked,

62
00:02:58.920 --> 00:03:01.803
and a new running object was created.

63
00:03:02.700 --> 00:03:05.220
So for example, if we add another one,

64
00:03:05.220 --> 00:03:10.220
but without any data, then we are gonna get this alert.

65
00:03:10.320 --> 00:03:12.630
Or the same, if we input any data,

66
00:03:12.630 --> 00:03:14.700
that doesn't make much sense.

67
00:03:14.700 --> 00:03:17.880
For example, a negative number for the cadence,

68
00:03:17.880 --> 00:03:19.620
which is, of course, impossible.

69
00:03:19.620 --> 00:03:22.710
And so again, we get this error here.

70
00:03:22.710 --> 00:03:25.590
So input validation is an important part

71
00:03:25.590 --> 00:03:30.207
of creating any application that works with user inputs.

72
00:03:30.207 --> 00:03:34.140
And so let's now actually work on the function

73
00:03:34.140 --> 00:03:37.620
that is responsible for doing all of this.

74
00:03:37.620 --> 00:03:41.310
And for starters, I will basically document everything

75
00:03:41.310 --> 00:03:43.563
that we need to do here using comments.

76
00:03:44.550 --> 00:03:49.550
So first, we need to get data from the form.

77
00:03:50.160 --> 00:03:54.713
Then we need to check if data is valid,

78
00:03:57.390 --> 00:03:59.163
then if it's running.

79
00:04:00.300 --> 00:04:04.353
So if the activity running, then create running object.

80
00:04:08.580 --> 00:04:11.070
And if the activity is cycling,

81
00:04:11.070 --> 00:04:14.463
then, of course, create a cycling object.

82
00:04:17.280 --> 00:04:22.280
Then add the new object to the workout array.

83
00:04:24.360 --> 00:04:27.480
And so yeah, instead of activity,

84
00:04:27.480 --> 00:04:29.553
let's actually call it workout here.

85
00:04:32.730 --> 00:04:37.730
Then we want to render workout on map as a marker.

86
00:04:38.370 --> 00:04:43.370
And finally, we want to render the new workout on the list.

87
00:04:44.880 --> 00:04:48.550
And finally, also, we want to then hide the form

88
00:04:49.620 --> 00:04:51.993
and clear the input fields.

89
00:04:54.720 --> 00:04:57.930
So you see, there's gonna be a lot of work.

90
00:04:57.930 --> 00:05:02.430
Let's put this one for now, at least here,

91
00:05:02.430 --> 00:05:05.013
even though it's not gonna really work like this,

92
00:05:07.560 --> 00:05:09.750
but okay, so with this,

93
00:05:09.750 --> 00:05:12.600
we now have all the steps lined out.

94
00:05:12.600 --> 00:05:14.403
And so let's get started.

95
00:05:15.780 --> 00:05:18.960
And we're gonna start by getting the data from the form

96
00:05:18.960 --> 00:05:20.910
and starting with the type,

97
00:05:20.910 --> 00:05:24.753
and type is already stored at the variable input type.

98
00:05:25.770 --> 00:05:27.690
So that's all the way up here.

99
00:05:27.690 --> 00:05:29.853
Let's bring that down actually.

100
00:05:31.650 --> 00:05:36.420
And we could even add these elements here basically

101
00:05:36.420 --> 00:05:39.540
as fields also inside of the application.

102
00:05:39.540 --> 00:05:42.180
But in this case, I prefer not to do that

103
00:05:42.180 --> 00:05:44.010
because then every time that we wanted

104
00:05:44.010 --> 00:05:47.520
to reference one of these elements,

105
00:05:47.520 --> 00:05:51.330
then we would always have to use like this .inputDistance

106
00:05:51.330 --> 00:05:54.570
or duration, and so on and so forth.

107
00:05:54.570 --> 00:05:56.703
And I just don't really like that.

108
00:05:57.630 --> 00:06:00.480
But anyway, let's not take the values of input type,

109
00:06:00.480 --> 00:06:03.663
distance, duration, cadence, and elevation.

110
00:06:06.030 --> 00:06:09.150
And these two here are not that straightforward,

111
00:06:09.150 --> 00:06:11.523
but let's see that in a minute.

112
00:06:13.980 --> 00:06:18.213
So inputType.value,

113
00:06:19.140 --> 00:06:22.470
and so input type is actually a select element,

114
00:06:22.470 --> 00:06:26.790
but still we get the value using the value property.

115
00:06:26.790 --> 00:06:28.263
Let me just show that to you.

116
00:06:29.370 --> 00:06:32.160
And so yeah, here it is.

117
00:06:32.160 --> 00:06:34.560
And so each option has this value.

118
00:06:34.560 --> 00:06:38.580
And so for running, the value is running with the r,

119
00:06:38.580 --> 00:06:42.000
and for cycling, the same, okay?

120
00:06:42.000 --> 00:06:44.640
And so again, the value will be whatever

121
00:06:44.640 --> 00:06:48.570
of these two is selected, and then we get this value here.

122
00:06:48.570 --> 00:06:50.793
And so that will be important in a minute.

123
00:06:53.280 --> 00:06:56.133
But anyway, let's not take the distance,

124
00:06:58.440 --> 00:07:02.070
so that's inputDistance.value.

125
00:07:02.070 --> 00:07:05.310
And remember that this always comes as strings,

126
00:07:05.310 --> 00:07:08.643
and so let's convert that immediately to a number.

127
00:07:10.620 --> 00:07:13.050
And then the duration,

128
00:07:13.050 --> 00:07:18.050
let's do the same here, inputDuration.value.

129
00:07:19.710 --> 00:07:22.350
Now, about the cadence and the elevation gain,

130
00:07:22.350 --> 00:07:24.360
we actually don't want to get them here right

131
00:07:24.360 --> 00:07:26.310
in the beginning, but the cadence,

132
00:07:26.310 --> 00:07:29.430
we only want to get if it is a running workout,

133
00:07:29.430 --> 00:07:31.920
and the elevation gain, we only want to get

134
00:07:31.920 --> 00:07:33.990
if it is a cycling workout.

135
00:07:33.990 --> 00:07:36.060
Because that will then make it easier for us

136
00:07:36.060 --> 00:07:40.770
to validate the data, but more about that in a second.

137
00:07:40.770 --> 00:07:43.440
So for now, let's actually check what kind of workout

138
00:07:43.440 --> 00:07:44.523
we are dealing with.

139
00:07:45.570 --> 00:07:48.123
And so all we have to do is to check the type.

140
00:07:49.293 --> 00:07:54.293
And if it's running, then we want to get the cadence.

141
00:07:54.810 --> 00:07:57.330
So let's call that cadence as well,

142
00:07:57.330 --> 00:08:02.330
and convert inputCadence.value to a number.

143
00:08:02.850 --> 00:08:05.583
But if we are dealing with cycling,

144
00:08:06.570 --> 00:08:08.170
then we want the elevation gain.

145
00:08:12.270 --> 00:08:15.990
So let's call this one elevation,

146
00:08:15.990 --> 00:08:18.803
and here, it's also called inputElevation.

147
00:08:21.761 --> 00:08:25.410
Now, okay, and so now let's check if the data is valid.

148
00:08:25.410 --> 00:08:28.650
And so we will now do that inside of each

149
00:08:28.650 --> 00:08:30.123
of these if statements.

150
00:08:31.020 --> 00:08:32.310
Now, you might have noticed

151
00:08:32.310 --> 00:08:35.460
that I actually created two separate if statements here,

152
00:08:35.460 --> 00:08:37.830
instead of an if else statement.

153
00:08:37.830 --> 00:08:41.160
And that's just something that you will see more and more

154
00:08:41.160 --> 00:08:42.810
in modern JavaScript.

155
00:08:42.810 --> 00:08:46.680
So the if else is not really that much used anymore,

156
00:08:46.680 --> 00:08:50.610
and I think that actually, it looks a lot cleaner like this.

157
00:08:50.610 --> 00:08:53.043
So to simply have two if statements.

158
00:08:54.510 --> 00:08:58.380
So anyway, let's not check if the data is valid,

159
00:08:58.380 --> 00:09:01.890
and what does it mean for the data to be valid?

160
00:09:01.890 --> 00:09:03.300
Well, first of all,

161
00:09:03.300 --> 00:09:06.693
each of them should be a number, right?

162
00:09:07.590 --> 00:09:09.633
And so let's do that.

163
00:09:11.670 --> 00:09:15.450
And here again, we will actually use a guard clause.

164
00:09:15.450 --> 00:09:18.150
So again, what a guard clause means is

165
00:09:18.150 --> 00:09:19.470
that we will basically check

166
00:09:19.470 --> 00:09:23.400
for the opposite of what we are originally interested in.

167
00:09:23.400 --> 00:09:25.200
And if that opposite is true,

168
00:09:25.200 --> 00:09:28.050
then we simply return the function immediately.

169
00:09:28.050 --> 00:09:30.600
And so once again, this is a trait

170
00:09:30.600 --> 00:09:32.790
of more modern JavaScript.

171
00:09:32.790 --> 00:09:37.230
So kind of a trend that you will see in modern JavaScript.

172
00:09:37.230 --> 00:09:40.170
But anyway, let me show you what I mean here.

173
00:09:40.170 --> 00:09:42.723
So if the distance is not a number,

174
00:09:44.130 --> 00:09:46.803
and remember that for that, we use Number.isFinite.

175
00:09:51.960 --> 00:09:55.560
So if the distance here is not a number,

176
00:09:55.560 --> 00:09:57.903
then we want to return immediately.

177
00:09:58.890 --> 00:10:00.240
So we want to return,

178
00:10:00.240 --> 00:10:04.560
and then we can also do some other code here.

179
00:10:04.560 --> 00:10:05.943
So let's create an alert.

180
00:10:07.530 --> 00:10:12.453
Inputs have to be positive numbers.

181
00:10:13.350 --> 00:10:15.270
So for now, we check for numbers,

182
00:10:15.270 --> 00:10:17.970
but we didn't yet check for positive,

183
00:10:17.970 --> 00:10:20.700
but let's leave that for a second.

184
00:10:20.700 --> 00:10:23.850
So we should already be able to test out

185
00:10:23.850 --> 00:10:25.623
if this if here is gonna work.

186
00:10:27.600 --> 00:10:29.853
So let's just see if our map appears here,

187
00:10:32.850 --> 00:10:34.860
let's try to reload here.

188
00:10:34.860 --> 00:10:35.850
And for some reason,

189
00:10:35.850 --> 00:10:38.730
sometimes this takes a really long time.

190
00:10:38.730 --> 00:10:41.940
So sometimes while I was developing this application,

191
00:10:41.940 --> 00:10:44.580
I waited up to like two or three minutes,

192
00:10:44.580 --> 00:10:46.890
and I don't know why that happens.

193
00:10:46.890 --> 00:10:50.190
But yeah, I hope that never happens for you.

194
00:10:50.190 --> 00:10:52.200
But in case you see long waiting times,

195
00:10:52.200 --> 00:10:54.423
that might be normal, all right?

196
00:10:55.980 --> 00:10:57.723
But now here it is,

197
00:10:59.390 --> 00:11:02.790
and so let's input some invalid distance,

198
00:11:02.790 --> 00:11:04.980
so like just any letter.

199
00:11:04.980 --> 00:11:07.893
And then we get inputs have to be positive numbers.

200
00:11:09.060 --> 00:11:11.700
So that is already working.

201
00:11:11.700 --> 00:11:14.943
And now we just need to do the same with the other inputs.

202
00:11:15.780 --> 00:11:18.963
So we want the same for the distance.

203
00:11:20.010 --> 00:11:21.633
So Number.isFinite,

204
00:11:24.930 --> 00:11:26.463
so actually for duration,

205
00:11:27.300 --> 00:11:32.300
and then the same thing for Number.isFinite, cadence, okay?

206
00:11:38.100 --> 00:11:39.930
Now, this is actually not correct

207
00:11:39.930 --> 00:11:42.180
because we don't want the and,

208
00:11:42.180 --> 00:11:44.610
but instead, we want or.

209
00:11:44.610 --> 00:11:46.320
So this one here should happen,

210
00:11:46.320 --> 00:11:50.130
whenever one of these three here is not a number

211
00:11:50.130 --> 00:11:54.600
and not when all of them are invalid numbers, right?

212
00:11:54.600 --> 00:11:56.973
And so that's exactly what or means.

213
00:11:58.560 --> 00:12:03.360
So if this one is an invalid number or this one or this one,

214
00:12:03.360 --> 00:12:06.570
then we can get this alert.

215
00:12:06.570 --> 00:12:10.560
And so the reason why we did this checking here inside

216
00:12:10.560 --> 00:12:15.560
of this if block is because if we did the same out here,

217
00:12:16.320 --> 00:12:20.310
then we would also want to check for the elevation, right?

218
00:12:20.310 --> 00:12:21.600
But as we know already,

219
00:12:21.600 --> 00:12:25.410
only one of the cadence and elevation can be defined

220
00:12:25.410 --> 00:12:26.700
at the same time.

221
00:12:26.700 --> 00:12:30.330
They cannot both be defined at the same time.

222
00:12:30.330 --> 00:12:31.830
And so performing this check,

223
00:12:31.830 --> 00:12:34.830
would then be a little bit more difficult.

224
00:12:34.830 --> 00:12:39.420
So now we can go ahead and do the same thing down here.

225
00:12:39.420 --> 00:12:41.280
So in the cycling part,

226
00:12:41.280 --> 00:12:44.700
but let's actually refactor this code here already,

227
00:12:44.700 --> 00:12:47.130
and basically create a small function

228
00:12:47.130 --> 00:12:49.620
which takes a number of arguments,

229
00:12:49.620 --> 00:12:50.760
and we'll then validate

230
00:12:50.760 --> 00:12:53.993
if all of them are numbers or not, okay?

231
00:12:56.370 --> 00:12:59.550
So basically, we want it to work like this,

232
00:12:59.550 --> 00:13:00.750
but we want to write this

233
00:13:00.750 --> 00:13:03.900
in a more clear and more beautiful,

234
00:13:03.900 --> 00:13:07.623
so to say, way, all right?

235
00:13:08.460 --> 00:13:11.463
So let's create a very simple helper function here,

236
00:13:12.720 --> 00:13:14.743
and let me call it validInputs.

237
00:13:18.300 --> 00:13:20.460
So a very simple arrow function,

238
00:13:20.460 --> 00:13:23.853
and this can take an arbitrary number of inputs.

239
00:13:27.420 --> 00:13:31.200
And remember that when we use rest parameters like this,

240
00:13:31.200 --> 00:13:32.493
then we get an array.

241
00:13:34.140 --> 00:13:36.120
So inputs is an array,

242
00:13:36.120 --> 00:13:38.520
and we now want to loop over this array,

243
00:13:38.520 --> 00:13:42.480
and basically check if all of them are positive.

244
00:13:42.480 --> 00:13:45.360
Now, there's actually already a predefined method

245
00:13:45.360 --> 00:13:48.750
in JavaScript that is very helpful for that.

246
00:13:48.750 --> 00:13:53.253
So remember that we have a nice little method called every,

247
00:13:54.480 --> 00:13:56.583
and so let's use it here,

248
00:13:57.586 --> 00:14:00.240
and then I will quickly explain what it does.

249
00:14:00.240 --> 00:14:03.783
So the current input and then Number.isFinite,

250
00:14:06.210 --> 00:14:07.923
the current input.

251
00:14:09.120 --> 00:14:12.150
So basically, this will loop over the array,

252
00:14:12.150 --> 00:14:14.400
and in each of them, it'll check

253
00:14:14.400 --> 00:14:17.700
whether the number is finite or not.

254
00:14:17.700 --> 00:14:21.720
And then in the end, the every method will only return true

255
00:14:21.720 --> 00:14:25.590
if this value here was true for all of them,

256
00:14:25.590 --> 00:14:27.990
so for all elements in the array.

257
00:14:27.990 --> 00:14:32.190
But if only one of these values here was not finite,

258
00:14:32.190 --> 00:14:34.500
so if the result here was false

259
00:14:34.500 --> 00:14:37.170
for one of the elements of the array,

260
00:14:37.170 --> 00:14:39.690
then every will return false.

261
00:14:39.690 --> 00:14:42.120
And so that will then be the return value

262
00:14:42.120 --> 00:14:44.823
of this arrow function, right?

263
00:14:45.794 --> 00:14:48.044
And so then here, we can replace all of this.

264
00:14:49.290 --> 00:14:53.280
And let's actually just commented out,

265
00:14:53.280 --> 00:14:57.000
we can now say if not valid inputs

266
00:14:57.000 --> 00:15:00.570
and then pass in the three that we're interested in,

267
00:15:00.570 --> 00:15:05.570
so distance, duration, and cadence.

268
00:15:06.870 --> 00:15:11.820
And again, here we are inverting the condition, right?

269
00:15:11.820 --> 00:15:14.010
So if all of these are numbers,

270
00:15:14.010 --> 00:15:17.040
then this year will become true, right?

271
00:15:17.040 --> 00:15:19.140
But whenever this is not true,

272
00:15:19.140 --> 00:15:21.270
then that's the case where we want to return

273
00:15:21.270 --> 00:15:24.273
from the function, and show this alert we know.

274
00:15:26.913 --> 00:15:30.467
All right, so let's copy this,

275
00:15:32.216 --> 00:15:36.140
and do the same here for the elevation like this.

276
00:15:37.350 --> 00:15:39.400
And here, I will get rid of the comments.

277
00:15:40.350 --> 00:15:42.810
And so this is the first check,

278
00:15:42.810 --> 00:15:45.000
but in fact, we also want to test

279
00:15:45.000 --> 00:15:47.220
if the numbers are positive,

280
00:15:47.220 --> 00:15:50.700
because otherwise, they don't make much sense.

281
00:15:50.700 --> 00:15:52.203
So let's reload here again.

282
00:15:53.970 --> 00:15:57.270
So right now, if I put a letter in any of these,

283
00:15:57.270 --> 00:16:00.900
then it's not gonna work, right?

284
00:16:00.900 --> 00:16:05.340
But if I put in a negative number of steps,

285
00:16:05.340 --> 00:16:07.830
then this is perfectly acceptable,

286
00:16:07.830 --> 00:16:12.030
and we already get the marker here printed to the map.

287
00:16:12.030 --> 00:16:15.630
But in fact, we don't want this to be acceptable.

288
00:16:15.630 --> 00:16:18.060
So negative values should not be allowed

289
00:16:18.060 --> 00:16:20.160
for any of the three,

290
00:16:20.160 --> 00:16:22.110
but in the cycling, it should be allowed

291
00:16:22.110 --> 00:16:23.790
for the elevation gain.

292
00:16:23.790 --> 00:16:26.670
So here, we can of course have a negative number

293
00:16:26.670 --> 00:16:30.813
which happens when we go basically down a mountain, right?

294
00:16:31.980 --> 00:16:35.490
So that's simple as well.

295
00:16:35.490 --> 00:16:37.200
All we have to do is to check

296
00:16:37.200 --> 00:16:40.680
if these three values here are greater than zero,

297
00:16:40.680 --> 00:16:42.990
and the same for these two,

298
00:16:42.990 --> 00:16:45.960
but not for the elevation, okay?

299
00:16:45.960 --> 00:16:48.840
And so actually, to make this really cool,

300
00:16:48.840 --> 00:16:52.623
I will create another small helper function like this one,

301
00:16:53.580 --> 00:16:56.070
and it might be a good habit for you as well

302
00:16:56.070 --> 00:16:59.400
to get used to these small helper functions.

303
00:16:59.400 --> 00:17:02.310
So they're especially nice in these situations

304
00:17:02.310 --> 00:17:04.293
for testing complex conditions.

305
00:17:05.130 --> 00:17:07.470
So instead of writing all of this

306
00:17:07.470 --> 00:17:10.650
and plus checking now for positive numbers,

307
00:17:10.650 --> 00:17:14.190
we can simply export that into one or two functions

308
00:17:14.190 --> 00:17:16.053
which then do the job for us.

309
00:17:17.370 --> 00:17:21.150
So here, I'm gonna create a function called allPositive,

310
00:17:21.150 --> 00:17:23.430
and this one is gonna be almost the same

311
00:17:23.430 --> 00:17:24.603
as the previous one.

312
00:17:25.500 --> 00:17:28.653
So it takes in an arbitrary amount of inputs,

313
00:17:32.250 --> 00:17:34.620
and then we will only return through

314
00:17:34.620 --> 00:17:38.310
if all of them are greater than zero.

315
00:17:38.310 --> 00:17:41.070
And so here, the every method is very useful,

316
00:17:41.070 --> 00:17:43.323
again, so input.

317
00:17:44.160 --> 00:17:45.720
And then here we need some condition

318
00:17:45.720 --> 00:17:48.180
that returns true or false.

319
00:17:48.180 --> 00:17:51.723
And so that's input greater than zero.

320
00:17:53.070 --> 00:17:55.650
And so let's now use that here.

321
00:17:55.650 --> 00:18:00.650
And so we want basically, if all of the inputs are not valid

322
00:18:01.830 --> 00:18:06.830
or if there is basically any number that is not positive,

323
00:18:06.840 --> 00:18:11.840
so if not allPositive, distance, duration,

324
00:18:14.460 --> 00:18:18.780
and cadence, all right?

325
00:18:18.780 --> 00:18:21.783
So in this case, we then want to get this alert.

326
00:18:22.650 --> 00:18:27.650
And now here, let's do the same for the cycling,

327
00:18:30.150 --> 00:18:33.630
but here, we are only interested in distance and duration,

328
00:18:33.630 --> 00:18:37.563
because again, the elevation might very well be negative.

329
00:18:39.000 --> 00:18:41.730
So this is a little bit complex validation,

330
00:18:41.730 --> 00:18:43.590
but that's no problem at all.

331
00:18:43.590 --> 00:18:45.420
That's why I spent some time here

332
00:18:45.420 --> 00:18:48.570
on this validation without any problem.

333
00:18:48.570 --> 00:18:50.730
Now, it would've been a little bit easier

334
00:18:50.730 --> 00:18:53.850
if we didn't have these different values of elevation

335
00:18:53.850 --> 00:18:56.433
and cadence for the two different workouts,

336
00:18:57.270 --> 00:18:58.950
but we do have it.

337
00:18:58.950 --> 00:19:03.030
And yeah, so we have to solve that problem.

338
00:19:03.030 --> 00:19:07.050
And so I think it works really nice like this.

339
00:19:07.050 --> 00:19:10.320
Let me just check it out here one more time now

340
00:19:10.320 --> 00:19:13.140
with these negative values.

341
00:19:13.140 --> 00:19:15.570
So if we have a negative distance,

342
00:19:15.570 --> 00:19:19.620
then now indeed, we get the (indistinct) two,

343
00:19:19.620 --> 00:19:21.453
except for cycling.

344
00:19:22.590 --> 00:19:24.333
So let's remove that one,

345
00:19:25.410 --> 00:19:30.410
and minus two, but that still works.

346
00:19:31.860 --> 00:19:36.860
And so clearly, our validation logic here is just fine.

347
00:19:37.500 --> 00:19:39.840
Great, so next up,

348
00:19:39.840 --> 00:19:41.523
let's see what we have to do.

349
00:19:42.480 --> 00:19:47.160
So actually, we still have to finish these ones.

350
00:19:47.160 --> 00:19:50.790
So if the workout is running, then create a running object,

351
00:19:50.790 --> 00:19:55.140
and otherwise, create a cycling object now, right?

352
00:19:55.140 --> 00:20:00.140
And then afterwards, push that object to the workout array.

353
00:20:00.300 --> 00:20:01.920
So add it to the array,

354
00:20:01.920 --> 00:20:05.043
and for that, we're gonna use the push method as always.

355
00:20:06.720 --> 00:20:08.670
So let's start with this one here,

356
00:20:08.670 --> 00:20:12.660
right after this guard clause, now, right?

357
00:20:12.660 --> 00:20:17.660
And so here, let's say workout should be a new running.

358
00:20:19.800 --> 00:20:23.580
And now let's see what we need for running,

359
00:20:23.580 --> 00:20:26.400
or actually, we can probably just hover this.

360
00:20:26.400 --> 00:20:28.680
And indeed here we have the coordinates,

361
00:20:28.680 --> 00:20:31.620
distance, duration, and cadence.

362
00:20:31.620 --> 00:20:35.613
All right, so where do we get the coordinates from?

363
00:20:36.900 --> 00:20:40.290
Well, we already know from the marker

364
00:20:40.290 --> 00:20:42.360
that they are right here.

365
00:20:42.360 --> 00:20:44.223
So in this .mapEvent.latlng,

366
00:20:46.530 --> 00:20:49.620
so we this because we already used this data before

367
00:20:49.620 --> 00:20:52.440
to render a marker on the map.

368
00:20:52.440 --> 00:20:55.530
So let's get this one and paste it here

369
00:20:55.530 --> 00:20:56.883
as the first argument.

370
00:20:58.140 --> 00:21:02.193
But actually, this year is now gonna be an object.

371
00:21:03.570 --> 00:21:07.410
So we know that because here we use these structuring

372
00:21:07.410 --> 00:21:11.850
to get the latitude and longitude out of that object.

373
00:21:11.850 --> 00:21:14.670
But up here, we said,

374
00:21:14.670 --> 00:21:16.260
so in the class definition

375
00:21:16.260 --> 00:21:18.963
that indeed we want an array, right?

376
00:21:20.250 --> 00:21:25.250
So let's simply get this code from here to up there.

377
00:21:27.240 --> 00:21:31.350
So here, and so basically create the latitude

378
00:21:31.350 --> 00:21:35.610
and longitude variables here based on this object.

379
00:21:35.610 --> 00:21:40.560
And so then here, we can define an array with that data,

380
00:21:40.560 --> 00:21:42.603
so lat and lng.

381
00:21:44.220 --> 00:21:46.350
So we already have our array

382
00:21:46.350 --> 00:21:49.320
of the coordinates just as expected,

383
00:21:49.320 --> 00:21:54.187
and then all we need is distance, duration, and cadence.

384
00:21:57.090 --> 00:22:01.620
And then we can take this.activities,

385
00:22:01.620 --> 00:22:04.263
and I think we didn't even create that one yet.

386
00:22:05.460 --> 00:22:08.367
So that's up here,

387
00:22:08.367 --> 00:22:11.913
and now again, we could do it right here like this.

388
00:22:12.750 --> 00:22:15.420
So basically, the more classical way.

389
00:22:15.420 --> 00:22:20.420
So this.workouts would be an empty array.

390
00:22:22.620 --> 00:22:24.210
But again, in this project,

391
00:22:24.210 --> 00:22:28.233
I chose to already use the class fields specification.

392
00:22:29.100 --> 00:22:30.660
And so this will become part

393
00:22:30.660 --> 00:22:32.883
of standard JavaScript very soon.

394
00:22:33.720 --> 00:22:37.380
And so therefore, I can create a class field like this,

395
00:22:37.380 --> 00:22:41.430
and I can even make it private just like the other two.

396
00:22:41.430 --> 00:22:44.640
But this time, I actually already initialized it here

397
00:22:44.640 --> 00:22:47.520
to a new empty array.

398
00:22:47.520 --> 00:22:48.993
And so now we can take that.

399
00:22:50.160 --> 00:22:51.720
So here in new workout,

400
00:22:51.720 --> 00:22:56.720
we can say this.#workouts.push this new workout.

401
00:23:02.310 --> 00:23:04.500
Now, we are gonna do basically,

402
00:23:04.500 --> 00:23:07.053
the exact same thing down here.

403
00:23:08.662 --> 00:23:12.210
And so this here is something that always needs to happen.

404
00:23:12.210 --> 00:23:15.480
So in both cases, and so let's not repeat that,

405
00:23:15.480 --> 00:23:18.090
and instead, put it down here.

406
00:23:18.090 --> 00:23:19.410
But then we have the problem

407
00:23:19.410 --> 00:23:22.770
that this workout variable is defined here

408
00:23:22.770 --> 00:23:25.530
in this block scope, right?

409
00:23:25.530 --> 00:23:28.800
And so because of the scope chain, as we already know,

410
00:23:28.800 --> 00:23:32.880
this workout variable will then not be available outside

411
00:23:32.880 --> 00:23:35.910
of this block, right?

412
00:23:35.910 --> 00:23:39.750
But we want it outside of the block, so right here.

413
00:23:39.750 --> 00:23:43.203
And so therefore, we put it right here outside.

414
00:23:45.660 --> 00:23:47.043
So let's work out.

415
00:23:49.170 --> 00:23:51.903
And then here, we simply redefine that,

416
00:23:52.813 --> 00:23:56.677
and then let's simply take this and put it here again.

417
00:23:59.940 --> 00:24:03.213
But this time, of course, with a cycling,

418
00:24:04.140 --> 00:24:07.230
and then still the coordinates distance duration,

419
00:24:07.230 --> 00:24:10.773
but here, the elevation, all right?

420
00:24:12.330 --> 00:24:15.480
The next step here is to actually render the workout

421
00:24:15.480 --> 00:24:18.870
on the map, all right?

422
00:24:18.870 --> 00:24:22.030
But before we do that, let's actually take a quick look

423
00:24:23.760 --> 00:24:27.570
at the console, and see our out there.

424
00:24:27.570 --> 00:24:30.270
And so with that, we can already check

425
00:24:30.270 --> 00:24:33.090
if all of this that we have up here,

426
00:24:33.090 --> 00:24:36.003
is already working, right?

427
00:24:37.860 --> 00:24:40.770
Okay, so let's wait for the map.

428
00:24:40.770 --> 00:24:44.910
And now, let's click here and add a running.

429
00:24:44.910 --> 00:24:49.910
So five and 25 with 170.

430
00:24:50.400 --> 00:24:54.033
And indeed, here we get our running object.

431
00:24:55.366 --> 00:24:59.160
So it has the coordinates, and so this worked,

432
00:24:59.160 --> 00:25:03.090
and of course, it has all the other data as well.

433
00:25:03.090 --> 00:25:06.000
This idea is now corrected as you see.

434
00:25:06.000 --> 00:25:08.580
And also, the pace is calculated here,

435
00:25:08.580 --> 00:25:13.350
based on this input data, right?

436
00:25:13.350 --> 00:25:16.380
And so indeed, the most complicated part

437
00:25:16.380 --> 00:25:20.280
of adding a new workout is already completed.

438
00:25:20.280 --> 00:25:21.990
So that's beautiful.

439
00:25:21.990 --> 00:25:24.093
Let's just try the same with cycling.

440
00:25:25.200 --> 00:25:30.200
Let's say 10 kilometers, and 10 minutes with 30 meters.

441
00:25:32.580 --> 00:25:37.580
No, and I didn't even click anywhere on the map, okay?

442
00:25:37.710 --> 00:25:41.340
And so that clearly means that we are still missing a step,

443
00:25:41.340 --> 00:25:43.560
which is to hide the form.

444
00:25:43.560 --> 00:25:47.640
But anyway, it simply took the coordinates from earlier,

445
00:25:47.640 --> 00:25:51.393
and then it added all the correct data here as well.

446
00:25:52.980 --> 00:25:55.200
So indeed it is now a cycling object,

447
00:25:55.200 --> 00:25:58.200
while before, it was a running object.

448
00:25:58.200 --> 00:26:01.100
Let's just do that again here, but this time with clicking

449
00:26:02.040 --> 00:26:03.690
so that I can show you something.

450
00:26:05.700 --> 00:26:08.520
All right, so it still says workout,

451
00:26:08.520 --> 00:26:10.710
and we're gonna fix that in the next video.

452
00:26:10.710 --> 00:26:13.590
But for now, what I want is the cycling actually

453
00:26:13.590 --> 00:26:15.543
to have this orange border.

454
00:26:16.440 --> 00:26:21.120
So just like this one, all right?

455
00:26:21.120 --> 00:26:24.363
So orange is for cycling, and green for running.

456
00:26:25.440 --> 00:26:28.203
And so let's quickly do that.

457
00:26:29.370 --> 00:26:33.000
So in our CSS, I think, I showed you earlier,

458
00:26:33.000 --> 00:26:36.390
that we have running-popup and cycling-popup.

459
00:26:36.390 --> 00:26:41.390
And these two values here are essentially simply the value

460
00:26:41.460 --> 00:26:42.813
of the input type.

461
00:26:43.650 --> 00:26:45.303
So this one here.

462
00:26:46.551 --> 00:26:50.950
And so here we can simply do a template literal,

463
00:26:53.070 --> 00:26:56.163
and then plug in the type here.

464
00:26:57.840 --> 00:27:00.420
And now actually, let's also export this here

465
00:27:00.420 --> 00:27:05.160
to its own method to make this add workout method here,

466
00:27:05.160 --> 00:27:07.800
a little bit cleaner, all right?

467
00:27:07.800 --> 00:27:11.143
So let's add down here, renderWorkoutMarker.

468
00:27:18.120 --> 00:27:20.463
Let's grab this code here.

469
00:27:25.185 --> 00:27:26.970
And so now, all we need to do is

470
00:27:26.970 --> 00:27:29.720
to call this.renderWorkoutMarker.

471
00:27:32.010 --> 00:27:34.780
And here, we need to pass in the workout object

472
00:27:35.700 --> 00:27:39.120
because otherwise, it's not gonna work.

473
00:27:39.120 --> 00:27:39.953
I mean, right now,

474
00:27:39.953 --> 00:27:43.593
we don't even need to workout yet, but later we will.

475
00:27:45.000 --> 00:27:48.480
So we want to display some kind of data about the workout,

476
00:27:48.480 --> 00:27:50.493
and so let's pass it in.

477
00:27:51.660 --> 00:27:53.610
So workout there and here,

478
00:27:53.610 --> 00:27:56.283
let's actually call it workout as well.

479
00:27:58.260 --> 00:28:00.990
And so here, instead of displaying this,

480
00:28:00.990 --> 00:28:05.990
let's simply display workout.distance.

481
00:28:06.210 --> 00:28:08.220
Okay, just for now,

482
00:28:08.220 --> 00:28:10.740
just so we are actually using the workout here

483
00:28:10.740 --> 00:28:12.053
in this method, okay?

484
00:28:13.950 --> 00:28:16.260
You see that we are also using the this keyword

485
00:28:16.260 --> 00:28:17.760
in this method.

486
00:28:17.760 --> 00:28:20.580
But actually, that's no problem in this case

487
00:28:20.580 --> 00:28:23.220
because here, we are actually calling this one here

488
00:28:23.220 --> 00:28:25.953
as a method of the this keyword.

489
00:28:27.030 --> 00:28:30.720
And besides that, we are also calling it ourselves.

490
00:28:30.720 --> 00:28:32.490
So it's not a callback function

491
00:28:32.490 --> 00:28:34.950
of any other function in JavaScript.

492
00:28:34.950 --> 00:28:38.280
And so therefore, the this keyword in this method here,

493
00:28:38.280 --> 00:28:40.980
will still be the current object.

494
00:28:40.980 --> 00:28:43.953
And so no need to using bind in this case.

495
00:28:44.820 --> 00:28:46.920
And so finally, the last step is

496
00:28:46.920 --> 00:28:49.830
to actually render the workout on the list.

497
00:28:49.830 --> 00:28:52.860
And this one, I'm gonna leave for the next lecture,

498
00:28:52.860 --> 00:28:55.740
because this one is gonna take a little bit of time

499
00:28:55.740 --> 00:28:59.070
in order to format all the HTML correctly.

500
00:28:59.070 --> 00:29:01.170
So let's give this one a save.

501
00:29:01.170 --> 00:29:04.863
And so besides that, this one is basically complete.

502
00:29:05.730 --> 00:29:09.750
And so let's quickly check it out one more time just

503
00:29:09.750 --> 00:29:12.393
to see the cycling-popup.

504
00:29:13.560 --> 00:29:15.540
So let's see right there,

505
00:29:15.540 --> 00:29:20.283
cycling 10, 10, 10, values don't matter.

506
00:29:21.150 --> 00:29:24.720
Oh, and here, we do actually have an error,

507
00:29:24.720 --> 00:29:28.110
which says that, "Latitude is not defined."

508
00:29:28.110 --> 00:29:31.863
And so indeed, here it is not defined.

509
00:29:32.730 --> 00:29:34.350
So instead these coordinates,

510
00:29:34.350 --> 00:29:37.740
should, of course, come from the workout itself.

511
00:29:37.740 --> 00:29:41.670
And so that itself is already a reason enough

512
00:29:41.670 --> 00:29:46.023
to pass in the workout argument here into this function.

513
00:29:47.580 --> 00:29:50.370
So now, it becomes very important for the first time

514
00:29:50.370 --> 00:29:53.790
to have some data in the actual workout object,

515
00:29:53.790 --> 00:29:57.780
because here we do need that in order to tell JavaScript,

516
00:29:57.780 --> 00:30:00.450
or actually in order to tell leaflet

517
00:30:00.450 --> 00:30:04.530
where to display this marker, okay?

518
00:30:04.530 --> 00:30:08.310
So it's the data that's coming directly from the workout.

519
00:30:08.310 --> 00:30:10.623
And so now, this should work,

520
00:30:11.460 --> 00:30:13.173
or maybe it shouldn't.

521
00:30:14.700 --> 00:30:17.040
So I'm looking at this variable here,

522
00:30:17.040 --> 00:30:18.330
and right now, the type is,

523
00:30:18.330 --> 00:30:22.710
of course, also no longer defined, right?

524
00:30:22.710 --> 00:30:25.260
So we get the type here from this one,

525
00:30:25.260 --> 00:30:27.976
but of course, this type variable,

526
00:30:27.976 --> 00:30:29.853
is not gonna be available right here.

527
00:30:30.780 --> 00:30:33.210
So, how do we fix that?

528
00:30:33.210 --> 00:30:36.090
Well, ideally we should get the information

529
00:30:36.090 --> 00:30:39.030
whether the current workout is of running

530
00:30:39.030 --> 00:30:42.393
or of cycling, right, from the workout object.

531
00:30:43.500 --> 00:30:46.080
And actually, that's a pretty good idea.

532
00:30:46.080 --> 00:30:49.890
And so let's add that value to the cycling

533
00:30:49.890 --> 00:30:51.690
and to the running.

534
00:30:51.690 --> 00:30:56.310
However, it doesn't make much sense to always pass that in.

535
00:30:56.310 --> 00:31:00.000
So we already know that running is always gonna be running,

536
00:31:00.000 --> 00:31:03.420
and cycling is always gonna be cycling.

537
00:31:03.420 --> 00:31:08.313
And so we can simply add basically that type right here.

538
00:31:09.660 --> 00:31:10.803
And so let's do that.

539
00:31:12.000 --> 00:31:17.000
So again, we are defining a field here, so cycling.

540
00:31:18.150 --> 00:31:21.510
And so this value type will now be a property

541
00:31:21.510 --> 00:31:26.510
that's gonna be available on all the instances, okay?

542
00:31:26.790 --> 00:31:28.650
So again, this would be the same thing

543
00:31:28.650 --> 00:31:33.650
as doing this.type equals cycling, like this, okay?

544
00:31:37.290 --> 00:31:41.203
And now, the same for running like this, all right?

545
00:31:46.590 --> 00:31:49.020
And so now, we can use that here,

546
00:31:49.020 --> 00:31:52.473
and we will actually also need that in some other places.

547
00:31:53.790 --> 00:31:56.553
And so this is indeed a good thing to have.

548
00:31:57.990 --> 00:32:01.230
So workout.type, and so now,

549
00:32:01.230 --> 00:32:03.843
this will weather be running or cycling.

550
00:32:05.280 --> 00:32:07.653
So let's test that now with cycling.

551
00:32:09.840 --> 00:32:11.943
So cycling and then,

552
00:32:14.010 --> 00:32:18.540
and we get another error, okay?

553
00:32:18.540 --> 00:32:23.540
So it failed to execute appendChild on Node for some reason,

554
00:32:24.870 --> 00:32:26.730
but let's go back to that in a second.

555
00:32:26.730 --> 00:32:31.170
For now, I just want to see if actually the type is there,

556
00:32:31.170 --> 00:32:33.420
and indeed it is.

557
00:32:33.420 --> 00:32:36.240
So that's great already.

558
00:32:36.240 --> 00:32:38.340
Now, let's just go back and see

559
00:32:38.340 --> 00:32:40.473
why this error here is happening.

560
00:32:42.930 --> 00:32:47.553
Well, there is no appendChild method anywhere here.

561
00:32:49.820 --> 00:32:52.053
Let's just set this here to something else,

562
00:32:53.670 --> 00:32:56.373
but that's probably not the problem anyway.

563
00:32:58.020 --> 00:33:00.900
So probably, I shouldn't have changed anything because now,

564
00:33:00.900 --> 00:33:03.060
the error message here will be gone.

565
00:33:03.060 --> 00:33:07.023
And then I cannot read the stack trace there,

566
00:33:10.020 --> 00:33:14.493
which is what we call to that list of errors.

567
00:33:15.390 --> 00:33:17.433
Oh, but now, it actually worked.

568
00:33:18.660 --> 00:33:21.420
All right, so the problem there was

569
00:33:21.420 --> 00:33:24.580
that we were actually probably passing in some value

570
00:33:25.750 --> 00:33:28.290
that was not a string, and so therefore,

571
00:33:28.290 --> 00:33:31.353
for some reason, leaflet created some problem there.

572
00:33:32.190 --> 00:33:34.830
But anyway, we will take care of this string here

573
00:33:34.830 --> 00:33:35.943
in the next video.

574
00:33:36.870 --> 00:33:41.133
For now, I just want to create just a running one here.

575
00:33:42.300 --> 00:33:46.110
And so this time, it turned out to be green,

576
00:33:46.110 --> 00:33:49.053
and so indeed, here the type is now running.

577
00:33:50.820 --> 00:33:54.810
All right, so this was a very long video,

578
00:33:54.810 --> 00:33:57.240
and so let's finish it here.

579
00:33:57.240 --> 00:33:59.820
And as I already said, in the next one,

580
00:33:59.820 --> 00:34:02.970
we will then finally render the workout also here

581
00:34:02.970 --> 00:34:04.233
on this sidebar.

