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
All right. 2
2
So this is the third and final part 3
3
of implementing the functionality of uploading or recipes. 4
4
And let's start by adding yet another recipe 5
5
so that I can show you something that is still missing 6
6
from our controller. 7
7
So actually, two things. 8
8
So, let's say this one here, test avocado. 9
9
Okay. 10
10
Just so we have a different name and watch what happens here 11
11
to the URL as we upload this recipe. 12
12
So actually nothing will change. 13
13
So, take a look at that. 14
14
Okay. 15
15
So recipe was successfully uploaded 16
16
and we also still need to remove this window. 17
17
Right? 18
18
But anyway, here is the recipe that we just uploaded 19
19
but the URL did not change. 20
20
And also it did not yet add this new recipe 21
21
to our bookmarks, okay? 22
22
So of course it is bookmarked, 23
23
all right, as you see here 24
24
and as you can also see down here. 25
25
But we didn't yet rerender this bookmarks panel, right? 26
26
So there are two things that we need to fix. 27
27
So we need to rerender this bookmarks view 28
28
and we also need to change the ID here in the URL 29
29
because watch what happens if I reload this page now. 30
30
So then we are back to the old recipe that was there before. 31
31
So, because that's the recipe that is associated to this ID. 32
32
So let's go back to our controller and fix these things 33
33
and also put back here, toggling the window. 34
34
So, let's do that right here 35
35
after displaying the success message we also want to render 36
36
the bookmark view. 37
37
And so that will then basically add this new element 38
38
to the bookmarksView.render. 39
39
So model.state.bookmarks. 40
40
Okay. 41
41
And we are not using update here 42
42
because we really want to insert a new element. 43
43
And for that we use always render and not the update method. 44
44
Now, the second thing that we wanted to do 45
45
is to change the ID into URL and for that, 46
46
we can use the history API. 47
47
So let's say change ID in the URL. 48
48
So we can say window.history. 49
49
So that is the history API of the browsers. 50
50
And then on this history object, 51
51
we can call the pushState method. 52
52
And so this will basically allow us to change the URL 53
53
without reloading the page. 54
54
Now, pushState takes three arguments. 55
55
And this first one here is called a state 56
56
which doesn't really matter. 57
57
You can just specify null. 58
58
Then the second one is the title 59
59
which is actually also not relevant. 60
60
So we can just use an empty string. 61
61
And then the one that actually is important 62
62
is the third one, because this one is actually the URL. 63
63
And so here we can simply put the hash 64
64
and then the ID that we want to put onto the URL. 65
65
So that is @model.state.recipe.id. 66
66
And that's actually it. 67
67
And we could also do all kinds of other stuff 68
68
with the history API, like for example going back and forth 69
69
just as if we were clicking the forward 70
70
and back buttons in the browser. 71
71
So we could do like this. 72
72
Of course, it doesn't make sense in this situation, 73
73
but maybe in some other situation you 74
74
might find this one helpful. 75
75
So automatically going back to the last page. 76
76
So that should work now but let's not test it yet 77
77
because the next thing that we want to do 78
78
is to refactor these to our methods here, 79
79
these two functions. 80
80
So getJSON and sendJSON are almost the same right now. 81
81
And so we can basically put them together just 82
82
in one function called AJAX, 83
83
because both of them are being done 84
84
for doing an AJAX request. 85
85
So just like this. 86
86
And in this one we'll receive the URL 87
87
and also the upload data 88
88
but we will set this one to undefined by default. 89
89
And so with this, when we call this AJAX function 90
90
with only the URL, then of course there is no upload data. 91
91
And then in that case, 92
92
we can simply define the fetchPro as only this. 93
93
So let's actually do that. 94
94
So conditionally defining this fetchPro variable. 95
95
So fetchPro and let's test if uploadData does exist. 96
96
So if it does exist, then fetchPro should become this. 97
97
So lets grab that, put that here. 98
98
And otherwise, it will simply be this. 99
99
And that's it. 100
100
Now of course I could have used an if else statement, 101
101
but then I would have had to declare this here 102
102
as a, let variable outside 103
103
and then change that variable in both the blocks. 104
104
And that's not really nice. 105
105
And so now we can, basically copy everything else here. 106
106
And we don't need this one anymore 107
107
and this should go all the way to the top. 108
108
And that's actually it. 109
109
So lets comment this one out. 110
110
Just one final look, but everything looks good here. 111
111
And so here now we can no longer import this one. 112
112
But let's just keep it there. 113
113
And we simply import AJAX. 114
114
So here and here, 115
115
and then down here for upload the recipe, 116
116
the same thing. 117
117
Okay, so let's try that. 118
118
And we see that we still get the recipe. 119
119
We also get to search. 120
120
And now finally, let's add another test23 recipe here. 121
121
Let's just change it up a little bit. 122
122
And now again, take a look what happens to the ID here. 123
123
So, you saw that it actually changed. 124
124
And so, now the idea for new recipe 125
125
is exactly that one that we have here. 126
126
And also, it should now be in your bookmark 127
127
and indeed it is. 128
128
Okay, and so now if we reload this page, then you see 129
129
that we are back at this recipe that we just created. 130
130
Great. 131
131
But now finally, let's use our keys 132
132
or key in order to actually mark this recipe here 133
133
as our own recipe by displaying like a small icon here. 134
134
And so for that, we need to attach 135
135
our key to all the API queries. 136
136
So, we can add the key to this one here, 137
137
simply by adding the key and of course also to this one. 138
138
So the one which has the ID. 139
139
So again at the end, question mark and then the key. 140
140
Okay, so let's simply get this one here. 141
141
So... 142
142
This one is for the search results. 143
143
Let's add this here. 144
144
And here we already have a parameter. 145
145
So here, it is then and. 146
146
So, search &key, but then 147
147
Yeah, for this one. 148
148
So for loading the recipe, there is nothing yet there. 149
149
And so we can simply add our KEY like this. 150
150
And so now by adding this KEY, 151
151
especially in the search results, 152
152
it will then load all the recipes including the ones 153
153
that contain or own key. 154
154
So if I search for avocado now 155
155
because I have, well not here in the demo, but in this one. 156
156
So I created a recipe which contains avocado. 157
157
And so if I search for avocado now 158
158
that should then contain this recipe that I just created. 159
159
All right, now we now want to mark this 160
160
as our own recipe again, 161
161
here in the search results and also here. 162
162
And so let's do that. 163
163
And just as a side note again, 164
164
if you're using your own API key 165
165
then of course you will not see this recipe here 166
166
because this recipe is linked to my API key. 167
167
So as we see right here. 168
168
So this is the key that I am using. 169
169
All right, and the same hear in the results. 170
170
So here in all the results you will see 171
171
that my own one has the key. 172
172
So this first one, 173
173
right, so TEST AVOCADO, it has my key, 174
174
but the other ones of course do not. 175
175
But anyway, let's noW go to the recipe view 176
176
and also the preview view. 177
177
So the one responsible for these results 178
178
and add the logic there to actually display 179
179
that small icon there. 180
180
So, we don't need this one anymore and neither this one. 181
181
So recipeView and PreviewView. 182
182
So the code for that is somewhere there at the top. 183
183
Here it is. 184
184
So user generated. 185
185
And I guess, I wrongly deleted some code here earlier. 186
186
So let's go back to the HTML 187
187
and copy it back like this. 188
188
And now the indentation is messed up. 189
189
Then here, we need to replace that with icons once again. 190
190
And so now, all we will do with this element here 191
191
is to basically add the hidden class 192
192
if there is no key on the recipe, 193
193
but if there is a key then we will add no class. 194
194
And so then it will become visible. 195
195
Okay. 196
196
So that's simply, this.data.key. 197
197
So if there is a key, then we want to add no class at all. 198
198
But if there is no key, then we add the hidden class. 199
199
Okay, and now the same here in the previewView, 200
200
and actually here, we don't even have that yet. 201
201
So, let's actually grab the same code 202
202
from the recipeView because it is almost the same. 203
203
And let's just see that here to see 204
204
where we have to paste it. 205
205
Well, it's not here, so let's just paste it anywhere. 206
206
So let's put it right here. 207
207
And then it's probably gonna called 208
208
the preview user generated. 209
209
All right, or actually, 210
210
I think that it is inside of this div here. 211
211
So let's move that down a little bit. 212
212
Fix the indentation here once again 213
213
to make it easier to see 214
214
just like this. 215
215
All right, and so let's now try it out. 216
216
So, let's search for avocado here again, 217
217
and then here it is. 218
218
And you see that now we have this icon here. 219
219
While if we click some other recipe then, it's not there. 220
220
All right. 221
221
Now it's only still missing here, 222
222
but that is because we actually never added this key 223
223
to the search data. 224
224
So let's go back to our model. 225
225
And so here in the load search results, 226
226
this is where we create the data 227
227
that will then be put in the state. 228
228
Right, so state.search.results will become 229
229
these objects here. 230
230
And so that only contains ID, title, publisher 231
231
and image, but not the key. 232
232
And so let's grab this code 233
233
that we used here in order to add the key 234
234
to the recipe object and do that here as well. 235
235
Right, then here, we just have to change this to rec, 236
236
just like all the others here. 237
237
And then with that, we should be good to go. 238
238
So let's see. 239
239
Search for avocado one more time. 240
240
And now it is there. 241
241
Do you see? 242
242
Great. 243
243
So again, this one does not have the icon 244
244
while this one here, of course now has. 245
245
So right here. 246
246
Beautiful. 247
247
So this is just great. 248
248
Let me know close this here and create one final, 249
249
more real recipe here for pizza that we have been using 250
250
all the time. 251
251
So let me get rid of all of these weird bookmarks. 252
252
Oh, and you see that also here, 253
253
we now have this icon, right? 254
254
And so that's the beauty of using the same preview here 255
255
in the results and also for the bookmarks. 256
256
Right? 257
257
So that makes everything really more reusable. 258
258
What's happening here? 259
259
Okay. 260
260
Just getting rid of all of them 261
261
because these recipes are not really that interesting. 262
262
So let's now add a super pizza. 263
263
Then the URL, let's make it jonas.io. 264
264
So that's HTTPS, jonas.io. 265
265
Then let's go to Unsplash and grab some image from there. 266
266
Just to make this again, a little bit more real world. 267
267
So this one here looks quite nice. 268
268
So let's right click and copy image address. 269
269
Okay. 270
270
Then here, Jonas Schmedtmann, 271
271
prep time 75 minutes, two servings. 272
272
And here let's just use one kilogram of flour. 273
273
Then some tomato sauce and the rest doesn't really matter. 274
274
Okay, so it looks correct. 275
275
Let's upload it and it was successful. 276
276
And here we get the super pizza. 277
277
Let's see here, and indeed we can update our servings here. 278
278
We are in the Bookmarks. 279
279
And if I now search for pizza, then here, it appears right 280
280
at the first position with this beautiful image. 281
281
And so, that means that our application 282
282
is now basically finished. 283
283
I just spotted a small bug here. 284
284
So in this ingredient description, 285
285
remember that we replaced all the spaces. 286
286
And so with that we lost the space between tomato sauce. 287
287
So let's quickly go fix that 288
288
but I will not add another recipe. 289
289
So we're not going to test this. 290
290
All I will do is to fix this problem down here. 291
291
So instead of this replaceAll here, let's do it differently. 292
292
So I will split the string into multiple parts, 293
293
which will then return an array. 294
294
And then I will loop over that array 295
295
and trim each of the elements. 296
296
So map to create a new array. 297
297
Let's just call it element here 298
298
and then just return element.trim, just like this. 299
299
Okay, and so now if we add just something to test here. 300
300
So adding some spaces here and maybe here, and here. 301
301
And so you see this work just fine now. 302
302
Oh, now we have two recipes for some reason. 303
303
Not sure why that was, but you see 304
304
that the spaces that are inserted there, they are gone. 305
305
Okay, let's remove this one here. 306
306
I don't want to see that again. 307
307
And so, yeah, our application is now feature complete. 308
308
So if we check out our flowchart's part three, 309
309
everything here is now implemented and that's just awesome. 310
310
So congratulations for going through this huge, 311
311
huge project together with me and making it all the way 312
312
to the end. 313
313
And now in the next final lecture of the section, 314
314
I will just quickly show you how we can write documentations 315
315
for functions in order to make other people understand 316
316
our code a little bit better, 317
317
and then and just like before, 318
318
I have some final suggestions for you. 319
319
So like, features and improvements 320
320
that you will be able to implement 321
321
on yourself if you want to practice your skills. 322
322
So I hope to see you there soon.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.