jwf-common-python 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jwf_common_python/__init__.py +14 -0
- jwf_common_python/db_utils/__init__.py +6 -0
- jwf_common_python/db_utils/clickhouse.py +124 -0
- jwf_common_python/db_utils/elasticsearch.py +196 -0
- jwf_common_python/db_utils/mysql.py +64 -0
- jwf_common_python/eudic/__init__.py +5 -0
- jwf_common_python/eudic/wordbook.py +211 -0
- jwf_common_python/file_storage/__init__.py +2 -0
- jwf_common_python/file_storage/file_interface.py +29 -0
- jwf_common_python/file_storage/local.py +50 -0
- jwf_common_python/file_storage/tencent_cos.py +65 -0
- jwf_common_python/geography/__init__.py +8 -0
- jwf_common_python/geography/district_amap.py +181 -0
- jwf_common_python/geography/search_amap.py +84 -0
- jwf_common_python/github/__init__.py +5 -0
- jwf_common_python/github/webhooks.py +87 -0
- jwf_common_python/language_utils/__init__.py +34 -0
- jwf_common_python/language_utils/core.py +203 -0
- jwf_common_python/language_utils/files.py +52 -0
- jwf_common_python/language_utils/web.py +117 -0
- jwf_common_python/llm/__init__.py +1 -0
- jwf_common_python/llm/aliyun_qwen.py +10 -0
- jwf_common_python/llm/azure_gpt.py +66 -0
- jwf_common_python/llm/baidu_ernie.py +112 -0
- jwf_common_python/message_queue/__init__.py +7 -0
- jwf_common_python/message_queue/interface.py +49 -0
- jwf_common_python/message_queue/kafka.py +145 -0
- jwf_common_python/message_queue/rabbitmq.py +113 -0
- jwf_common_python/oauth2/__init__.py +0 -0
- jwf_common_python/oauth2/google.py +158 -0
- jwf_common_python/parse_subtitle/__init__.py +6 -0
- jwf_common_python/parse_subtitle/aa.vtt +2364 -0
- jwf_common_python/parse_subtitle/parse_srt_file.py +60 -0
- jwf_common_python/pdf/__init__.py +0 -0
- jwf_common_python/pdf/aaa.py +38 -0
- jwf_common_python/pdf/local_parse.py +259 -0
- jwf_common_python/sms/__init__.py +1 -0
- jwf_common_python/sms/interface.py +7 -0
- jwf_common_python/sms/tencent_sms.py +117 -0
- jwf_common_python/translate/__init__.py +152 -0
- jwf_common_python/translate/_youdao.py +234 -0
- jwf_common_python/translate/microsoft.py +696 -0
- jwf_common_python/translate/tencent.py +194 -0
- jwf_common_python/tts/__init__.py +0 -0
- jwf_common_python/tts/microsoft.py +87 -0
- jwf_common_python/utils/__init__.py +0 -0
- jwf_common_python/utils/image_utils.py +18 -0
- jwf_common_python/utils/tencent_utils.py +51 -0
- jwf_common_python/utils/utils.py +46 -0
- jwf_common_python/video/__init__.py +5 -0
- jwf_common_python/video/merge.py +276 -0
- jwf_common_python/weather/__init__.py +0 -0
- jwf_common_python/weather/amap.py +127 -0
- jwf_common_python/weather/wanwei.py +58 -0
- jwf_common_python/youdao/__init__.py +13 -0
- jwf_common_python/youdao/wordbook.py +88 -0
- jwf_common_python-1.0.0.dist-info/METADATA +669 -0
- jwf_common_python-1.0.0.dist-info/RECORD +60 -0
- jwf_common_python-1.0.0.dist-info/WHEEL +4 -0
- jwf_common_python-1.0.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,2364 @@
|
|
|
1
|
+
WEBVTT
|
|
2
|
+
Kind: captions
|
|
3
|
+
Language: en
|
|
4
|
+
|
|
5
|
+
00:00:00.160 --> 00:00:03.360
|
|
6
|
+
If you want to create your own Chrome
|
|
7
|
+
extension, you're in the right place.
|
|
8
|
+
|
|
9
|
+
00:00:03.920 --> 00:00:08.640
|
|
10
|
+
In this course, Raman will teach you how
|
|
11
|
+
to create a Chrome extension using the new
|
|
12
|
+
|
|
13
|
+
00:00:08.640 --> 00:00:15.920
|
|
14
|
+
iteration of the web extensions platform, which is
|
|
15
|
+
called Manifest v3. Rahman is a great instructor.
|
|
16
|
+
|
|
17
|
+
00:00:16.640 --> 00:00:23.120
|
|
18
|
+
And he works for pieces that app pieces that app
|
|
19
|
+
provided a grant that made this course possible,
|
|
20
|
+
|
|
21
|
+
00:00:23.120 --> 00:00:27.680
|
|
22
|
+
but you don't have to use their extension to
|
|
23
|
+
follow along share in the comments what type
|
|
24
|
+
|
|
25
|
+
00:00:27.680 --> 00:00:32.240
|
|
26
|
+
of Chrome extension you want to make. Now the
|
|
27
|
+
reason I want to teach about this particular
|
|
28
|
+
|
|
29
|
+
00:00:32.240 --> 00:00:38.320
|
|
30
|
+
topic is I've created two web extensions in my
|
|
31
|
+
career. The first is for a previous company,
|
|
32
|
+
|
|
33
|
+
00:00:38.320 --> 00:00:43.760
|
|
34
|
+
where my extension generated a significant amount
|
|
35
|
+
of revenue for the company. And the second for my
|
|
36
|
+
|
|
37
|
+
00:00:43.760 --> 00:00:49.120
|
|
38
|
+
current company pieces, where our web extensions
|
|
39
|
+
play a critical part of our product stack,
|
|
40
|
+
|
|
41
|
+
00:00:49.120 --> 00:00:52.560
|
|
42
|
+
and help developers across the
|
|
43
|
+
globe boost their productivity.
|
|
44
|
+
|
|
45
|
+
00:00:53.520 --> 00:00:58.320
|
|
46
|
+
I'm going to be using the pieces web extensions
|
|
47
|
+
and integrations quite a bit in this video. So if
|
|
48
|
+
|
|
49
|
+
00:00:58.320 --> 00:01:03.520
|
|
50
|
+
you're interested in downloading an AI coding
|
|
51
|
+
assistant that helps you save and reuse code
|
|
52
|
+
|
|
53
|
+
00:01:03.520 --> 00:01:10.560
|
|
54
|
+
snippets, convert screenshots to code, and more,
|
|
55
|
+
go ahead and download pieces in the description.
|
|
56
|
+
|
|
57
|
+
00:01:10.560 --> 00:01:14.880
|
|
58
|
+
And you can totally follow along. So during
|
|
59
|
+
my journey as a Chrome extension developer,
|
|
60
|
+
|
|
61
|
+
00:01:14.880 --> 00:01:20.640
|
|
62
|
+
I did often notice that tutorials and
|
|
63
|
+
StackOverflow answers were using outdated versions
|
|
64
|
+
|
|
65
|
+
00:01:20.640 --> 00:01:26.000
|
|
66
|
+
of the web extensions platform. My hope for you
|
|
67
|
+
after you leave this video is that you have a
|
|
68
|
+
|
|
69
|
+
00:01:26.000 --> 00:01:30.240
|
|
70
|
+
resource to create a modern Chrome extension,
|
|
71
|
+
and you understand the difference between
|
|
72
|
+
|
|
73
|
+
00:01:30.800 --> 00:01:36.480
|
|
74
|
+
the newer version of the web extensions
|
|
75
|
+
platform manifest v3, and older versions. Now,
|
|
76
|
+
|
|
77
|
+
00:01:36.480 --> 00:01:39.840
|
|
78
|
+
before we get started, there's going to
|
|
79
|
+
be three prerequisites to this course,
|
|
80
|
+
|
|
81
|
+
00:01:40.640 --> 00:01:44.960
|
|
82
|
+
the first is required, and it's that you have
|
|
83
|
+
a basic understanding of JavaScript and DOM
|
|
84
|
+
|
|
85
|
+
00:01:44.960 --> 00:01:50.160
|
|
86
|
+
manipulation. The second is optional. If you
|
|
87
|
+
want to follow along with this video and code
|
|
88
|
+
|
|
89
|
+
00:01:50.160 --> 00:01:55.440
|
|
90
|
+
alongside with me, you can go to the description
|
|
91
|
+
below, I'm gonna have a link to my GitHub repo,
|
|
92
|
+
|
|
93
|
+
00:01:55.440 --> 00:02:00.960
|
|
94
|
+
go ahead and get cloned that and you'll be able
|
|
95
|
+
to follow along. The third is also optional.
|
|
96
|
+
|
|
97
|
+
00:02:00.960 --> 00:02:06.880
|
|
98
|
+
If you totally want to follow along, you can go
|
|
99
|
+
ahead to pieces dot app and install a pieces IDE
|
|
100
|
+
|
|
101
|
+
00:02:06.880 --> 00:02:12.240
|
|
102
|
+
integration along with the pieces Web Extension,
|
|
103
|
+
and you'll be able to use pieces exactly the way I
|
|
104
|
+
|
|
105
|
+
00:02:12.240 --> 00:02:17.680
|
|
106
|
+
do in this video. With that, let's get started. So
|
|
107
|
+
as I mentioned before, the extension we're going
|
|
108
|
+
|
|
109
|
+
00:02:17.680 --> 00:02:22.960
|
|
110
|
+
to create as a YouTube bookmarker. Basically,
|
|
111
|
+
anytime you navigate to a YouTube video page,
|
|
112
|
+
|
|
113
|
+
00:02:22.960 --> 00:02:28.000
|
|
114
|
+
an icon will show up on your YouTube video player
|
|
115
|
+
to allow you to bookmark a particular timestamp on
|
|
116
|
+
|
|
117
|
+
00:02:28.000 --> 00:02:33.280
|
|
118
|
+
any video. So let me show you how that's gonna
|
|
119
|
+
work. If you're on a YouTube video page, you're
|
|
120
|
+
|
|
121
|
+
00:02:33.280 --> 00:02:39.760
|
|
122
|
+
gonna see this item at the bottom right, you can
|
|
123
|
+
go ahead and click that. And if you navigate to
|
|
124
|
+
|
|
125
|
+
00:02:39.760 --> 00:02:43.920
|
|
126
|
+
your chrome extension icon at the top, right,
|
|
127
|
+
I've pinned, so it's showing in the toolbar,
|
|
128
|
+
|
|
129
|
+
00:02:45.680 --> 00:02:51.520
|
|
130
|
+
you're going to see a new timestamp already had
|
|
131
|
+
one timestamp for 15 minutes, I added one with
|
|
132
|
+
|
|
133
|
+
00:02:51.520 --> 00:02:58.240
|
|
134
|
+
an hour 18. I can go ahead and delete this one
|
|
135
|
+
because I just decided I don't want it. And our
|
|
136
|
+
|
|
137
|
+
00:02:58.240 --> 00:03:04.400
|
|
138
|
+
extension is going to give us that ability to do
|
|
139
|
+
that. Now if I want to go back to my 15 minute
|
|
140
|
+
|
|
141
|
+
00:03:04.400 --> 00:03:10.960
|
|
142
|
+
timestamp, you can click the play button. And it
|
|
143
|
+
goes directly back to that particular timestamp.
|
|
144
|
+
|
|
145
|
+
00:03:12.160 --> 00:03:16.240
|
|
146
|
+
I can also delete this one too. And
|
|
147
|
+
when there's no bookmarks to show,
|
|
148
|
+
|
|
149
|
+
00:03:16.240 --> 00:03:17.840
|
|
150
|
+
it's going to say there's no bookmarks to show.
|
|
151
|
+
|
|
152
|
+
00:03:19.520 --> 00:03:24.640
|
|
153
|
+
Now we're going to add one, just so we have one on
|
|
154
|
+
this video, and I can show you how storage works.
|
|
155
|
+
|
|
156
|
+
00:03:24.640 --> 00:03:30.480
|
|
157
|
+
I'm going to navigate to a new video. And in
|
|
158
|
+
this video, we have no bookmarks. So it says
|
|
159
|
+
|
|
160
|
+
00:03:30.480 --> 00:03:35.360
|
|
161
|
+
there's no bookmarks to show. But if we go back
|
|
162
|
+
to our previous video where we saved a bookmark,
|
|
163
|
+
|
|
164
|
+
00:03:36.320 --> 00:03:41.840
|
|
165
|
+
it's going to load that previous bookmark.
|
|
166
|
+
Now the last thing is if you navigate to a
|
|
167
|
+
|
|
168
|
+
00:03:41.840 --> 00:03:47.920
|
|
169
|
+
non YouTube video page, it's going to say this
|
|
170
|
+
is not a YouTube video page in the extension UI.
|
|
171
|
+
|
|
172
|
+
00:03:49.120 --> 00:03:54.000
|
|
173
|
+
And that's basically all the capabilities of this
|
|
174
|
+
chrome extension we're going to build out here,
|
|
175
|
+
|
|
176
|
+
00:03:54.000 --> 00:03:57.120
|
|
177
|
+
there's going to be a lot more
|
|
178
|
+
you can do on your own afterwards.
|
|
179
|
+
|
|
180
|
+
00:03:57.120 --> 00:04:01.600
|
|
181
|
+
Now I also want to mention the reason we're
|
|
182
|
+
working on creating this extension in particular,
|
|
183
|
+
|
|
184
|
+
00:04:01.600 --> 00:04:05.360
|
|
185
|
+
is because it's going to show you all the
|
|
186
|
+
major parts of creating a Chrome extension,
|
|
187
|
+
|
|
188
|
+
00:04:05.360 --> 00:04:09.280
|
|
189
|
+
it's going to show you how to work with
|
|
190
|
+
a content script to manipulate the DOM.
|
|
191
|
+
|
|
192
|
+
00:04:09.280 --> 00:04:13.760
|
|
193
|
+
It's going to show you how to create a UI for your
|
|
194
|
+
extension. And it's going to show you how to use
|
|
195
|
+
|
|
196
|
+
00:04:13.760 --> 00:04:19.760
|
|
197
|
+
service workers as background scripts, which
|
|
198
|
+
is a major part of the ship from manifest v2
|
|
199
|
+
|
|
200
|
+
00:04:19.760 --> 00:04:26.320
|
|
201
|
+
to manifest v3. And to start working on
|
|
202
|
+
the extension. Once you get cloned my repo,
|
|
203
|
+
|
|
204
|
+
00:04:26.320 --> 00:04:32.080
|
|
205
|
+
you can go ahead and click on the puzzle piece in
|
|
206
|
+
your Chrome browser at the top right click Manage
|
|
207
|
+
|
|
208
|
+
00:04:32.080 --> 00:04:38.640
|
|
209
|
+
extensions. I'm going to go ahead and remove my
|
|
210
|
+
extension show I can show you how it works. And
|
|
211
|
+
|
|
212
|
+
00:04:38.640 --> 00:04:43.920
|
|
213
|
+
you're going to see this developer mode option at
|
|
214
|
+
the top right go ahead and toggle that so it's on
|
|
215
|
+
|
|
216
|
+
00:04:44.800 --> 00:04:52.000
|
|
217
|
+
click Load unpacked, then go to the repo that
|
|
218
|
+
you get cloned in mind with the boilerplate code.
|
|
219
|
+
|
|
220
|
+
00:04:53.600 --> 00:05:00.640
|
|
221
|
+
Go ahead and load that. And we're going to see
|
|
222
|
+
our extension here. If we Click on this puzzle
|
|
223
|
+
|
|
224
|
+
00:05:00.640 --> 00:05:07.200
|
|
225
|
+
piece and pin it. What we're going to see is this
|
|
226
|
+
basic UI, it's just going to say your bookmarks
|
|
227
|
+
|
|
228
|
+
00:05:07.200 --> 00:05:13.280
|
|
229
|
+
for this video with no bookmarks, and it's just
|
|
230
|
+
going to show up everywhere. This is the default
|
|
231
|
+
|
|
232
|
+
00:05:13.280 --> 00:05:18.240
|
|
233
|
+
messaging in the boilerplate code I supplied
|
|
234
|
+
and the boilerplate code will also contain all
|
|
235
|
+
|
|
236
|
+
00:05:18.240 --> 00:05:23.120
|
|
237
|
+
the files you need to follow along. The best
|
|
238
|
+
place to start with creating our extension
|
|
239
|
+
|
|
240
|
+
00:05:23.120 --> 00:05:28.720
|
|
241
|
+
is the manifest dot JSON file. This file is a
|
|
242
|
+
JSON file where we can specify what version of
|
|
243
|
+
|
|
244
|
+
00:05:28.720 --> 00:05:33.840
|
|
245
|
+
the extensions platform we will use, among other
|
|
246
|
+
information that is going to serve as default for
|
|
247
|
+
|
|
248
|
+
00:05:33.840 --> 00:05:39.280
|
|
249
|
+
loading in our extensions. Also, every extension
|
|
250
|
+
you would want to create whether it's Safari,
|
|
251
|
+
|
|
252
|
+
00:05:39.280 --> 00:05:45.040
|
|
253
|
+
Mozilla, or any chromium base extension will need
|
|
254
|
+
a manifest dot JSON file. And it's probably the
|
|
255
|
+
|
|
256
|
+
00:05:45.040 --> 00:05:50.400
|
|
257
|
+
single most important file in your extension,
|
|
258
|
+
because it simply just won't work without it.
|
|
259
|
+
|
|
260
|
+
00:05:51.360 --> 00:05:57.040
|
|
261
|
+
In our boilerplate code already added the manifest
|
|
262
|
+
dot json file, so we don't have to spend too long
|
|
263
|
+
|
|
264
|
+
00:05:57.040 --> 00:06:00.960
|
|
265
|
+
writing it out, I think it would be especially
|
|
266
|
+
helpful if I just point out some of the things
|
|
267
|
+
|
|
268
|
+
00:06:00.960 --> 00:06:07.280
|
|
269
|
+
that you should note, in case you're creating your
|
|
270
|
+
own extension. So let's take a look here, as you'd
|
|
271
|
+
|
|
272
|
+
00:06:07.280 --> 00:06:13.840
|
|
273
|
+
suspect, there's a name, there's a version number
|
|
274
|
+
and a description. And basically, the version
|
|
275
|
+
|
|
276
|
+
00:06:13.840 --> 00:06:18.720
|
|
277
|
+
number is going to populate when you loaded in the
|
|
278
|
+
extension, the name you see is also going to be
|
|
279
|
+
|
|
280
|
+
00:06:18.720 --> 00:06:22.960
|
|
281
|
+
the name of the extension when you load it in. And
|
|
282
|
+
the description is pretty self explanatory. It's
|
|
283
|
+
|
|
284
|
+
00:06:22.960 --> 00:06:28.000
|
|
285
|
+
just a description of what the extension does. Now
|
|
286
|
+
things get more interesting with the permissions.
|
|
287
|
+
|
|
288
|
+
00:06:29.200 --> 00:06:32.880
|
|
289
|
+
The permissions will be different depending
|
|
290
|
+
on whatever Chrome extension you're building.
|
|
291
|
+
|
|
292
|
+
00:06:33.440 --> 00:06:36.640
|
|
293
|
+
For this particular extension, we're
|
|
294
|
+
going to request two permissions,
|
|
295
|
+
|
|
296
|
+
00:06:37.600 --> 00:06:43.440
|
|
297
|
+
which is going to be the permission to use the
|
|
298
|
+
Chrome dot storage API, and the chrome dot tabs
|
|
299
|
+
|
|
300
|
+
00:06:43.440 --> 00:06:49.680
|
|
301
|
+
API. The chrome dot storage API is to store things
|
|
302
|
+
in the user's browser for the extension. And the
|
|
303
|
+
|
|
304
|
+
00:06:49.680 --> 00:06:56.160
|
|
305
|
+
second permission, which is a chrome dot tabs API,
|
|
306
|
+
is what helps us access our browser's tab system.
|
|
307
|
+
|
|
308
|
+
00:06:56.720 --> 00:07:01.680
|
|
309
|
+
So we can read the tab for the extension. This is
|
|
310
|
+
basically going to help us identify what browser
|
|
311
|
+
|
|
312
|
+
00:07:01.680 --> 00:07:07.280
|
|
313
|
+
tab the user is currently using, and grab the URL
|
|
314
|
+
to see if they are in a YouTube video page for
|
|
315
|
+
|
|
316
|
+
00:07:07.280 --> 00:07:12.160
|
|
317
|
+
our extension. Now, the host permissions just give
|
|
318
|
+
you the ability to send cause requests to certain
|
|
319
|
+
|
|
320
|
+
00:07:12.160 --> 00:07:17.440
|
|
321
|
+
host names. Our extension only deals with YouTube
|
|
322
|
+
pages. So I have a match pattern written here just
|
|
323
|
+
|
|
324
|
+
00:07:17.440 --> 00:07:22.720
|
|
325
|
+
for YouTube. The service worker, as I mentioned
|
|
326
|
+
before, there's a big change between extensions,
|
|
327
|
+
|
|
328
|
+
00:07:22.720 --> 00:07:29.680
|
|
329
|
+
v2, and v3. And one of the big changes is the
|
|
330
|
+
use of a service worker. As you can see here, the
|
|
331
|
+
|
|
332
|
+
00:07:29.680 --> 00:07:34.320
|
|
333
|
+
other is the ability to use promises. But let's
|
|
334
|
+
just focus on service workers. For right now.
|
|
335
|
+
|
|
336
|
+
00:07:35.440 --> 00:07:39.920
|
|
337
|
+
Service workers are just a JavaScript file that
|
|
338
|
+
runs separately from the main browser thread.
|
|
339
|
+
|
|
340
|
+
00:07:40.720 --> 00:07:44.880
|
|
341
|
+
This means that your service worker would
|
|
342
|
+
not have access to content of a webpage,
|
|
343
|
+
|
|
344
|
+
00:07:44.880 --> 00:07:49.840
|
|
345
|
+
since it is separate from main processes.
|
|
346
|
+
However, your service worker does have
|
|
347
|
+
|
|
348
|
+
00:07:49.840 --> 00:07:56.240
|
|
349
|
+
capabilities to speak to your extension using the
|
|
350
|
+
extensions messaging system, which we will see
|
|
351
|
+
|
|
352
|
+
00:07:56.240 --> 00:08:01.440
|
|
353
|
+
and use in our bookmarking extension. The next
|
|
354
|
+
thing I want to point out is the content scripts.
|
|
355
|
+
|
|
356
|
+
00:08:02.080 --> 00:08:06.800
|
|
357
|
+
The content scripts are just files that
|
|
358
|
+
run in context of the webpages we're on.
|
|
359
|
+
|
|
360
|
+
00:08:07.600 --> 00:08:12.480
|
|
361
|
+
We're going to use this to manipulate the DOM
|
|
362
|
+
of our webpage that our extension is looking at.
|
|
363
|
+
|
|
364
|
+
00:08:13.120 --> 00:08:18.560
|
|
365
|
+
And here we're just specifying that our
|
|
366
|
+
content script is represented by our content
|
|
367
|
+
|
|
368
|
+
00:08:18.560 --> 00:08:25.200
|
|
369
|
+
script J S file. As you can see, with the J s
|
|
370
|
+
colon content script dot j s, the last thing I
|
|
371
|
+
|
|
372
|
+
00:08:25.200 --> 00:08:33.040
|
|
373
|
+
want to point out is the pop up dot HTML file down
|
|
374
|
+
here, under default pop up, this just specifies
|
|
375
|
+
|
|
376
|
+
00:08:33.040 --> 00:08:38.480
|
|
377
|
+
which file was served as our UI. In our case,
|
|
378
|
+
we've specified the pop up dot HTML file, and
|
|
379
|
+
|
|
380
|
+
00:08:38.480 --> 00:08:43.360
|
|
381
|
+
in that file, we specify that the corresponding
|
|
382
|
+
file that helps it with its interactivity is a
|
|
383
|
+
|
|
384
|
+
00:08:43.360 --> 00:08:48.240
|
|
385
|
+
pop up.js file. With all that out of the way,
|
|
386
|
+
let's get to coding the actual extension.
|
|
387
|
+
|
|
388
|
+
00:08:48.880 --> 00:08:52.640
|
|
389
|
+
We're now finally going to start
|
|
390
|
+
writing code to make our extension work.
|
|
391
|
+
|
|
392
|
+
00:08:53.280 --> 00:08:57.920
|
|
393
|
+
For us even test the extension, we have to add the
|
|
394
|
+
button of the YouTube player that will allow us to
|
|
395
|
+
|
|
396
|
+
00:08:57.920 --> 00:09:03.720
|
|
397
|
+
save bookmarks with timestamps. So in order for
|
|
398
|
+
us to add a button on the YouTube video player
|
|
399
|
+
|
|
400
|
+
00:09:03.720 --> 00:09:08.480
|
|
401
|
+
will have to manipulate the DOM of the web
|
|
402
|
+
page we are on. What that means is we'll have
|
|
403
|
+
|
|
404
|
+
00:09:08.480 --> 00:09:13.760
|
|
405
|
+
to write our logic in our content script file,
|
|
406
|
+
which operates in the context of the webpage,
|
|
407
|
+
|
|
408
|
+
00:09:13.760 --> 00:09:20.240
|
|
409
|
+
as I mentioned before, so let's go ahead and add
|
|
410
|
+
some code to our content script file. We're going
|
|
411
|
+
|
|
412
|
+
00:09:20.240 --> 00:09:31.280
|
|
413
|
+
to go ahead and add the following variables
|
|
414
|
+
YouTube, left, controls, and YouTube player
|
|
415
|
+
|
|
416
|
+
00:09:32.960 --> 00:09:36.880
|
|
417
|
+
one is going to be for accessing the
|
|
418
|
+
YouTube player one is going to be for
|
|
419
|
+
|
|
420
|
+
00:09:36.880 --> 00:09:41.680
|
|
421
|
+
accessing the controls. And this is going
|
|
422
|
+
to allow us to manipulate each of these.
|
|
423
|
+
|
|
424
|
+
00:09:42.640 --> 00:09:49.680
|
|
425
|
+
But before we continue writing the logic to do DOM
|
|
426
|
+
manipulation in the context strip, we also have to
|
|
427
|
+
|
|
428
|
+
00:09:49.680 --> 00:09:54.480
|
|
429
|
+
think about how our extension is even going to
|
|
430
|
+
know when we've navigated to a new web page.
|
|
431
|
+
|
|
432
|
+
00:09:54.480 --> 00:10:00.400
|
|
433
|
+
And we need to know this so the content script
|
|
434
|
+
knows to execute logic to add the plus i Call to
|
|
435
|
+
|
|
436
|
+
00:10:00.400 --> 00:10:05.200
|
|
437
|
+
add bookmarks for our extension. Let's go
|
|
438
|
+
ahead and go in our background.js file now.
|
|
439
|
+
|
|
440
|
+
00:10:06.000 --> 00:10:12.960
|
|
441
|
+
And what we want to do here is listen to any
|
|
442
|
+
updates in our tab system and find the most
|
|
443
|
+
|
|
444
|
+
00:10:12.960 --> 00:10:19.760
|
|
445
|
+
recent tab or the tab that we're on currently
|
|
446
|
+
and see if it's a YouTube page. So we're going
|
|
447
|
+
|
|
448
|
+
00:10:19.760 --> 00:10:24.240
|
|
449
|
+
to have a listener, that's going to
|
|
450
|
+
listen to tabs. And if you remember,
|
|
451
|
+
|
|
452
|
+
00:10:24.240 --> 00:10:31.840
|
|
453
|
+
we got permissions to access the Chrome tabs API.
|
|
454
|
+
And we're going to listen for an update to tabs.
|
|
455
|
+
|
|
456
|
+
00:10:34.880 --> 00:10:38.000
|
|
457
|
+
The parameters were given is a tab ID and a tab.
|
|
458
|
+
|
|
459
|
+
00:10:43.600 --> 00:10:49.680
|
|
460
|
+
What we're going to do from here is see if
|
|
461
|
+
there's a tab URL, and if there is a tab Euro.
|
|
462
|
+
|
|
463
|
+
00:10:50.880 --> 00:11:00.640
|
|
464
|
+
Let's see if that Euro includes
|
|
465
|
+
youtube.com/watch. The way I came up with that
|
|
466
|
+
|
|
467
|
+
00:11:02.080 --> 00:11:07.680
|
|
468
|
+
is if you look at our YouTube video, every
|
|
469
|
+
individual video has YouTube slash watch.
|
|
470
|
+
|
|
471
|
+
00:11:08.320 --> 00:11:14.160
|
|
472
|
+
And we just want to make sure we're on a
|
|
473
|
+
page that has that specifically as a URL,
|
|
474
|
+
|
|
475
|
+
00:11:14.160 --> 00:11:20.160
|
|
476
|
+
then what we want to do is set our query
|
|
477
|
+
parameters. And we're going to use query
|
|
478
|
+
|
|
479
|
+
00:11:20.160 --> 00:11:26.400
|
|
480
|
+
parameters as a unique ID for each video. So we
|
|
481
|
+
can grab it from storage, you'll see what I mean
|
|
482
|
+
|
|
483
|
+
00:11:26.400 --> 00:11:32.640
|
|
484
|
+
in a second, and I'll show you. So we're going
|
|
485
|
+
to do that by using the JavaScript split method.
|
|
486
|
+
|
|
487
|
+
00:11:35.600 --> 00:11:42.720
|
|
488
|
+
What that means is basically after this question
|
|
489
|
+
mark query parameter, we're going to grab
|
|
490
|
+
|
|
491
|
+
00:11:42.720 --> 00:11:48.320
|
|
492
|
+
this value. And this is going to be our unique
|
|
493
|
+
video value this right here after the equal
|
|
494
|
+
|
|
495
|
+
00:11:48.320 --> 00:11:55.440
|
|
496
|
+
sign. And every video on YouTube has a different
|
|
497
|
+
value right here. So it's a pretty unique key that
|
|
498
|
+
|
|
499
|
+
00:11:55.440 --> 00:12:03.360
|
|
500
|
+
will help us store videos uniquely as well in our
|
|
501
|
+
storage, and it's consistent. So then we're going
|
|
502
|
+
|
|
503
|
+
00:12:03.360 --> 00:12:13.440
|
|
504
|
+
to add your URL parameters. And this is just an
|
|
505
|
+
interface to work with URLs URL search params.
|
|
506
|
+
|
|
507
|
+
00:12:17.520 --> 00:12:22.720
|
|
508
|
+
And the final thing we want to do is there's
|
|
509
|
+
a messaging system that happens between
|
|
510
|
+
|
|
511
|
+
00:12:22.720 --> 00:12:26.080
|
|
512
|
+
the extension, we're going to send a message
|
|
513
|
+
|
|
514
|
+
00:12:26.080 --> 00:12:33.760
|
|
515
|
+
to our content script that basically says a new
|
|
516
|
+
video is loaded. And this is the video ID of
|
|
517
|
+
|
|
518
|
+
00:12:33.760 --> 00:12:40.240
|
|
519
|
+
that video, and the video ID being that unique
|
|
520
|
+
video value that we saw in the URL on YouTube.
|
|
521
|
+
|
|
522
|
+
00:12:46.400 --> 00:12:52.960
|
|
523
|
+
And this tab, Id send message usage that I'm doing
|
|
524
|
+
right here is all directly from documentation.
|
|
525
|
+
|
|
526
|
+
00:12:53.520 --> 00:12:59.760
|
|
527
|
+
The Send Message takes a tab ID, it takes a
|
|
528
|
+
unique object. So right now I'm going to type
|
|
529
|
+
|
|
530
|
+
00:12:59.760 --> 00:13:05.840
|
|
531
|
+
type. And this is a type of event is a new
|
|
532
|
+
video event. And then a video ID value,
|
|
533
|
+
|
|
534
|
+
00:13:07.440 --> 00:13:18.720
|
|
535
|
+
which is going to be URL, parameters, dot get v.
|
|
536
|
+
So if we're doing URL dot get D, it's going to
|
|
537
|
+
|
|
538
|
+
00:13:18.720 --> 00:13:25.120
|
|
539
|
+
grab this right here. And that's basically going
|
|
540
|
+
to be the code for that send message takes a tab
|
|
541
|
+
|
|
542
|
+
00:13:25.120 --> 00:13:30.560
|
|
543
|
+
ID, it takes an object and then it can also take a
|
|
544
|
+
callback function. This object right here doesn't
|
|
545
|
+
|
|
546
|
+
00:13:30.560 --> 00:13:38.000
|
|
547
|
+
have to be type or video ID, it could also be
|
|
548
|
+
something random, like I could literally pass this
|
|
549
|
+
|
|
550
|
+
00:13:38.000 --> 00:13:45.440
|
|
551
|
+
and the content script will have access to
|
|
552
|
+
random, and then the string random. In our case,
|
|
553
|
+
|
|
554
|
+
00:13:45.440 --> 00:13:50.400
|
|
555
|
+
the only thing that's applicable is the
|
|
556
|
+
type of the event and then the video ID,
|
|
557
|
+
|
|
558
|
+
00:13:50.400 --> 00:13:55.520
|
|
559
|
+
which is a content script needs. Now in our
|
|
560
|
+
content script, we're going to add a listener that
|
|
561
|
+
|
|
562
|
+
00:13:56.240 --> 00:14:01.120
|
|
563
|
+
is going to listen to any of those incoming
|
|
564
|
+
messages, we need to be able to listen to that
|
|
565
|
+
|
|
566
|
+
00:14:01.120 --> 00:14:06.480
|
|
567
|
+
background.js message. So to do that, we're
|
|
568
|
+
going to end up writing the following code
|
|
569
|
+
|
|
570
|
+
00:14:07.840 --> 00:14:15.840
|
|
571
|
+
to add that listener, so we're going to say on
|
|
572
|
+
message add listener. And this is going to accept
|
|
573
|
+
|
|
574
|
+
00:14:17.040 --> 00:14:24.160
|
|
575
|
+
three parameters. So an object a sender,
|
|
576
|
+
and a response. And the response is,
|
|
577
|
+
|
|
578
|
+
00:14:24.160 --> 00:14:30.000
|
|
579
|
+
when a message is being sent to the content
|
|
580
|
+
script, we can also send a response back where
|
|
581
|
+
|
|
582
|
+
00:14:30.000 --> 00:14:35.520
|
|
583
|
+
the message is coming from. So I'm going
|
|
584
|
+
to destructure those values we're getting
|
|
585
|
+
|
|
586
|
+
00:14:40.400 --> 00:14:47.040
|
|
587
|
+
and if you remember, the way I'm deconstructing
|
|
588
|
+
Type value video ID is basically we're given a
|
|
589
|
+
|
|
590
|
+
00:14:47.040 --> 00:14:54.800
|
|
591
|
+
video ID right here. Later on, we're going to grab
|
|
592
|
+
a value as well, and I'm just destructuring. So
|
|
593
|
+
|
|
594
|
+
00:14:55.520 --> 00:15:02.400
|
|
595
|
+
each of these are its own variable.
|
|
596
|
+
So it's a If type is equal to new,
|
|
597
|
+
|
|
598
|
+
00:15:02.400 --> 00:15:09.040
|
|
599
|
+
so if the type of event is new video loaded,
|
|
600
|
+
which we're getting from the background.js file,
|
|
601
|
+
|
|
602
|
+
00:15:09.600 --> 00:15:17.440
|
|
603
|
+
we want to be able to set current video, which
|
|
604
|
+
will be a global variable in the content script
|
|
605
|
+
|
|
606
|
+
00:15:18.640 --> 00:15:25.120
|
|
607
|
+
as the video ID, and then we want to
|
|
608
|
+
call a function to handle any actions
|
|
609
|
+
|
|
610
|
+
00:15:25.680 --> 00:15:29.760
|
|
611
|
+
with new video. So we're going to
|
|
612
|
+
call a new video loaded function.
|
|
613
|
+
|
|
614
|
+
00:15:32.240 --> 00:15:41.520
|
|
615
|
+
And let's go ahead and set current video as a
|
|
616
|
+
top level variable. And that's just going to
|
|
617
|
+
|
|
618
|
+
00:15:41.520 --> 00:15:47.760
|
|
619
|
+
be an empty string. But it's going to be set as
|
|
620
|
+
the string set from the background at js file,
|
|
621
|
+
|
|
622
|
+
00:15:48.480 --> 00:15:54.320
|
|
623
|
+
once the message is received on this end, so let's
|
|
624
|
+
go ahead and actually see if this works at all.
|
|
625
|
+
|
|
626
|
+
00:15:55.520 --> 00:16:01.600
|
|
627
|
+
I'm gonna go ahead and just
|
|
628
|
+
console dot log your parameters.
|
|
629
|
+
|
|
630
|
+
00:16:06.960 --> 00:16:16.320
|
|
631
|
+
I'm gonna give this a reload. Open this, let's
|
|
632
|
+
inspect it. And we ever URL search parameters.
|
|
633
|
+
|
|
634
|
+
00:16:16.320 --> 00:16:24.000
|
|
635
|
+
So we know we're getting our URL search parameters
|
|
636
|
+
now. Great. So so far, things look good.
|
|
637
|
+
|
|
638
|
+
00:16:25.600 --> 00:16:31.360
|
|
639
|
+
Now, what we want to do from here is
|
|
640
|
+
create that new video loaded function.
|
|
641
|
+
|
|
642
|
+
00:16:32.080 --> 00:16:35.840
|
|
643
|
+
And after we create this function and
|
|
644
|
+
all the functionality surrounding it,
|
|
645
|
+
|
|
646
|
+
00:16:36.400 --> 00:16:43.280
|
|
647
|
+
we should see the YouTube player button on the
|
|
648
|
+
YouTube video. So let's go ahead and do that.
|
|
649
|
+
|
|
650
|
+
00:16:43.280 --> 00:16:49.840
|
|
651
|
+
So what we're going to do is create this function
|
|
652
|
+
that we have right here called New Video loaded.
|
|
653
|
+
|
|
654
|
+
00:16:55.840 --> 00:17:02.240
|
|
655
|
+
And what we probably want to do is check
|
|
656
|
+
if a bookmark button already exists,
|
|
657
|
+
|
|
658
|
+
00:17:02.240 --> 00:17:06.880
|
|
659
|
+
I know the class name that this item
|
|
660
|
+
has, it's called Bookmark button
|
|
661
|
+
|
|
662
|
+
00:17:06.880 --> 00:17:11.760
|
|
663
|
+
because I wrote the CSS code that's
|
|
664
|
+
going to style this whole extension.
|
|
665
|
+
|
|
666
|
+
00:17:11.760 --> 00:17:21.120
|
|
667
|
+
So you could just copy this part right here. But
|
|
668
|
+
this is just some native Dom, slash JavaScript
|
|
669
|
+
|
|
670
|
+
00:17:23.280 --> 00:17:30.960
|
|
671
|
+
methods that we can use. It's actually MB by
|
|
672
|
+
class name. And it's going to return an HTML
|
|
673
|
+
|
|
674
|
+
00:17:30.960 --> 00:17:36.240
|
|
675
|
+
collection. So what we're going to do is grab
|
|
676
|
+
the first element that matches this class name,
|
|
677
|
+
|
|
678
|
+
00:17:36.240 --> 00:17:41.760
|
|
679
|
+
bookmark button. And it's just going to
|
|
680
|
+
exist on every single YouTube video page.
|
|
681
|
+
|
|
682
|
+
00:17:43.680 --> 00:17:52.400
|
|
683
|
+
So if we want to test that, we could just say
|
|
684
|
+
console dot log bookmark exists. And let's reload
|
|
685
|
+
|
|
686
|
+
00:17:52.400 --> 00:18:02.080
|
|
687
|
+
this page and inspect it. Actually, let's reload
|
|
688
|
+
our extension as well. reload this page inspect,
|
|
689
|
+
|
|
690
|
+
00:18:03.520 --> 00:18:09.440
|
|
691
|
+
we're probably going to get undefined
|
|
692
|
+
this is exactly what I expected.
|
|
693
|
+
|
|
694
|
+
00:18:10.240 --> 00:18:15.280
|
|
695
|
+
Because we don't have any logic surrounding the
|
|
696
|
+
Bookmark button yet. And also, we're not even
|
|
697
|
+
|
|
698
|
+
00:18:15.280 --> 00:18:21.760
|
|
699
|
+
setting a bookmark button right now. So if the
|
|
700
|
+
Bookmark button did exist, we would get true,
|
|
701
|
+
|
|
702
|
+
00:18:21.760 --> 00:18:26.640
|
|
703
|
+
it does exist, but we're getting undefined right
|
|
704
|
+
now. So what we want to do if we're getting
|
|
705
|
+
|
|
706
|
+
00:18:26.640 --> 00:18:36.080
|
|
707
|
+
that undefined or false value that a bookmark
|
|
708
|
+
button does not exist, is add some logic to say,
|
|
709
|
+
|
|
710
|
+
00:18:36.080 --> 00:18:43.440
|
|
711
|
+
hey, let's add this bookmark button to any YouTube
|
|
712
|
+
player. So we're going to create an image element.
|
|
713
|
+
|
|
714
|
+
00:18:45.120 --> 00:18:55.840
|
|
715
|
+
That is going to be the image we
|
|
716
|
+
click on for bookmark buttons.
|
|
717
|
+
|
|
718
|
+
00:19:00.000 --> 00:19:03.360
|
|
719
|
+
As part is in, we're going to
|
|
720
|
+
add a couple of attributes.
|
|
721
|
+
|
|
722
|
+
00:19:07.840 --> 00:19:12.960
|
|
723
|
+
The first thing we're going to want to do
|
|
724
|
+
is pull the image that we're using, which is
|
|
725
|
+
|
|
726
|
+
00:19:15.120 --> 00:19:20.560
|
|
727
|
+
our assets slash bookmark. PNG, you already
|
|
728
|
+
have this if you're following along with the
|
|
729
|
+
|
|
730
|
+
00:19:20.560 --> 00:19:30.400
|
|
731
|
+
boilerplate code. The second thing we want to do
|
|
732
|
+
is add a class. And the way we're going to add
|
|
733
|
+
|
|
734
|
+
00:19:30.400 --> 00:19:37.840
|
|
735
|
+
this class is basically make it pretty dynamic
|
|
736
|
+
here. So we're gonna add a YouTube button class
|
|
737
|
+
|
|
738
|
+
00:19:41.120 --> 00:19:52.320
|
|
739
|
+
with a space and then we're going to add a
|
|
740
|
+
bookmark button class in quotes. And this
|
|
741
|
+
|
|
742
|
+
00:19:52.320 --> 00:19:56.800
|
|
743
|
+
is again, just some styling I have that
|
|
744
|
+
you don't need to worry about right now.
|
|
745
|
+
|
|
746
|
+
00:19:57.680 --> 00:20:02.480
|
|
747
|
+
And the last thing we want to do is basically
|
|
748
|
+
on hover, we want to make a title show.
|
|
749
|
+
|
|
750
|
+
00:20:03.840 --> 00:20:06.800
|
|
751
|
+
So we're just gonna say the
|
|
752
|
+
title is click to bookmark,
|
|
753
|
+
|
|
754
|
+
00:20:07.520 --> 00:20:11.840
|
|
755
|
+
current timestamp. And this is just
|
|
756
|
+
a UI thing. You'll see this in a bit.
|
|
757
|
+
|
|
758
|
+
00:20:14.320 --> 00:20:21.440
|
|
759
|
+
Next, what we want to show is a way to
|
|
760
|
+
grab the YouTube controls. So these are
|
|
761
|
+
|
|
762
|
+
00:20:21.440 --> 00:20:26.800
|
|
763
|
+
the YouTube controls over here, we want
|
|
764
|
+
to be able to grab these left controls,
|
|
765
|
+
|
|
766
|
+
00:20:26.800 --> 00:20:33.840
|
|
767
|
+
so we can add a bookmark button right here.
|
|
768
|
+
So let's go ahead and find out how to do that.
|
|
769
|
+
|
|
770
|
+
00:20:35.440 --> 00:20:41.200
|
|
771
|
+
I already know how to grab this. So I'm going
|
|
772
|
+
to show you how this works. You can inspect
|
|
773
|
+
|
|
774
|
+
00:20:41.200 --> 00:20:47.120
|
|
775
|
+
elements right here and find what elements they
|
|
776
|
+
exactly are. But basically, we're going to use
|
|
777
|
+
|
|
778
|
+
00:20:47.120 --> 00:20:52.160
|
|
779
|
+
native JavaScript methods like we have done
|
|
780
|
+
previously to grab those controls and insert
|
|
781
|
+
|
|
782
|
+
00:20:52.160 --> 00:21:04.320
|
|
783
|
+
our button. If I do document dot get elements
|
|
784
|
+
by class name. And I grab YouTube left controls,
|
|
785
|
+
|
|
786
|
+
00:21:07.040 --> 00:21:13.040
|
|
787
|
+
we should get an element back, which is
|
|
788
|
+
going to be this div class over here.
|
|
789
|
+
|
|
790
|
+
00:21:14.320 --> 00:21:19.680
|
|
791
|
+
And you can see that it gives us all the left
|
|
792
|
+
controls over here, where we're going to add
|
|
793
|
+
|
|
794
|
+
00:21:19.680 --> 00:21:25.040
|
|
795
|
+
our button. And the second thing we're going to
|
|
796
|
+
want to do is grab the YouTube player as well.
|
|
797
|
+
|
|
798
|
+
00:21:25.040 --> 00:21:31.280
|
|
799
|
+
And that's one of the global variables we set
|
|
800
|
+
in our content script. And we can also do that
|
|
801
|
+
|
|
802
|
+
00:21:33.360 --> 00:21:44.960
|
|
803
|
+
by writing document dot get elements by class
|
|
804
|
+
name. And then there's this video stream class.
|
|
805
|
+
|
|
806
|
+
00:21:46.800 --> 00:21:55.360
|
|
807
|
+
And we're going to grab the one at the zero with
|
|
808
|
+
index. And it grabs a whole YouTube component
|
|
809
|
+
|
|
810
|
+
00:21:55.360 --> 00:22:02.000
|
|
811
|
+
right there. So now we know the two elements in
|
|
812
|
+
the DOM we need to manipulate. But let's set those
|
|
813
|
+
|
|
814
|
+
00:22:02.000 --> 00:22:10.040
|
|
815
|
+
elements. First, we're going to do exactly what
|
|
816
|
+
we saw in our content over there. Document get,
|
|
817
|
+
|
|
818
|
+
00:22:10.640 --> 00:22:15.760
|
|
819
|
+
actually, I'm just gonna go back and copy
|
|
820
|
+
these way easier, so don't make a mistake.
|
|
821
|
+
|
|
822
|
+
00:22:20.640 --> 00:22:25.840
|
|
823
|
+
And then the second one is going to be
|
|
824
|
+
YouTube player. Go back and copy that.
|
|
825
|
+
|
|
826
|
+
00:22:32.320 --> 00:22:38.320
|
|
827
|
+
Okay, so after this, what we're going to
|
|
828
|
+
want to do is add that bookmark button and
|
|
829
|
+
|
|
830
|
+
00:22:38.320 --> 00:22:44.240
|
|
831
|
+
we grabbed the controls, you saw that row in
|
|
832
|
+
the player, we want to add it to that row. So
|
|
833
|
+
|
|
834
|
+
00:22:44.240 --> 00:22:49.600
|
|
835
|
+
we're going to type out YouTube left controls to
|
|
836
|
+
get those left controls we stored in a variable.
|
|
837
|
+
|
|
838
|
+
00:22:50.320 --> 00:22:57.200
|
|
839
|
+
And to use this native JavaScript method we can
|
|
840
|
+
use called append child, which is going to append
|
|
841
|
+
|
|
842
|
+
00:22:58.640 --> 00:23:01.120
|
|
843
|
+
this bookmark element inside that row.
|
|
844
|
+
|
|
845
|
+
00:23:03.680 --> 00:23:08.000
|
|
846
|
+
And then the second thing we're going to want
|
|
847
|
+
to do is probably add a listener to listen to
|
|
848
|
+
|
|
849
|
+
00:23:08.000 --> 00:23:14.000
|
|
850
|
+
any clicks on our icon. So there's a correction I
|
|
851
|
+
want to make to this portion of the video, before
|
|
852
|
+
|
|
853
|
+
00:23:14.000 --> 00:23:19.760
|
|
854
|
+
we continue, it's going to be very important in
|
|
855
|
+
order for your extension to work functionally.
|
|
856
|
+
|
|
857
|
+
00:23:20.720 --> 00:23:26.000
|
|
858
|
+
And it's only one line of code, but it's going
|
|
859
|
+
to make such a big difference. I'm also going to
|
|
860
|
+
|
|
861
|
+
00:23:26.000 --> 00:23:30.960
|
|
862
|
+
explain an important concept of Chrome extensions
|
|
863
|
+
that I neglected while I was writing this,
|
|
864
|
+
|
|
865
|
+
00:23:31.520 --> 00:23:38.000
|
|
866
|
+
which is that in our manifest json file, we
|
|
867
|
+
have a match pattern for our content script.
|
|
868
|
+
|
|
869
|
+
00:23:38.000 --> 00:23:44.320
|
|
870
|
+
And basically the match pattern, we currently
|
|
871
|
+
have checks if any youtube.com video is loaded.
|
|
872
|
+
|
|
873
|
+
00:23:44.320 --> 00:23:49.840
|
|
874
|
+
And if it is, we're injecting our content script
|
|
875
|
+
into the context of that web page. So basically,
|
|
876
|
+
|
|
877
|
+
00:23:49.840 --> 00:23:55.840
|
|
878
|
+
what that means is, anytime a youtube.com
|
|
879
|
+
page shows up, we're running a bunch of logic
|
|
880
|
+
|
|
881
|
+
00:23:56.400 --> 00:24:04.000
|
|
882
|
+
using our content script. But the problem right
|
|
883
|
+
now is that our background.js file is telling
|
|
884
|
+
|
|
885
|
+
00:24:04.000 --> 00:24:09.440
|
|
886
|
+
us when a new video is loaded. And the
|
|
887
|
+
event listener we're using is on updated,
|
|
888
|
+
|
|
889
|
+
00:24:09.440 --> 00:24:15.520
|
|
890
|
+
which is just checking if this URL is updated. If
|
|
891
|
+
you refresh this page, the URL is not updated. So
|
|
892
|
+
|
|
893
|
+
00:24:15.520 --> 00:24:21.760
|
|
894
|
+
this button actually isn't going to show up. And
|
|
895
|
+
if you continue coding without this fix right
|
|
896
|
+
|
|
897
|
+
00:24:21.760 --> 00:24:27.840
|
|
898
|
+
here, you're gonna see some edge cases that you
|
|
899
|
+
might not like. So let's go ahead and fix this,
|
|
900
|
+
|
|
901
|
+
00:24:27.840 --> 00:24:34.320
|
|
902
|
+
we're going to do a super simple fix. It's not the
|
|
903
|
+
best fix in the world, but it will fix the problem
|
|
904
|
+
|
|
905
|
+
00:24:34.320 --> 00:24:41.360
|
|
906
|
+
here. We're just going to call a new video loaded
|
|
907
|
+
anytime our content script matches youtube.com.
|
|
908
|
+
|
|
909
|
+
00:24:42.080 --> 00:24:47.280
|
|
910
|
+
And what this is going to do is call this
|
|
911
|
+
new video loaded function anytime we hit
|
|
912
|
+
|
|
913
|
+
00:24:47.280 --> 00:24:55.520
|
|
914
|
+
that match pattern. The downside of this is now
|
|
915
|
+
if the background script sees it as a new video
|
|
916
|
+
|
|
917
|
+
00:24:55.520 --> 00:25:01.520
|
|
918
|
+
using the on updated event listener, and there's
|
|
919
|
+
a condition that content script is injected,
|
|
920
|
+
|
|
921
|
+
00:25:01.520 --> 00:25:06.480
|
|
922
|
+
we're going to hit this or call this new video
|
|
923
|
+
loaded function twice, you can fix this pretty
|
|
924
|
+
|
|
925
|
+
00:25:06.480 --> 00:25:10.800
|
|
926
|
+
easily by just adding a conditional make sure
|
|
927
|
+
that doesn't happen. But to make sure everyone
|
|
928
|
+
|
|
929
|
+
00:25:10.800 --> 00:25:14.960
|
|
930
|
+
is able to follow along with this correction,
|
|
931
|
+
I will not be doing that here. And we'll just
|
|
932
|
+
|
|
933
|
+
00:25:14.960 --> 00:25:19.600
|
|
934
|
+
only be inserting this one line of code calling
|
|
935
|
+
the new video loaded function. Luckily, the only
|
|
936
|
+
|
|
937
|
+
00:25:19.600 --> 00:25:24.640
|
|
938
|
+
thing our new video loaded function is doing is
|
|
939
|
+
adding the Bookmark button to the YouTube player.
|
|
940
|
+
|
|
941
|
+
00:25:24.640 --> 00:25:29.200
|
|
942
|
+
So there's going to be no negative implications to
|
|
943
|
+
calling it twice. Since we have a condition that
|
|
944
|
+
|
|
945
|
+
00:25:29.200 --> 00:25:33.040
|
|
946
|
+
checks if the button is already on the player.
|
|
947
|
+
It's just not the most efficient implementation,
|
|
948
|
+
|
|
949
|
+
00:25:33.040 --> 00:25:42.160
|
|
950
|
+
which is fine for the sake of this tutorial. With
|
|
951
|
+
that, let's continue with the rest of the video.
|
|
952
|
+
|
|
953
|
+
00:25:42.160 --> 00:25:47.520
|
|
954
|
+
There we go, we have the button right there.
|
|
955
|
+
But right now, if we click the button,
|
|
956
|
+
|
|
957
|
+
00:25:49.040 --> 00:25:55.680
|
|
958
|
+
it's not doing anything. And there's a reason for
|
|
959
|
+
that. The reason is that we don't have any event
|
|
960
|
+
|
|
961
|
+
00:25:55.680 --> 00:26:02.640
|
|
962
|
+
listener listening to click on this particular
|
|
963
|
+
byte. Let's go ahead and add the code for that.
|
|
964
|
+
|
|
965
|
+
00:26:05.200 --> 00:26:10.080
|
|
966
|
+
So what we're going to do is add an event
|
|
967
|
+
listener to listen to a click for the button.
|
|
968
|
+
|
|
969
|
+
00:26:11.440 --> 00:26:16.560
|
|
970
|
+
And we're literally going to use the add
|
|
971
|
+
event listener method, listen for a click,
|
|
972
|
+
|
|
973
|
+
00:26:17.360 --> 00:26:26.400
|
|
974
|
+
and then call a function called add new bookmark
|
|
975
|
+
event handler. And this is a function we have not
|
|
976
|
+
|
|
977
|
+
00:26:26.400 --> 00:26:33.360
|
|
978
|
+
coded yet. So to make this function work, we're
|
|
979
|
+
going to have to do the following. We're probably
|
|
980
|
+
|
|
981
|
+
00:26:33.360 --> 00:26:40.800
|
|
982
|
+
going to have to figure out the timestamp of the
|
|
983
|
+
video at which point someone presses the button.
|
|
984
|
+
|
|
985
|
+
00:26:40.800 --> 00:26:45.440
|
|
986
|
+
This is basically going to help us figure
|
|
987
|
+
out what our bookmark should be saved as in
|
|
988
|
+
|
|
989
|
+
00:26:45.440 --> 00:26:50.000
|
|
990
|
+
storage according to its timestamp. So how
|
|
991
|
+
are we going to do that? How are we going
|
|
992
|
+
|
|
993
|
+
00:26:50.000 --> 00:26:55.520
|
|
994
|
+
to figure out the YouTube video timestamp.
|
|
995
|
+
Again, YouTube makes this pretty accessible,
|
|
996
|
+
|
|
997
|
+
00:26:56.080 --> 00:27:02.160
|
|
998
|
+
it can be found as an attribute. So what we're
|
|
999
|
+
going to want to do is grab the YouTube player.
|
|
1000
|
+
|
|
1001
|
+
00:27:03.120 --> 00:27:08.960
|
|
1002
|
+
And we already have a global variable that has
|
|
1003
|
+
it. But I'm just going to grab it again. So we can
|
|
1004
|
+
|
|
1005
|
+
00:27:08.960 --> 00:27:16.240
|
|
1006
|
+
see how to do this in the console, I'm going to
|
|
1007
|
+
create a YouTube player variable in our console.
|
|
1008
|
+
|
|
1009
|
+
00:27:16.240 --> 00:27:23.760
|
|
1010
|
+
Okay, now we have it saved. And then on YouTube
|
|
1011
|
+
player, there's going to be a property called
|
|
1012
|
+
|
|
1013
|
+
00:27:23.760 --> 00:27:32.480
|
|
1014
|
+
current time. And it's going to give us the
|
|
1015
|
+
current time in seconds. And in order for us to
|
|
1016
|
+
|
|
1017
|
+
00:27:32.480 --> 00:27:39.360
|
|
1018
|
+
save our bookmark, according to hours, minutes
|
|
1019
|
+
seconds, we're probably going to also have to
|
|
1020
|
+
|
|
1021
|
+
00:27:39.360 --> 00:27:47.840
|
|
1022
|
+
create a function that converts seconds into a
|
|
1023
|
+
standard time of how it's displayed in YouTube.
|
|
1024
|
+
|
|
1025
|
+
00:27:49.120 --> 00:27:54.960
|
|
1026
|
+
So let's go ahead and start with all those
|
|
1027
|
+
things. We're gonna go ahead and add the function,
|
|
1028
|
+
|
|
1029
|
+
00:27:54.960 --> 00:28:06.000
|
|
1030
|
+
add new bookmark event handler. And we're going
|
|
1031
|
+
to use the exact property we saw in our console,
|
|
1032
|
+
|
|
1033
|
+
00:28:07.360 --> 00:28:13.440
|
|
1034
|
+
YouTube player dot current time, which is going to
|
|
1035
|
+
give us the current time. And we're going to say
|
|
1036
|
+
|
|
1037
|
+
00:28:13.440 --> 00:28:20.000
|
|
1038
|
+
okay, now, this is only called when a new bookmark
|
|
1039
|
+
is made. So let's create a new bookmark variable.
|
|
1040
|
+
|
|
1041
|
+
00:28:21.920 --> 00:28:28.800
|
|
1042
|
+
And this is going to be an object that has
|
|
1043
|
+
the time of the bookmark and a description.
|
|
1044
|
+
|
|
1045
|
+
00:28:29.760 --> 00:28:34.880
|
|
1046
|
+
And the description is just going to end up
|
|
1047
|
+
being the title that's going to be displayed
|
|
1048
|
+
|
|
1049
|
+
00:28:35.600 --> 00:28:41.840
|
|
1050
|
+
in the Chrome extension. So it's going to be
|
|
1051
|
+
a dynamic description and skins a bookmark at
|
|
1052
|
+
|
|
1053
|
+
00:28:43.440 --> 00:28:49.920
|
|
1054
|
+
current time. However, the problem is that
|
|
1055
|
+
this is in seconds, as we said before,
|
|
1056
|
+
|
|
1057
|
+
00:28:49.920 --> 00:28:54.320
|
|
1058
|
+
so we're going to have to convert this. So
|
|
1059
|
+
we're going to use a function called get time.
|
|
1060
|
+
|
|
1061
|
+
00:28:56.720 --> 00:29:01.680
|
|
1062
|
+
I'm just going to insert it using pieces. So I'm
|
|
1063
|
+
going to do is go over to this time function here.
|
|
1064
|
+
|
|
1065
|
+
00:29:02.960 --> 00:29:11.360
|
|
1066
|
+
Insert snippet. And there it is. So now I'm
|
|
1067
|
+
able to convert my seconds into time. And then
|
|
1068
|
+
|
|
1069
|
+
00:29:11.360 --> 00:29:14.800
|
|
1070
|
+
the last thing I want to do here
|
|
1071
|
+
is sync it to Chrome Storage.
|
|
1072
|
+
|
|
1073
|
+
00:29:16.000 --> 00:29:23.200
|
|
1074
|
+
And what this is going to do is set Chrome storage
|
|
1075
|
+
with each bookmark. So basically, each video,
|
|
1076
|
+
|
|
1077
|
+
00:29:23.200 --> 00:29:27.040
|
|
1078
|
+
according to its video identification
|
|
1079
|
+
number that we're grabbing from the URL
|
|
1080
|
+
|
|
1081
|
+
00:29:28.080 --> 00:29:35.440
|
|
1082
|
+
will also map back to a set up bookmarks in Chrome
|
|
1083
|
+
Storage. So to do that, we're going to do Chrome
|
|
1084
|
+
|
|
1085
|
+
00:29:35.440 --> 00:29:39.840
|
|
1086
|
+
storage sync. And again, if you're interested in
|
|
1087
|
+
this, you can look in documentation to find out
|
|
1088
|
+
|
|
1089
|
+
00:29:41.040 --> 00:29:47.280
|
|
1090
|
+
what this function takes. Current video, it's
|
|
1091
|
+
important to remember that things need to be
|
|
1092
|
+
|
|
1093
|
+
00:29:47.280 --> 00:29:57.680
|
|
1094
|
+
stored in JSON in Chrome Storage. So I'm going to
|
|
1095
|
+
do JSON stringify. All my current video bookmarks,
|
|
1096
|
+
|
|
1097
|
+
00:29:57.680 --> 00:30:04.000
|
|
1098
|
+
so I'm actually going to add it A variable up here
|
|
1099
|
+
that's going to store all current video bookmarks
|
|
1100
|
+
|
|
1101
|
+
00:30:07.040 --> 00:30:14.080
|
|
1102
|
+
in an array. And I'm going
|
|
1103
|
+
to spread that. So we can
|
|
1104
|
+
|
|
1105
|
+
00:30:15.920 --> 00:30:22.240
|
|
1106
|
+
add a new bookmark to those set of current video
|
|
1107
|
+
bookmarks. And then the last thing I want to do
|
|
1108
|
+
|
|
1109
|
+
00:30:22.240 --> 00:30:27.120
|
|
1110
|
+
here is sort bookmarks by their save
|
|
1111
|
+
timestamp in our Chrome Storage.
|
|
1112
|
+
|
|
1113
|
+
00:30:29.120 --> 00:30:36.560
|
|
1114
|
+
So we're going to sort by time, and this is just
|
|
1115
|
+
coming from this right here, every bookmark is
|
|
1116
|
+
|
|
1117
|
+
00:30:36.560 --> 00:30:44.640
|
|
1118
|
+
going to have a time and a description. So we're
|
|
1119
|
+
going to look at that and sort accordingly. Great.
|
|
1120
|
+
|
|
1121
|
+
00:30:46.880 --> 00:30:52.640
|
|
1122
|
+
Now, if we reload our extension, we're going
|
|
1123
|
+
to see if it works as expected. And the way
|
|
1124
|
+
|
|
1125
|
+
00:30:52.640 --> 00:31:01.680
|
|
1126
|
+
to see that is basically console dot log, this new
|
|
1127
|
+
bookmark, let's do it. Great. That time it worked,
|
|
1128
|
+
|
|
1129
|
+
00:31:01.680 --> 00:31:07.120
|
|
1130
|
+
we just had to give it another reload. And
|
|
1131
|
+
we got a time in seconds and a description.
|
|
1132
|
+
|
|
1133
|
+
00:31:08.400 --> 00:31:13.360
|
|
1134
|
+
Now the final thing I want to do is complete this
|
|
1135
|
+
file before we go to the UI. And we want to make
|
|
1136
|
+
|
|
1137
|
+
00:31:13.360 --> 00:31:18.320
|
|
1138
|
+
this fully functional to fetch all bookmarks when
|
|
1139
|
+
a new video is loaded. To do this, we're going
|
|
1140
|
+
|
|
1141
|
+
00:31:18.320 --> 00:31:24.160
|
|
1142
|
+
to grab asynchronously, all bookmarks from Chrome
|
|
1143
|
+
storage, which means I'm going to write a promise
|
|
1144
|
+
|
|
1145
|
+
00:31:24.160 --> 00:31:28.560
|
|
1146
|
+
that resolves once we retrieve all bookmarks.
|
|
1147
|
+
So that code is going to look like this.
|
|
1148
|
+
|
|
1149
|
+
00:31:29.920 --> 00:31:36.720
|
|
1150
|
+
I'm going to create it at the top here.
|
|
1151
|
+
And I'm going to say const fetch bookmarks.
|
|
1152
|
+
|
|
1153
|
+
00:31:41.920 --> 00:31:48.880
|
|
1154
|
+
And I want to return a promise. So
|
|
1155
|
+
we can resolve this asynchronously.
|
|
1156
|
+
|
|
1157
|
+
00:31:52.240 --> 00:31:56.240
|
|
1158
|
+
And within that promise, I'm going
|
|
1159
|
+
to fetch from Chrome Storage. So
|
|
1160
|
+
|
|
1161
|
+
00:31:57.520 --> 00:32:01.520
|
|
1162
|
+
I'm going to do a Chrome storage
|
|
1163
|
+
sync and we did a set before to
|
|
1164
|
+
|
|
1165
|
+
00:32:01.520 --> 00:32:06.480
|
|
1166
|
+
set Chrome Storage, we're going
|
|
1167
|
+
to get this time our current video
|
|
1168
|
+
|
|
1169
|
+
00:32:10.320 --> 00:32:15.600
|
|
1170
|
+
it takes an object. And we're going to resolve
|
|
1171
|
+
|
|
1172
|
+
00:32:23.840 --> 00:32:34.080
|
|
1173
|
+
to find any bookmarks when indexing
|
|
1174
|
+
using our current video. So
|
|
1175
|
+
|
|
1176
|
+
00:32:38.480 --> 00:32:44.640
|
|
1177
|
+
basically look in storage to see if our current
|
|
1178
|
+
video has any bookmarks, or if it exists in
|
|
1179
|
+
|
|
1180
|
+
00:32:44.640 --> 00:32:50.560
|
|
1181
|
+
storage. That's what's happening right here. If
|
|
1182
|
+
it does exist, we're going to JSON dot parse it
|
|
1183
|
+
|
|
1184
|
+
00:32:50.560 --> 00:32:56.960
|
|
1185
|
+
because we JSON dot Stringify before,
|
|
1186
|
+
if it doesn't, what we want to do is
|
|
1187
|
+
|
|
1188
|
+
00:32:59.680 --> 00:33:07.600
|
|
1189
|
+
return an empty array. And this should work.
|
|
1190
|
+
And we're really only going to add these in
|
|
1191
|
+
|
|
1192
|
+
00:33:07.600 --> 00:33:14.000
|
|
1193
|
+
two places, which will be in our new video
|
|
1194
|
+
loaded function. So we're going to make this
|
|
1195
|
+
|
|
1196
|
+
00:33:14.000 --> 00:33:22.240
|
|
1197
|
+
async. And we're gonna add a fetch bookmarks.
|
|
1198
|
+
So actually, we're just going to add this to
|
|
1199
|
+
|
|
1200
|
+
00:33:22.240 --> 00:33:29.120
|
|
1201
|
+
our current video bookmarks variable.
|
|
1202
|
+
And call a weight fetch bookmarks.
|
|
1203
|
+
|
|
1204
|
+
00:33:31.440 --> 00:33:33.600
|
|
1205
|
+
async await is going to resolve this promise.
|
|
1206
|
+
|
|
1207
|
+
00:33:35.920 --> 00:33:40.560
|
|
1208
|
+
And then the second place we want to add this
|
|
1209
|
+
is to our add new bookmarks event handler.
|
|
1210
|
+
|
|
1211
|
+
00:33:42.400 --> 00:33:47.760
|
|
1212
|
+
To basically handle this case, and make
|
|
1213
|
+
sure we're always using the most up to date
|
|
1214
|
+
|
|
1215
|
+
00:33:49.600 --> 00:33:51.840
|
|
1216
|
+
set of bookmarks when destructuring.
|
|
1217
|
+
|
|
1218
|
+
00:33:54.000 --> 00:34:03.840
|
|
1219
|
+
So we're gonna do current video bookmarks equals
|
|
1220
|
+
the weight, veg bookmarks. And also make this
|
|
1221
|
+
|
|
1222
|
+
00:34:03.840 --> 00:34:12.800
|
|
1223
|
+
async. Awesome. So for right now, we finished
|
|
1224
|
+
everything we need for our content script file,
|
|
1225
|
+
|
|
1226
|
+
00:34:12.800 --> 00:34:16.800
|
|
1227
|
+
obviously, things aren't going to show in the
|
|
1228
|
+
UI. And we could check that out right here.
|
|
1229
|
+
|
|
1230
|
+
00:34:18.000 --> 00:34:22.960
|
|
1231
|
+
And as you can see, there's nothing in the UI
|
|
1232
|
+
because everything we've been doing so far has
|
|
1233
|
+
|
|
1234
|
+
00:34:22.960 --> 00:34:29.520
|
|
1235
|
+
been manipulating the DOM right here to add
|
|
1236
|
+
the icon. Add some logic to get us ready to
|
|
1237
|
+
|
|
1238
|
+
00:34:29.520 --> 00:34:35.520
|
|
1239
|
+
create a UI for our extension. Let's go ahead and
|
|
1240
|
+
start making some UI components show starting out
|
|
1241
|
+
|
|
1242
|
+
00:34:35.520 --> 00:34:39.680
|
|
1243
|
+
with some bookmarks from clicking that addition
|
|
1244
|
+
button in the YouTube player that we added.
|
|
1245
|
+
|
|
1246
|
+
00:34:40.800 --> 00:34:46.000
|
|
1247
|
+
Now, the first thing we need to figure out on any
|
|
1248
|
+
given page is if it's a YouTube video page or not,
|
|
1249
|
+
|
|
1250
|
+
00:34:46.000 --> 00:34:50.480
|
|
1251
|
+
if it is, we're going on one of fetch any
|
|
1252
|
+
bookmarks we may have from Chrome Storage.
|
|
1253
|
+
|
|
1254
|
+
00:34:51.120 --> 00:34:56.320
|
|
1255
|
+
And if it's not, we'll just want to display
|
|
1256
|
+
some messaging saying it's not a YouTube page.
|
|
1257
|
+
|
|
1258
|
+
00:34:56.320 --> 00:35:01.680
|
|
1259
|
+
If you open the Chrome extension on a
|
|
1260
|
+
page that is not YouTube. So to do this,
|
|
1261
|
+
|
|
1262
|
+
00:35:01.680 --> 00:35:08.080
|
|
1263
|
+
we're going to add a utility function that's
|
|
1264
|
+
going to allow us to decipher that logic.
|
|
1265
|
+
|
|
1266
|
+
00:35:08.080 --> 00:35:14.000
|
|
1267
|
+
So we're actually going to grab our utility
|
|
1268
|
+
function to find the active tab that the user is
|
|
1269
|
+
|
|
1270
|
+
00:35:14.000 --> 00:35:20.640
|
|
1271
|
+
on through Google Chrome documentation. I'm going
|
|
1272
|
+
to go ahead and use this example right here, which
|
|
1273
|
+
|
|
1274
|
+
00:35:21.200 --> 00:35:26.960
|
|
1275
|
+
helps us retrieved a currently focused tab
|
|
1276
|
+
from the Chrome documentation. And since I
|
|
1277
|
+
|
|
1278
|
+
00:35:26.960 --> 00:35:31.520
|
|
1279
|
+
have the google chrome pieces extension over
|
|
1280
|
+
every codeblock, whether it's in documentation
|
|
1281
|
+
|
|
1282
|
+
00:35:31.520 --> 00:35:36.880
|
|
1283
|
+
or Stack Overflow, I'm able to directly
|
|
1284
|
+
save on pieces with this icon that shows up
|
|
1285
|
+
|
|
1286
|
+
00:35:37.440 --> 00:35:41.840
|
|
1287
|
+
at the top right of any code block, I'm going
|
|
1288
|
+
to go ahead and save it. And then I'm going
|
|
1289
|
+
|
|
1290
|
+
00:35:41.840 --> 00:35:48.320
|
|
1291
|
+
to go back to my VS code and refresh my pieces
|
|
1292
|
+
tree, I can go ahead and insert this snippet,
|
|
1293
|
+
|
|
1294
|
+
00:35:48.320 --> 00:35:54.240
|
|
1295
|
+
which is the newest one, and I'm just going
|
|
1296
|
+
to rename this snippet to active tab Chrome.
|
|
1297
|
+
|
|
1298
|
+
00:35:56.400 --> 00:36:02.320
|
|
1299
|
+
Amazing and pieces automatically classified this
|
|
1300
|
+
as JavaScript, because it was able to decipher
|
|
1301
|
+
|
|
1302
|
+
00:36:02.320 --> 00:36:08.320
|
|
1303
|
+
that from some machine learning. I'm gonna go
|
|
1304
|
+
ahead and delete this background.js comment.
|
|
1305
|
+
|
|
1306
|
+
00:36:09.440 --> 00:36:15.840
|
|
1307
|
+
And awesome, we now have a function that grabs
|
|
1308
|
+
the current tab. But also, I want to make sure
|
|
1309
|
+
|
|
1310
|
+
00:36:15.840 --> 00:36:21.120
|
|
1311
|
+
I'm exporting this function. So I'm going
|
|
1312
|
+
to add export. And then what I want to do is
|
|
1313
|
+
|
|
1314
|
+
00:36:21.120 --> 00:36:26.720
|
|
1315
|
+
open up the pop up.js file. And over here,
|
|
1316
|
+
we're going to want to import that function
|
|
1317
|
+
|
|
1318
|
+
00:36:26.720 --> 00:36:34.240
|
|
1319
|
+
at the very top. So we can use it here.
|
|
1320
|
+
So I'm going to import Get active tab URL
|
|
1321
|
+
|
|
1322
|
+
00:36:36.720 --> 00:36:43.440
|
|
1323
|
+
from utils dot j, s, and I actually
|
|
1324
|
+
don't think the documentation called
|
|
1325
|
+
|
|
1326
|
+
00:36:43.440 --> 00:36:47.760
|
|
1327
|
+
it this. So I'm going to go ahead and
|
|
1328
|
+
change the function name, so it matches.
|
|
1329
|
+
|
|
1330
|
+
00:36:49.760 --> 00:36:58.800
|
|
1331
|
+
So go to utils.js. Change that thought,
|
|
1332
|
+
awesome. Now, the event we want to listen
|
|
1333
|
+
|
|
1334
|
+
00:36:58.800 --> 00:37:03.920
|
|
1335
|
+
to when opening the pop up.js file is the DOM
|
|
1336
|
+
content loaded event, which is right here.
|
|
1337
|
+
|
|
1338
|
+
00:37:04.720 --> 00:37:10.480
|
|
1339
|
+
This event is a native window event that fires
|
|
1340
|
+
when an HTML document has initially been loaded.
|
|
1341
|
+
|
|
1342
|
+
00:37:10.480 --> 00:37:15.120
|
|
1343
|
+
It's essentially when we want to load all our
|
|
1344
|
+
bookmarks and show them. So we're going to
|
|
1345
|
+
|
|
1346
|
+
00:37:15.120 --> 00:37:21.840
|
|
1347
|
+
type the following to do so what we're going
|
|
1348
|
+
to do is grab our active tab function first.
|
|
1349
|
+
|
|
1350
|
+
00:37:22.400 --> 00:37:30.080
|
|
1351
|
+
And we're going to look at the user's current
|
|
1352
|
+
active tab, which we already have the function
|
|
1353
|
+
|
|
1354
|
+
00:37:30.080 --> 00:37:37.680
|
|
1355
|
+
for from in the utiles. It's an async function.
|
|
1356
|
+
So we're going to async await this. And then after
|
|
1357
|
+
|
|
1358
|
+
00:37:37.680 --> 00:37:43.680
|
|
1359
|
+
that, we're going to grab the query parameters
|
|
1360
|
+
to help us identify the video. If you remember,
|
|
1361
|
+
|
|
1362
|
+
00:37:44.720 --> 00:37:51.280
|
|
1363
|
+
each YouTube video has a unique identifier. After
|
|
1364
|
+
the question mark, where the query parameter,
|
|
1365
|
+
|
|
1366
|
+
00:37:52.960 --> 00:37:59.760
|
|
1367
|
+
we're going to grab that, we're going to use a
|
|
1368
|
+
URL search params to be able to get the unique
|
|
1369
|
+
|
|
1370
|
+
00:37:59.760 --> 00:38:09.120
|
|
1371
|
+
identifier for each video. And to get the
|
|
1372
|
+
unique identifier, we're going to create it
|
|
1373
|
+
|
|
1374
|
+
00:38:09.120 --> 00:38:17.360
|
|
1375
|
+
current video variable and do URL parameters
|
|
1376
|
+
dot get V. And this is just based off of
|
|
1377
|
+
|
|
1378
|
+
00:38:17.360 --> 00:38:22.880
|
|
1379
|
+
what the YouTube video URLs look
|
|
1380
|
+
like. Now, our active tab URL
|
|
1381
|
+
|
|
1382
|
+
00:38:24.880 --> 00:38:34.160
|
|
1383
|
+
should have youtube.com/watch Because any specific
|
|
1384
|
+
YouTube video always has this in its URL. And
|
|
1385
|
+
|
|
1386
|
+
00:38:34.160 --> 00:38:39.680
|
|
1387
|
+
we want to make sure we're watching a YouTube
|
|
1388
|
+
video when our Chrome Extension has any logic
|
|
1389
|
+
|
|
1390
|
+
00:38:39.680 --> 00:38:44.480
|
|
1391
|
+
with bookmarks. And we want to make sure
|
|
1392
|
+
this current video variable is truthy
|
|
1393
|
+
|
|
1394
|
+
00:38:44.480 --> 00:38:51.120
|
|
1395
|
+
meaning is get actually returned something
|
|
1396
|
+
other than undefined or any falsie value.
|
|
1397
|
+
|
|
1398
|
+
00:38:54.160 --> 00:39:00.160
|
|
1399
|
+
And then what we want to do is we want
|
|
1400
|
+
to get any current video bookmarks from
|
|
1401
|
+
|
|
1402
|
+
00:39:00.160 --> 00:39:06.000
|
|
1403
|
+
Chrome storage. If you remember, we're setting
|
|
1404
|
+
Chrome storage with the current video as a key
|
|
1405
|
+
|
|
1406
|
+
00:39:06.720 --> 00:39:12.640
|
|
1407
|
+
and then all the bookmarks as a value that is
|
|
1408
|
+
JSON ified. And in order for us to retrieve those
|
|
1409
|
+
|
|
1410
|
+
00:39:12.640 --> 00:39:17.760
|
|
1411
|
+
bookmarks, we need to use a Chrome Storage API
|
|
1412
|
+
to get them. So to do that, we're going to grab
|
|
1413
|
+
|
|
1414
|
+
00:39:19.280 --> 00:39:26.640
|
|
1415
|
+
the video bookmarks using Chrome storage sync get.
|
|
1416
|
+
And we're going to get it with the current video
|
|
1417
|
+
|
|
1418
|
+
00:39:26.640 --> 00:39:32.160
|
|
1419
|
+
unique identifier, which is the YouTube
|
|
1420
|
+
videos unique identifier in the URL.
|
|
1421
|
+
|
|
1422
|
+
00:39:34.480 --> 00:39:41.440
|
|
1423
|
+
And then, we are going to set a current video
|
|
1424
|
+
bookmarks variable which is going to contain
|
|
1425
|
+
|
|
1426
|
+
00:39:41.440 --> 00:39:46.800
|
|
1427
|
+
all those JSON ified current videos. And in
|
|
1428
|
+
order for us to pass this to any function
|
|
1429
|
+
|
|
1430
|
+
00:39:46.800 --> 00:39:55.360
|
|
1431
|
+
or write some custom logic to show bookmarks,
|
|
1432
|
+
we're going to have to JSON dot parse any
|
|
1433
|
+
|
|
1434
|
+
00:39:55.360 --> 00:39:59.760
|
|
1435
|
+
bookmarks that are saved in Chrome Storage since
|
|
1436
|
+
it's in JSON, and we can't really work with that.
|
|
1437
|
+
|
|
1438
|
+
00:40:00.960 --> 00:40:07.760
|
|
1439
|
+
But if there are no bookmarks or chrome searches
|
|
1440
|
+
and return anything, we're just going to want to
|
|
1441
|
+
|
|
1442
|
+
00:40:07.760 --> 00:40:14.880
|
|
1443
|
+
return an empty array. Now, we're going to have
|
|
1444
|
+
to pass this over to the view bookmarks function,
|
|
1445
|
+
|
|
1446
|
+
00:40:15.680 --> 00:40:20.320
|
|
1447
|
+
which is basically going to help us
|
|
1448
|
+
view any bookmarks in our extension,
|
|
1449
|
+
|
|
1450
|
+
00:40:21.040 --> 00:40:26.880
|
|
1451
|
+
that Chrome Storage dot get returns. But before
|
|
1452
|
+
that, I'm just going to put a comment right
|
|
1453
|
+
|
|
1454
|
+
00:40:26.880 --> 00:40:32.960
|
|
1455
|
+
here. So we remember, we want to handle this
|
|
1456
|
+
else condition, which basically is for the
|
|
1457
|
+
|
|
1458
|
+
00:40:32.960 --> 00:40:39.520
|
|
1459
|
+
scenario where we're not on a youtube.com video
|
|
1460
|
+
page, or current video returns a falsie value.
|
|
1461
|
+
|
|
1462
|
+
00:40:40.560 --> 00:40:46.320
|
|
1463
|
+
So what we're going to want to do is add a message
|
|
1464
|
+
that says this is not a YouTube video page.
|
|
1465
|
+
|
|
1466
|
+
00:40:47.200 --> 00:40:52.080
|
|
1467
|
+
And let's just go back to chrome to
|
|
1468
|
+
look at what that might look like.
|
|
1469
|
+
|
|
1470
|
+
00:40:54.000 --> 00:41:02.480
|
|
1471
|
+
So this is our UI Currently, we have this
|
|
1472
|
+
container class right here that encapsulates
|
|
1473
|
+
|
|
1474
|
+
00:41:03.040 --> 00:41:08.320
|
|
1475
|
+
and will eventually encapsulate all the bookmarks
|
|
1476
|
+
we have, it has this container class name in it,
|
|
1477
|
+
|
|
1478
|
+
00:41:09.600 --> 00:41:15.040
|
|
1479
|
+
what we're going to want to do is get that class
|
|
1480
|
+
name. So we're just going to do this in the
|
|
1481
|
+
|
|
1482
|
+
00:41:15.040 --> 00:41:22.560
|
|
1483
|
+
console before we actually do in code just to make
|
|
1484
|
+
sure it works. The class was called container. And
|
|
1485
|
+
|
|
1486
|
+
00:41:22.560 --> 00:41:27.440
|
|
1487
|
+
that's just from the CSS in the boilerplate,
|
|
1488
|
+
so you don't have to worry about it, or the
|
|
1489
|
+
|
|
1490
|
+
00:41:27.440 --> 00:41:34.000
|
|
1491
|
+
HTML or other. So when we wrote this document that
|
|
1492
|
+
get elements by class name container, and then
|
|
1493
|
+
|
|
1494
|
+
00:41:34.000 --> 00:41:43.280
|
|
1495
|
+
grab the first element in the HTML collection, we
|
|
1496
|
+
get this element right here, which is containing
|
|
1497
|
+
|
|
1498
|
+
00:41:43.280 --> 00:41:51.360
|
|
1499
|
+
all these other elements within it. And what we
|
|
1500
|
+
want to do here is basically specify in the HTML
|
|
1501
|
+
|
|
1502
|
+
00:41:54.800 --> 00:41:59.280
|
|
1503
|
+
on pages that are not youtube.com. So
|
|
1504
|
+
this is actually a YouTube video page.
|
|
1505
|
+
|
|
1506
|
+
00:42:00.000 --> 00:42:03.360
|
|
1507
|
+
We don't want to display this message. But I
|
|
1508
|
+
just want to show how this is going to look,
|
|
1509
|
+
|
|
1510
|
+
00:42:04.400 --> 00:42:06.240
|
|
1511
|
+
we're going to want to put a new div class
|
|
1512
|
+
|
|
1513
|
+
00:42:11.760 --> 00:42:14.400
|
|
1514
|
+
that says, This is not a YouTube video page.
|
|
1515
|
+
|
|
1516
|
+
00:42:15.600 --> 00:42:19.680
|
|
1517
|
+
And let's just see if that works. Will this
|
|
1518
|
+
change the extension the way we want it to?
|
|
1519
|
+
|
|
1520
|
+
00:42:24.560 --> 00:42:27.600
|
|
1521
|
+
Container is not. So what we need to do over here
|
|
1522
|
+
|
|
1523
|
+
00:42:29.440 --> 00:42:33.920
|
|
1524
|
+
is actually encapsulate this in a variable.
|
|
1525
|
+
We're gonna set this equal to container.
|
|
1526
|
+
|
|
1527
|
+
00:42:35.520 --> 00:42:41.760
|
|
1528
|
+
And now let's try that. And change the extension
|
|
1529
|
+
to show that this is not a YouTube video page.
|
|
1530
|
+
|
|
1531
|
+
00:42:42.720 --> 00:42:45.760
|
|
1532
|
+
So the way we're going to do
|
|
1533
|
+
this dynamically in our code
|
|
1534
|
+
|
|
1535
|
+
00:42:45.760 --> 00:42:49.840
|
|
1536
|
+
is basically put all the code we just
|
|
1537
|
+
put in our console to test this out
|
|
1538
|
+
|
|
1539
|
+
00:42:50.400 --> 00:42:55.920
|
|
1540
|
+
within our else conditions. So every time we're
|
|
1541
|
+
not on a YouTube video page, or this returns a
|
|
1542
|
+
|
|
1543
|
+
00:42:55.920 --> 00:43:01.680
|
|
1544
|
+
falsie value, we want to show that this is
|
|
1545
|
+
not a YouTube video page when we try to open
|
|
1546
|
+
|
|
1547
|
+
00:43:01.680 --> 00:43:06.880
|
|
1548
|
+
up the Chrome extension in those scenarios. So
|
|
1549
|
+
we're gonna say const container equals document
|
|
1550
|
+
|
|
1551
|
+
00:43:06.880 --> 00:43:15.040
|
|
1552
|
+
dot get elements by class name, right there.
|
|
1553
|
+
Grab that container class, first element.
|
|
1554
|
+
|
|
1555
|
+
00:43:17.760 --> 00:43:25.200
|
|
1556
|
+
And then set the inner HTML, set that equal to div
|
|
1557
|
+
class equals title, title, just add some styling,
|
|
1558
|
+
|
|
1559
|
+
00:43:25.760 --> 00:43:28.560
|
|
1560
|
+
that's going to make it look
|
|
1561
|
+
slightly nicer. There's nothing
|
|
1562
|
+
|
|
1563
|
+
00:43:29.120 --> 00:43:31.280
|
|
1564
|
+
super special about the styling I have.
|
|
1565
|
+
|
|
1566
|
+
00:43:35.360 --> 00:43:40.240
|
|
1567
|
+
And since we tested it, there shouldn't be
|
|
1568
|
+
really any surprises here, it should pretty much
|
|
1569
|
+
|
|
1570
|
+
00:43:40.240 --> 00:43:45.760
|
|
1571
|
+
work as expected. So let's go ahead
|
|
1572
|
+
and give this extension a reload.
|
|
1573
|
+
|
|
1574
|
+
00:43:47.600 --> 00:43:52.880
|
|
1575
|
+
It shouldn't show the message for this page.
|
|
1576
|
+
It doesn't. But if we go to a non YouTube page,
|
|
1577
|
+
|
|
1578
|
+
00:43:53.520 --> 00:43:58.000
|
|
1579
|
+
it's gonna say this is not a YouTube
|
|
1580
|
+
video page. Amazing. So let's go back to
|
|
1581
|
+
|
|
1582
|
+
00:43:59.520 --> 00:44:03.280
|
|
1583
|
+
our code. And we're going to want to
|
|
1584
|
+
write this view bookmarks function.
|
|
1585
|
+
|
|
1586
|
+
00:44:03.280 --> 00:44:09.520
|
|
1587
|
+
So if it does meet the conditions of being on
|
|
1588
|
+
a youtube.com/watch page, and as you can see,
|
|
1589
|
+
|
|
1590
|
+
00:44:10.640 --> 00:44:19.320
|
|
1591
|
+
that's from any page that has a video page,
|
|
1592
|
+
it has youtube.com/watch on it. And your
|
|
1593
|
+
|
|
1594
|
+
00:44:19.840 --> 00:44:27.840
|
|
1595
|
+
URL params dot get the return something so it's
|
|
1596
|
+
a truthy value, we're going to want to view the
|
|
1597
|
+
|
|
1598
|
+
00:44:27.840 --> 00:44:33.040
|
|
1599
|
+
bookmarks associated with that video. So let's
|
|
1600
|
+
go ahead and call the view bookmarks function
|
|
1601
|
+
|
|
1602
|
+
00:44:34.320 --> 00:44:39.680
|
|
1603
|
+
and pass it all the current video bookmarks.
|
|
1604
|
+
And we're gonna go ahead and write the logic
|
|
1605
|
+
|
|
1606
|
+
00:44:39.680 --> 00:44:44.720
|
|
1607
|
+
that's going to help us populate the UI with all
|
|
1608
|
+
the bookmarks we grabbed from Chrome Storage.
|
|
1609
|
+
|
|
1610
|
+
00:44:46.240 --> 00:44:50.720
|
|
1611
|
+
So to do that, we're going
|
|
1612
|
+
to pass it current bookmarks.
|
|
1613
|
+
|
|
1614
|
+
00:44:54.000 --> 00:44:58.560
|
|
1615
|
+
And we're going to set a default argument of an
|
|
1616
|
+
empty array just in case nothing is passed to it.
|
|
1617
|
+
|
|
1618
|
+
00:44:59.120 --> 00:45:08.480
|
|
1619
|
+
It's just going To return or show no bookmarks,
|
|
1620
|
+
and we're going to grab a bookmark element.
|
|
1621
|
+
|
|
1622
|
+
00:45:10.880 --> 00:45:17.200
|
|
1623
|
+
Again, this is just from the HTML that I have
|
|
1624
|
+
given you. So it's not anything you need to
|
|
1625
|
+
|
|
1626
|
+
00:45:17.200 --> 00:45:23.280
|
|
1627
|
+
worry about. If you want to try this out on your
|
|
1628
|
+
own, you could try it out in the console. Just
|
|
1629
|
+
|
|
1630
|
+
00:45:23.280 --> 00:45:27.360
|
|
1631
|
+
to save some time here, I'm just going to write
|
|
1632
|
+
the code here. And you can go ahead and copy it.
|
|
1633
|
+
|
|
1634
|
+
00:45:28.560 --> 00:45:33.680
|
|
1635
|
+
But again, it's just knowing how to work with
|
|
1636
|
+
the DOM and inspecting the elements to figure out
|
|
1637
|
+
|
|
1638
|
+
00:45:34.400 --> 00:45:35.120
|
|
1639
|
+
how to do this.
|
|
1640
|
+
|
|
1641
|
+
00:45:37.840 --> 00:45:43.600
|
|
1642
|
+
What I'm doing right here is basically saying,
|
|
1643
|
+
Okay, if there are any bookmarks, let's just set
|
|
1644
|
+
|
|
1645
|
+
00:45:43.600 --> 00:45:49.280
|
|
1646
|
+
it to nothing. So we're not displaying anything,
|
|
1647
|
+
we're going to reset the whole thing, since we're
|
|
1648
|
+
|
|
1649
|
+
00:45:49.280 --> 00:45:54.240
|
|
1650
|
+
calling this function to view bookmarks. And we're
|
|
1651
|
+
going to have new bookmarks being passed in, which
|
|
1652
|
+
|
|
1653
|
+
00:45:54.240 --> 00:46:00.480
|
|
1654
|
+
is the current bookmarks. And we're gonna say if
|
|
1655
|
+
the current bookmarks length is greater than zero,
|
|
1656
|
+
|
|
1657
|
+
00:46:00.480 --> 00:46:05.920
|
|
1658
|
+
meaning if there are current bookmarks,
|
|
1659
|
+
and it's just not an empty array.
|
|
1660
|
+
|
|
1661
|
+
00:46:08.160 --> 00:46:11.360
|
|
1662
|
+
Let's go ahead and iterate
|
|
1663
|
+
over all those bookmarks,
|
|
1664
|
+
|
|
1665
|
+
00:46:11.360 --> 00:46:18.400
|
|
1666
|
+
and show them in our UI. So to do that, we're
|
|
1667
|
+
going to iterate over every bookmark in a loop.
|
|
1668
|
+
|
|
1669
|
+
00:46:22.960 --> 00:46:28.160
|
|
1670
|
+
And then, we're going to grab the bookmark
|
|
1671
|
+
through indexing, so current bookmarks.
|
|
1672
|
+
|
|
1673
|
+
00:46:29.920 --> 00:46:35.760
|
|
1674
|
+
With whatever iteration we are in the loop. And
|
|
1675
|
+
then what we're going to have to do from here
|
|
1676
|
+
|
|
1677
|
+
00:46:36.480 --> 00:46:41.840
|
|
1678
|
+
is call another function, add new bookmark,
|
|
1679
|
+
which is going to add a new bookmark row to
|
|
1680
|
+
|
|
1681
|
+
00:46:42.720 --> 00:46:48.400
|
|
1682
|
+
our pop up, I'm going to go ahead and remove this
|
|
1683
|
+
comment. And we're going to add a new bookmark,
|
|
1684
|
+
|
|
1685
|
+
00:46:49.600 --> 00:46:52.480
|
|
1686
|
+
we're going to pass it the bookmark
|
|
1687
|
+
element up here, which is going to
|
|
1688
|
+
|
|
1689
|
+
00:46:52.480 --> 00:46:56.400
|
|
1690
|
+
populate all our bookmarks, well, it's
|
|
1691
|
+
going to be where we add each of our rows.
|
|
1692
|
+
|
|
1693
|
+
00:46:59.120 --> 00:47:03.680
|
|
1694
|
+
And I'm going to pass it each specific bookmark.
|
|
1695
|
+
So we're going to add one bookmark at a time and
|
|
1696
|
+
|
|
1697
|
+
00:47:03.680 --> 00:47:09.760
|
|
1698
|
+
call this function every time we're adding a
|
|
1699
|
+
bookmark. But before that, what we want to do
|
|
1700
|
+
|
|
1701
|
+
00:47:09.760 --> 00:47:14.960
|
|
1702
|
+
is if there are no bookmarks to show meaning,
|
|
1703
|
+
current bookmarks is just an empty array.
|
|
1704
|
+
|
|
1705
|
+
00:47:17.280 --> 00:47:20.720
|
|
1706
|
+
We're going to want a message that
|
|
1707
|
+
says there are no bookmarks here.
|
|
1708
|
+
|
|
1709
|
+
00:47:20.720 --> 00:47:24.720
|
|
1710
|
+
So we're going to set a message using italics.
|
|
1711
|
+
|
|
1712
|
+
00:47:30.480 --> 00:47:42.640
|
|
1713
|
+
Saying no bookmarks. To show before we move
|
|
1714
|
+
on and add individual bookmarks to our pop up,
|
|
1715
|
+
|
|
1716
|
+
00:47:42.640 --> 00:47:47.840
|
|
1717
|
+
let's go ahead and check if this condition
|
|
1718
|
+
works. Where there's no bookmarks to show and
|
|
1719
|
+
|
|
1720
|
+
00:47:47.840 --> 00:47:51.760
|
|
1721
|
+
since we haven't added any bookmarks to this
|
|
1722
|
+
YouTube video that I'm looking at right now,
|
|
1723
|
+
|
|
1724
|
+
00:47:51.760 --> 00:47:58.000
|
|
1725
|
+
it should work, I want to go ahead and reload my
|
|
1726
|
+
extension. Yep, there it is no bookmarks to show.
|
|
1727
|
+
|
|
1728
|
+
00:47:59.920 --> 00:48:07.280
|
|
1729
|
+
Amazing. So now we're going to want to finally
|
|
1730
|
+
handle the case where we have bookmarks to show
|
|
1731
|
+
|
|
1732
|
+
00:48:07.920 --> 00:48:14.640
|
|
1733
|
+
and this is going to allow us to start seeing
|
|
1734
|
+
bookmarks in our UI. So the first thing we're
|
|
1735
|
+
|
|
1736
|
+
00:48:14.640 --> 00:48:19.840
|
|
1737
|
+
going to do is go to our add new bookmark
|
|
1738
|
+
function. And it's going to accept bookmark
|
|
1739
|
+
|
|
1740
|
+
00:48:22.640 --> 00:48:29.440
|
|
1741
|
+
bookmarks element, and it's
|
|
1742
|
+
going to accept a bookmark.
|
|
1743
|
+
|
|
1744
|
+
00:48:31.040 --> 00:48:36.000
|
|
1745
|
+
And then what we're going to do from here
|
|
1746
|
+
is we're going to create two elements. So
|
|
1747
|
+
|
|
1748
|
+
00:48:36.000 --> 00:48:42.320
|
|
1749
|
+
one element is going to be for the title, which
|
|
1750
|
+
is going to display in the UI of each bookmark.
|
|
1751
|
+
|
|
1752
|
+
00:48:43.040 --> 00:48:48.960
|
|
1753
|
+
And then one element is going to be the whole
|
|
1754
|
+
bookmark element that will contain the title
|
|
1755
|
+
|
|
1756
|
+
00:48:49.520 --> 00:48:54.960
|
|
1757
|
+
will contain the delete button and will contain
|
|
1758
|
+
the play button. So let's go ahead and create
|
|
1759
|
+
|
|
1760
|
+
00:48:54.960 --> 00:49:09.760
|
|
1761
|
+
the bookmark title element. And then after
|
|
1762
|
+
this one, we're also going to create the new
|
|
1763
|
+
|
|
1764
|
+
00:49:09.760 --> 00:49:19.840
|
|
1765
|
+
bookmark element, which will encapsulate all these
|
|
1766
|
+
other elements that are part of a bookmark row.
|
|
1767
|
+
|
|
1768
|
+
00:49:24.080 --> 00:49:29.600
|
|
1769
|
+
From here, for bookmark title element, we're
|
|
1770
|
+
going to want to display what the bookmark
|
|
1771
|
+
|
|
1772
|
+
00:49:29.600 --> 00:49:35.920
|
|
1773
|
+
is and give it a title. So we actually already
|
|
1774
|
+
created the title. The title is the description
|
|
1775
|
+
|
|
1776
|
+
00:49:35.920 --> 00:49:41.200
|
|
1777
|
+
of the bookmark. If you remember in our bookmark
|
|
1778
|
+
object, there's a timestamp and a description.
|
|
1779
|
+
|
|
1780
|
+
00:49:41.200 --> 00:49:46.480
|
|
1781
|
+
So we're gonna set our text content to the
|
|
1782
|
+
description, which is bookmark dot description.
|
|
1783
|
+
|
|
1784
|
+
00:49:48.720 --> 00:49:55.680
|
|
1785
|
+
And then our class name is going to be bookmark
|
|
1786
|
+
title element dot class name, and that will be
|
|
1787
|
+
|
|
1788
|
+
00:49:55.680 --> 00:50:03.040
|
|
1789
|
+
set equal to bookmark title and this is just
|
|
1790
|
+
going to add some In CSS, that is already in
|
|
1791
|
+
|
|
1792
|
+
00:50:03.040 --> 00:50:09.040
|
|
1793
|
+
our boilerplate code. Now for the general
|
|
1794
|
+
component that is going to encapsulate all
|
|
1795
|
+
|
|
1796
|
+
00:50:09.040 --> 00:50:13.040
|
|
1797
|
+
the play button, the title, a delete
|
|
1798
|
+
button, anything else you might want to add,
|
|
1799
|
+
|
|
1800
|
+
00:50:14.160 --> 00:50:20.880
|
|
1801
|
+
we're going to do a couple things, the first
|
|
1802
|
+
thing we're going to do is give it an ID of
|
|
1803
|
+
|
|
1804
|
+
00:50:20.880 --> 00:50:28.000
|
|
1805
|
+
bookmark element, or bookmark with the
|
|
1806
|
+
bookmark time, and this is going to guarantee a
|
|
1807
|
+
|
|
1808
|
+
00:50:28.960 --> 00:50:38.080
|
|
1809
|
+
unique ID for each element that is a row. So if
|
|
1810
|
+
you save any bookmark, what's gonna happen is
|
|
1811
|
+
|
|
1812
|
+
00:50:38.080 --> 00:50:42.320
|
|
1813
|
+
there's going to be a row associated with each
|
|
1814
|
+
bookmark, which is our new bookmark element.
|
|
1815
|
+
|
|
1816
|
+
00:50:43.280 --> 00:50:47.840
|
|
1817
|
+
And there's going to be an ID set for that
|
|
1818
|
+
row, which will be the bookmark along with
|
|
1819
|
+
|
|
1820
|
+
00:50:47.840 --> 00:50:53.680
|
|
1821
|
+
the time and they'll help us uniquely
|
|
1822
|
+
identify any specific row in the UI.
|
|
1823
|
+
|
|
1824
|
+
00:50:53.680 --> 00:51:00.560
|
|
1825
|
+
And that's later we're going to be used to delete
|
|
1826
|
+
elements when we're deleting a specific bookmark.
|
|
1827
|
+
|
|
1828
|
+
00:51:02.640 --> 00:51:06.320
|
|
1829
|
+
And then we're going to set a class name,
|
|
1830
|
+
which was is going to help with some styling,
|
|
1831
|
+
|
|
1832
|
+
00:51:07.120 --> 00:51:12.480
|
|
1833
|
+
that's going to be set to a bookmark
|
|
1834
|
+
class. And then we're going to set
|
|
1835
|
+
|
|
1836
|
+
00:51:12.480 --> 00:51:18.160
|
|
1837
|
+
an attribute which is going to help us
|
|
1838
|
+
with playing a video. Because basically,
|
|
1839
|
+
|
|
1840
|
+
00:51:18.160 --> 00:51:24.000
|
|
1841
|
+
we're going to want to know the timestamp of any
|
|
1842
|
+
specific bookmark. So when we play the video,
|
|
1843
|
+
|
|
1844
|
+
00:51:24.800 --> 00:51:30.080
|
|
1845
|
+
we know where to set the video player at what
|
|
1846
|
+
time we want to send it out and the attribute
|
|
1847
|
+
|
|
1848
|
+
00:51:30.080 --> 00:51:35.840
|
|
1849
|
+
of the bookmark element will help us find that.
|
|
1850
|
+
And the final things we want to do here is,
|
|
1851
|
+
|
|
1852
|
+
00:51:35.840 --> 00:51:40.240
|
|
1853
|
+
since we know the new bookmark element
|
|
1854
|
+
is encapsulating all these other things,
|
|
1855
|
+
|
|
1856
|
+
00:51:41.040 --> 00:51:50.160
|
|
1857
|
+
we want to append child bookmark title element,
|
|
1858
|
+
so it displays within the new bookmark element.
|
|
1859
|
+
|
|
1860
|
+
00:51:50.160 --> 00:51:56.720
|
|
1861
|
+
And then we have this bookmarks element
|
|
1862
|
+
that is passed in. And we're going to
|
|
1863
|
+
|
|
1864
|
+
00:51:56.720 --> 00:52:03.840
|
|
1865
|
+
append our new bookmark element, which is this
|
|
1866
|
+
element that's encapsulating all the other things.
|
|
1867
|
+
|
|
1868
|
+
00:52:05.600 --> 00:52:11.280
|
|
1869
|
+
Inside that since it's a container.
|
|
1870
|
+
So now if we go back to our UI,
|
|
1871
|
+
|
|
1872
|
+
00:52:13.600 --> 00:52:20.560
|
|
1873
|
+
and we give this a reload, just in case, let's
|
|
1874
|
+
just go to a new video. And if I press plus,
|
|
1875
|
+
|
|
1876
|
+
00:52:20.560 --> 00:52:29.600
|
|
1877
|
+
in this video, we see a new row, it
|
|
1878
|
+
says bookmark out one hour, 54 minutes.
|
|
1879
|
+
|
|
1880
|
+
00:52:31.040 --> 00:52:36.480
|
|
1881
|
+
And we could add another row if we
|
|
1882
|
+
want. And it gives us that same row,
|
|
1883
|
+
|
|
1884
|
+
00:52:38.320 --> 00:52:41.680
|
|
1885
|
+
we're going to handle the case of the
|
|
1886
|
+
deletion, there's an ADD, it's just going to
|
|
1887
|
+
|
|
1888
|
+
00:52:41.680 --> 00:52:49.600
|
|
1889
|
+
set at zero seconds. Bookmark it
|
|
1890
|
+
000. Awesome. So that works. So now
|
|
1891
|
+
|
|
1892
|
+
00:52:52.320 --> 00:52:55.600
|
|
1893
|
+
let's go back work on some
|
|
1894
|
+
additional functionality.
|
|
1895
|
+
|
|
1896
|
+
00:52:56.560 --> 00:53:03.520
|
|
1897
|
+
Right now, we have no functionality associated
|
|
1898
|
+
with each bookmark yet, so we can't play any
|
|
1899
|
+
|
|
1900
|
+
00:53:03.520 --> 00:53:09.440
|
|
1901
|
+
particular timestamped bookmark, we can't delete a
|
|
1902
|
+
bookmark. And the next thing we want to add is the
|
|
1903
|
+
|
|
1904
|
+
00:53:09.440 --> 00:53:14.880
|
|
1905
|
+
play button. So to do this, we're going to add a
|
|
1906
|
+
play button to each bookmark that will go directly
|
|
1907
|
+
|
|
1908
|
+
00:53:14.880 --> 00:53:20.080
|
|
1909
|
+
to this timestamp that we have saved for each
|
|
1910
|
+
video. To start off, we're going to have to add
|
|
1911
|
+
|
|
1912
|
+
00:53:20.080 --> 00:53:25.360
|
|
1913
|
+
a function that is going to add an icon for
|
|
1914
|
+
a play button, listen for a click and call a
|
|
1915
|
+
|
|
1916
|
+
00:53:25.360 --> 00:53:30.720
|
|
1917
|
+
function or event listener that will perform the
|
|
1918
|
+
logic to set a video at a particular timestamp.
|
|
1919
|
+
|
|
1920
|
+
00:53:30.720 --> 00:53:35.200
|
|
1921
|
+
The function will end up looking something like
|
|
1922
|
+
what we're going to code right here in a second.
|
|
1923
|
+
|
|
1924
|
+
00:53:36.400 --> 00:53:41.840
|
|
1925
|
+
And we're going to keep it super generic because
|
|
1926
|
+
it's going to be used for both our delete
|
|
1927
|
+
|
|
1928
|
+
00:53:42.400 --> 00:53:49.600
|
|
1929
|
+
and play functionality. So the functions
|
|
1930
|
+
are going to take a source attribute
|
|
1931
|
+
|
|
1932
|
+
00:53:50.480 --> 00:54:04.960
|
|
1933
|
+
an event listener. And it control parent element.
|
|
1934
|
+
And when we say control elements in our code,
|
|
1935
|
+
|
|
1936
|
+
00:54:04.960 --> 00:54:09.840
|
|
1937
|
+
it means the play button, the delete button,
|
|
1938
|
+
we're just calling those control elements.
|
|
1939
|
+
|
|
1940
|
+
00:54:12.560 --> 00:54:14.640
|
|
1941
|
+
So we're going to create a control element.
|
|
1942
|
+
|
|
1943
|
+
00:54:21.120 --> 00:54:27.120
|
|
1944
|
+
And this is just one particular functionality,
|
|
1945
|
+
we're going to call a singular control element.
|
|
1946
|
+
|
|
1947
|
+
00:54:27.840 --> 00:54:32.400
|
|
1948
|
+
So in this specific case, we're going
|
|
1949
|
+
to have a play button. But again,
|
|
1950
|
+
|
|
1951
|
+
00:54:32.400 --> 00:54:37.600
|
|
1952
|
+
this is a generic function. So think of this
|
|
1953
|
+
as like a play button, a delete button we want
|
|
1954
|
+
|
|
1955
|
+
00:54:37.600 --> 00:54:43.760
|
|
1956
|
+
this singular control element will be one
|
|
1957
|
+
of those. And then those control elements
|
|
1958
|
+
|
|
1959
|
+
00:54:46.240 --> 00:54:52.160
|
|
1960
|
+
will be linked to a image in our assets
|
|
1961
|
+
folder. So if we want to play button,
|
|
1962
|
+
|
|
1963
|
+
00:54:52.880 --> 00:55:00.640
|
|
1964
|
+
what we're going to link to is assets slash play
|
|
1965
|
+
dot PNG, and our schema super are predictable
|
|
1966
|
+
|
|
1967
|
+
00:55:01.440 --> 00:55:07.120
|
|
1968
|
+
for this. So all we're going
|
|
1969
|
+
to do is assets plus SRC plus
|
|
1970
|
+
|
|
1971
|
+
00:55:08.000 --> 00:55:12.720
|
|
1972
|
+
dot png. And there's definitely a better
|
|
1973
|
+
way of doing this, you can go back
|
|
1974
|
+
|
|
1975
|
+
00:55:12.720 --> 00:55:17.040
|
|
1976
|
+
and work on the code after this video. But we're
|
|
1977
|
+
just going to keep it super simple for right now.
|
|
1978
|
+
|
|
1979
|
+
00:55:19.360 --> 00:55:26.880
|
|
1980
|
+
We're going to give it a title that is
|
|
1981
|
+
the same as our source attribute, or what
|
|
1982
|
+
|
|
1983
|
+
00:55:26.880 --> 00:55:34.720
|
|
1984
|
+
we pass in this source. So what's going to get
|
|
1985
|
+
passed in here is play, edit, delete, whatever.
|
|
1986
|
+
|
|
1987
|
+
00:55:34.720 --> 00:55:40.960
|
|
1988
|
+
And the title will be set to that. So in this
|
|
1989
|
+
particular case, for play, it will be set as play,
|
|
1990
|
+
|
|
1991
|
+
00:55:42.960 --> 00:55:51.760
|
|
1992
|
+
we're going to add a event listener. And
|
|
1993
|
+
that event listener will listen for a click.
|
|
1994
|
+
|
|
1995
|
+
00:55:53.920 --> 00:55:59.360
|
|
1996
|
+
And we're going to pass it a function that
|
|
1997
|
+
is going to be performed on that clique. And
|
|
1998
|
+
|
|
1999
|
+
00:55:59.360 --> 00:56:03.600
|
|
2000
|
+
the last thing we want to do is there's
|
|
2001
|
+
going to be a container for all control
|
|
2002
|
+
|
|
2003
|
+
00:56:03.600 --> 00:56:09.360
|
|
2004
|
+
elements. And we're passing that in into
|
|
2005
|
+
this function. And we're calling it control
|
|
2006
|
+
|
|
2007
|
+
00:56:09.360 --> 00:56:15.840
|
|
2008
|
+
parent element. So we're going to append this
|
|
2009
|
+
singular control element to the parent element.
|
|
2010
|
+
|
|
2011
|
+
00:56:18.560 --> 00:56:23.760
|
|
2012
|
+
And the next thing we're going to want to do is
|
|
2013
|
+
add the function call that will add a play button,
|
|
2014
|
+
|
|
2015
|
+
00:56:23.760 --> 00:56:29.280
|
|
2016
|
+
a title and our event listener to each individual
|
|
2017
|
+
bookmark. So in the add new bookmark function
|
|
2018
|
+
|
|
2019
|
+
00:56:29.280 --> 00:56:34.400
|
|
2020
|
+
that we coded earlier, we're going to add a couple
|
|
2021
|
+
lines of code here. And these couple lines of code
|
|
2022
|
+
|
|
2023
|
+
00:56:34.400 --> 00:56:39.440
|
|
2024
|
+
are going to add those control elements. So we're
|
|
2025
|
+
going to go ahead and create the element that's
|
|
2026
|
+
|
|
2027
|
+
00:56:39.440 --> 00:56:46.560
|
|
2028
|
+
going to hold all our buttons, we're going
|
|
2029
|
+
to call it the controls element. And it's
|
|
2030
|
+
|
|
2031
|
+
00:56:46.560 --> 00:56:49.680
|
|
2032
|
+
going to be a div just like these other
|
|
2033
|
+
ones, we're going to keep it super simple.
|
|
2034
|
+
|
|
2035
|
+
00:56:53.280 --> 00:56:57.840
|
|
2036
|
+
And then what we want to do
|
|
2037
|
+
is give this some styling.
|
|
2038
|
+
|
|
2039
|
+
00:57:01.120 --> 00:57:04.320
|
|
2040
|
+
We're going to add the class name, but controls,
|
|
2041
|
+
|
|
2042
|
+
00:57:05.360 --> 00:57:14.000
|
|
2043
|
+
and you're just gonna have to trust me on
|
|
2044
|
+
this it exists. Then what we want to do is
|
|
2045
|
+
|
|
2046
|
+
00:57:14.000 --> 00:57:21.440
|
|
2047
|
+
set our attributes using a set bookmark attributes
|
|
2048
|
+
function that we created, we're going to pass in
|
|
2049
|
+
|
|
2050
|
+
00:57:21.440 --> 00:57:26.960
|
|
2051
|
+
play, the event listener is going to be called
|
|
2052
|
+
on Play. And we're going to code that later.
|
|
2053
|
+
|
|
2054
|
+
00:57:26.960 --> 00:57:30.880
|
|
2055
|
+
And then we're going to pass in the controls
|
|
2056
|
+
element, which is going to be the parent element.
|
|
2057
|
+
|
|
2058
|
+
00:57:31.680 --> 00:57:39.840
|
|
2059
|
+
And the last thing we want to do is
|
|
2060
|
+
append this to our new bookmark element.
|
|
2061
|
+
|
|
2062
|
+
00:57:41.840 --> 00:57:47.440
|
|
2063
|
+
And what we should see now is, this
|
|
2064
|
+
play button is going to show up in
|
|
2065
|
+
|
|
2066
|
+
00:57:47.440 --> 00:57:53.840
|
|
2067
|
+
our extension. So let's check this out.
|
|
2068
|
+
Let's give this a refresh over here.
|
|
2069
|
+
|
|
2070
|
+
00:57:57.440 --> 00:58:01.920
|
|
2071
|
+
There we go. We have the play button in our
|
|
2072
|
+
extension. But what we're going to notice
|
|
2073
|
+
|
|
2074
|
+
00:58:02.480 --> 00:58:09.040
|
|
2075
|
+
is it's actually not going to work. Let's go
|
|
2076
|
+
ahead and play this video. And we're going to
|
|
2077
|
+
|
|
2078
|
+
00:58:09.040 --> 00:58:14.960
|
|
2079
|
+
try to get it back to 26 minutes, 51 seconds,
|
|
2080
|
+
it doesn't work. And the reason it doesn't work
|
|
2081
|
+
|
|
2082
|
+
00:58:14.960 --> 00:58:21.840
|
|
2083
|
+
is we still need to code the On Play Event
|
|
2084
|
+
listener. So let's go ahead and do that.
|
|
2085
|
+
|
|
2086
|
+
00:58:23.600 --> 00:58:30.800
|
|
2087
|
+
What we're going to do is we're going to target
|
|
2088
|
+
the timestamp attribute that we set earlier.
|
|
2089
|
+
|
|
2090
|
+
00:58:33.120 --> 00:58:39.920
|
|
2091
|
+
So again, you could check this out in your
|
|
2092
|
+
console or inspect, if you want to get a
|
|
2093
|
+
|
|
2094
|
+
00:58:39.920 --> 00:58:44.000
|
|
2095
|
+
visualization of how this is gonna work. But I'm
|
|
2096
|
+
gonna go ahead and type this for the sake of time.
|
|
2097
|
+
|
|
2098
|
+
00:58:47.760 --> 00:58:53.360
|
|
2099
|
+
And we're gonna get that timestamp we set
|
|
2100
|
+
earlier. And then the second thing we're
|
|
2101
|
+
|
|
2102
|
+
00:58:53.360 --> 00:58:58.240
|
|
2103
|
+
gonna want to do is grab the active tab, and
|
|
2104
|
+
that's just using the active tab function.
|
|
2105
|
+
|
|
2106
|
+
00:59:00.080 --> 00:59:04.560
|
|
2107
|
+
This is an async await function. So we're going
|
|
2108
|
+
to have to async await it. And I'm going to add
|
|
2109
|
+
|
|
2110
|
+
00:59:04.560 --> 00:59:09.600
|
|
2111
|
+
async to make this async function. So
|
|
2112
|
+
we've actually run into a problem now,
|
|
2113
|
+
|
|
2114
|
+
00:59:10.400 --> 00:59:14.960
|
|
2115
|
+
we need to send the content script and message
|
|
2116
|
+
to manipulate the YouTube player to set it at
|
|
2117
|
+
|
|
2118
|
+
00:59:14.960 --> 00:59:20.240
|
|
2119
|
+
the timestamp that the bookmark is placed on.
|
|
2120
|
+
So in this file, we're going to have to add that
|
|
2121
|
+
|
|
2122
|
+
00:59:20.880 --> 00:59:25.280
|
|
2123
|
+
message. Let's go ahead and send
|
|
2124
|
+
a message to the content script.
|
|
2125
|
+
|
|
2126
|
+
00:59:27.280 --> 00:59:34.560
|
|
2127
|
+
And this is going to follow the same pattern
|
|
2128
|
+
of how we did it with our background script.
|
|
2129
|
+
|
|
2130
|
+
00:59:37.040 --> 00:59:43.360
|
|
2131
|
+
Missing comma there. We're going to have type
|
|
2132
|
+
of play. That's going to be our event type.
|
|
2133
|
+
|
|
2134
|
+
00:59:44.320 --> 00:59:46.480
|
|
2135
|
+
And then the value is going to be bookmark time.
|
|
2136
|
+
|
|
2137
|
+
00:59:50.560 --> 00:59:54.160
|
|
2138
|
+
And then in our content script,
|
|
2139
|
+
we're going to have to be able
|
|
2140
|
+
|
|
2141
|
+
00:59:54.160 --> 01:00:00.160
|
|
2142
|
+
to read this message. So what we're
|
|
2143
|
+
going to do is add a condition to our
|
|
2144
|
+
|
|
2145
|
+
01:00:00.160 --> 01:00:04.800
|
|
2146
|
+
On message listener here, and we're
|
|
2147
|
+
going to say if the type is play.
|
|
2148
|
+
|
|
2149
|
+
01:00:11.360 --> 01:00:13.840
|
|
2150
|
+
Let's set the YouTube player time
|
|
2151
|
+
|
|
2152
|
+
01:00:14.960 --> 01:00:18.960
|
|
2153
|
+
equal to the value that's passed in. So basically,
|
|
2154
|
+
let's just take a look at this for a second.
|
|
2155
|
+
|
|
2156
|
+
01:00:20.080 --> 01:00:25.200
|
|
2157
|
+
If it's sending a message of type play,
|
|
2158
|
+
and the value is the bookmark time,
|
|
2159
|
+
|
|
2160
|
+
01:00:25.200 --> 01:00:29.840
|
|
2161
|
+
then what we want to do is take that value and
|
|
2162
|
+
set it to the YouTube Players Current Time,
|
|
2163
|
+
|
|
2164
|
+
01:00:29.840 --> 01:00:35.120
|
|
2165
|
+
which will make it the time of the bookmark.
|
|
2166
|
+
And let's go ahead and see if this works.
|
|
2167
|
+
|
|
2168
|
+
01:00:37.200 --> 01:00:46.080
|
|
2169
|
+
I'm going to go ahead and reload my extension.
|
|
2170
|
+
And let's go ahead and go to the extension,
|
|
2171
|
+
|
|
2172
|
+
01:00:46.080 --> 01:00:51.200
|
|
2173
|
+
we have a bookmark at 26 minutes, 51 seconds,
|
|
2174
|
+
it's currently at 48 minutes, 30 seconds.
|
|
2175
|
+
|
|
2176
|
+
01:00:52.000 --> 01:00:55.840
|
|
2177
|
+
Let's hit that play button. It goes
|
|
2178
|
+
back to 26 minutes, 51 seconds.
|
|
2179
|
+
|
|
2180
|
+
01:00:57.280 --> 01:01:00.320
|
|
2181
|
+
And now if we also hit this addition
|
|
2182
|
+
button anywhere in the video,
|
|
2183
|
+
|
|
2184
|
+
01:01:01.280 --> 01:01:05.840
|
|
2185
|
+
we should get a new bookmark, we have
|
|
2186
|
+
two hours, 21 minutes, 22 seconds.
|
|
2187
|
+
|
|
2188
|
+
01:01:07.520 --> 01:01:14.080
|
|
2189
|
+
Now let's go forward. Let's press play
|
|
2190
|
+
here. And it goes back to that time.
|
|
2191
|
+
|
|
2192
|
+
01:01:14.080 --> 01:01:19.840
|
|
2193
|
+
Awesome. So now our Play button works. The last
|
|
2194
|
+
functionality we want to build is the ability to
|
|
2195
|
+
|
|
2196
|
+
01:01:19.840 --> 01:01:25.360
|
|
2197
|
+
delete a bookmark, which will be super similar to
|
|
2198
|
+
what we did for the play button. The first thing
|
|
2199
|
+
|
|
2200
|
+
01:01:25.360 --> 01:01:30.480
|
|
2201
|
+
we're going to want to do is go to our POP up.js
|
|
2202
|
+
file. And we're going to add the delete button
|
|
2203
|
+
|
|
2204
|
+
01:01:30.480 --> 01:01:37.920
|
|
2205
|
+
to our controls element with the code in our add
|
|
2206
|
+
new bookmark function to set bookmark attributes.
|
|
2207
|
+
|
|
2208
|
+
01:01:37.920 --> 01:01:44.400
|
|
2209
|
+
So let's go ahead and do that we're going to pass
|
|
2210
|
+
in delete our on delete event listener, and then
|
|
2211
|
+
|
|
2212
|
+
01:01:44.400 --> 01:01:51.760
|
|
2213
|
+
the parent controls element. And since we set
|
|
2214
|
+
the undelete function as the event listener,
|
|
2215
|
+
|
|
2216
|
+
01:01:51.760 --> 01:01:56.960
|
|
2217
|
+
we need to code some operations that are
|
|
2218
|
+
going to take care of our deletion. So we
|
|
2219
|
+
|
|
2220
|
+
01:01:56.960 --> 01:02:02.240
|
|
2221
|
+
already know we're going to use this active tab
|
|
2222
|
+
that we used over here. So let's go ahead and
|
|
2223
|
+
|
|
2224
|
+
01:02:02.240 --> 01:02:08.720
|
|
2225
|
+
already create this an async function ahead
|
|
2226
|
+
of time. Let's grab the user's active tab.
|
|
2227
|
+
|
|
2228
|
+
01:02:13.680 --> 01:02:19.840
|
|
2229
|
+
And then what we're going to want to do is grab
|
|
2230
|
+
the timestamp attribute that we set earlier.
|
|
2231
|
+
|
|
2232
|
+
01:02:23.920 --> 01:02:27.200
|
|
2233
|
+
And it's going to be the same code from up
|
|
2234
|
+
here. So I'm just going to copy and paste
|
|
2235
|
+
|
|
2236
|
+
01:02:31.920 --> 01:02:40.400
|
|
2237
|
+
there we go. Then what we're going to also want
|
|
2238
|
+
to do is grab the element that we want to delete.
|
|
2239
|
+
|
|
2240
|
+
01:02:42.400 --> 01:02:48.480
|
|
2241
|
+
So if you remember, I created a
|
|
2242
|
+
specific ID linked to timestamps,
|
|
2243
|
+
|
|
2244
|
+
01:02:49.360 --> 01:02:54.080
|
|
2245
|
+
what we're going to want to do is grab
|
|
2246
|
+
elements by the ID so we can delete them.
|
|
2247
|
+
|
|
2248
|
+
01:02:58.160 --> 01:03:05.120
|
|
2249
|
+
So bookmark. Plus the bookmark time will
|
|
2250
|
+
give us the element we want to delete.
|
|
2251
|
+
|
|
2252
|
+
01:03:07.040 --> 01:03:09.520
|
|
2253
|
+
And then what we're going
|
|
2254
|
+
to do is delete that element
|
|
2255
|
+
|
|
2256
|
+
01:03:10.320 --> 01:03:15.840
|
|
2257
|
+
by going to the parent node, and then removing the
|
|
2258
|
+
child which will be the element we want to delete.
|
|
2259
|
+
|
|
2260
|
+
01:03:19.200 --> 01:03:23.360
|
|
2261
|
+
And then the final thing we're going to want to
|
|
2262
|
+
do here is send a message to our content script.
|
|
2263
|
+
|
|
2264
|
+
01:03:26.000 --> 01:03:33.520
|
|
2265
|
+
Saying we want to perform a deletion type of
|
|
2266
|
+
|
|
2267
|
+
01:03:36.800 --> 01:03:45.200
|
|
2268
|
+
delete, and then the value is going to be bookmark
|
|
2269
|
+
time. And there's one final thing we want to do
|
|
2270
|
+
|
|
2271
|
+
01:03:45.200 --> 01:03:51.040
|
|
2272
|
+
here, this Send Message function from the Chrome's
|
|
2273
|
+
tabs API actually takes a callback function
|
|
2274
|
+
|
|
2275
|
+
01:03:51.040 --> 01:03:56.240
|
|
2276
|
+
optionally. And we're going to pass one in which
|
|
2277
|
+
is going to be our view bookmarks function. And
|
|
2278
|
+
|
|
2279
|
+
01:03:56.240 --> 01:04:03.680
|
|
2280
|
+
that's just going to refresh our bookmarks, so any
|
|
2281
|
+
deletions show up immediately, then in our content
|
|
2282
|
+
|
|
2283
|
+
01:04:03.680 --> 01:04:08.720
|
|
2284
|
+
script, we're going to add another condition,
|
|
2285
|
+
which is basically you're going to ingest
|
|
2286
|
+
|
|
2287
|
+
01:04:08.720 --> 01:04:16.720
|
|
2288
|
+
that Delete message. So we're going
|
|
2289
|
+
to say else if type equals Delete.
|
|
2290
|
+
|
|
2291
|
+
01:04:19.600 --> 01:04:25.840
|
|
2292
|
+
The current video bookmarks will be
|
|
2293
|
+
equal to current video bookmarks.
|
|
2294
|
+
|
|
2295
|
+
01:04:26.960 --> 01:04:29.120
|
|
2296
|
+
Filter, and we're going to filter by time.
|
|
2297
|
+
|
|
2298
|
+
01:04:31.760 --> 01:04:35.120
|
|
2299
|
+
So the time is not equal to the value
|
|
2300
|
+
being passed in because that's a
|
|
2301
|
+
|
|
2302
|
+
01:04:35.120 --> 01:04:39.840
|
|
2303
|
+
value we're deleting. And then the final
|
|
2304
|
+
thing we want to do is sync Chrome Storage.
|
|
2305
|
+
|
|
2306
|
+
01:04:41.680 --> 01:04:48.000
|
|
2307
|
+
So if this page reloads, this
|
|
2308
|
+
deleted bookmark does not show up.
|
|
2309
|
+
|
|
2310
|
+
01:04:52.720 --> 01:05:03.120
|
|
2311
|
+
We're going to JSON fi, error bookmarks and If
|
|
2312
|
+
that should work, the last thing we want to do
|
|
2313
|
+
|
|
2314
|
+
01:05:03.120 --> 01:05:09.520
|
|
2315
|
+
is add a way to send the updated bookmarks back
|
|
2316
|
+
to our POP up.js file in order to display the most
|
|
2317
|
+
|
|
2318
|
+
01:05:09.520 --> 01:05:16.480
|
|
2319
|
+
recent bookmarks, and we'll do the following.
|
|
2320
|
+
To do that, we're going to send a response of
|
|
2321
|
+
|
|
2322
|
+
01:05:16.480 --> 01:05:22.560
|
|
2323
|
+
current video bookmarks. So now we can go ahead
|
|
2324
|
+
and try out deleting a bookmark with a reload
|
|
2325
|
+
|
|
2326
|
+
01:05:22.560 --> 01:05:28.400
|
|
2327
|
+
of our extension, and it should start working.
|
|
2328
|
+
So I'm going to go back to our Chrome browser,
|
|
2329
|
+
|
|
2330
|
+
01:05:31.840 --> 01:05:39.360
|
|
2331
|
+
reload our extension. And if we
|
|
2332
|
+
go ahead and delete a bookmark,
|
|
2333
|
+
|
|
2334
|
+
01:05:40.240 --> 01:05:47.200
|
|
2335
|
+
we're gonna see that they're deleted. If we go
|
|
2336
|
+
ahead and add a bookmark, we're gonna see there's
|
|
2337
|
+
|
|
2338
|
+
01:05:47.200 --> 01:05:52.320
|
|
2339
|
+
a new bookmark. It's at a different timestamp the
|
|
2340
|
+
YouTube players a different time. So if we play,
|
|
2341
|
+
|
|
2342
|
+
01:05:53.600 --> 01:05:58.720
|
|
2343
|
+
it goes back to the timestamp of the bookmark.
|
|
2344
|
+
We want to delete again, it's going to delete.
|
|
2345
|
+
|
|
2346
|
+
01:05:59.680 --> 01:06:03.360
|
|
2347
|
+
The last thing we're going to want to
|
|
2348
|
+
do is distribute our extension. However,
|
|
2349
|
+
|
|
2350
|
+
01:06:03.360 --> 01:06:07.840
|
|
2351
|
+
I'm not going to quite go over that in this video,
|
|
2352
|
+
because Google gives great documentation that
|
|
2353
|
+
|
|
2354
|
+
01:06:07.840 --> 01:06:12.960
|
|
2355
|
+
serves as a step by step guide on how to go about
|
|
2356
|
+
publishing your chrome extension to the Google web
|
|
2357
|
+
|
|
2358
|
+
01:06:12.960 --> 01:06:18.400
|
|
2359
|
+
store for anyone to download. And with that, the
|
|
2360
|
+
videos over you know everything you have to do
|
|
2361
|
+
|
|
2362
|
+
01:06:18.400 --> 01:06:23.920
|
|
2363
|
+
in order to create a modern web extension
|
|
2364
|
+
using manifest v3, and I'll see you next time.
|