wai-website-theme 1.3.1 → 1.4
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.
- checksums.yaml +4 -4
- data/_includes/different.html +2 -1
- data/_includes/external.html +2 -1
- data/_includes/header.html +2 -1
- data/_includes/menuitem.html +6 -2
- data/_includes/peoplelist.html +21 -0
- data/_includes/prevnext-navigation.html +56 -0
- data/_includes/{prevnext.html → prevnext-order.html} +9 -0
- data/_includes/translation-note-msg.html +5 -3
- data/_includes/video-player.html +2 -2
- data/_layouts/default.html +8 -1
- data/_layouts/news.html +7 -1
- data/_layouts/policy.html +7 -1
- data/_layouts/sidenav.html +8 -1
- data/_layouts/sidenavsidebar.html +8 -1
- data/assets/ableplayer/Gruntfile.js +2 -1
- data/assets/ableplayer/README.md +158 -85
- data/assets/ableplayer/build/ableplayer.dist.js +15445 -13823
- data/assets/ableplayer/build/ableplayer.js +15445 -13823
- data/assets/ableplayer/build/ableplayer.min.css +1 -2
- data/assets/ableplayer/build/ableplayer.min.js +3 -10
- data/assets/ableplayer/package-lock.json +944 -346
- data/assets/ableplayer/package.json +8 -8
- data/assets/ableplayer/scripts/ableplayer-base.js +515 -524
- data/assets/ableplayer/scripts/browser.js +158 -158
- data/assets/ableplayer/scripts/buildplayer.js +1750 -1682
- data/assets/ableplayer/scripts/caption.js +424 -401
- data/assets/ableplayer/scripts/chapters.js +259 -259
- data/assets/ableplayer/scripts/control.js +1831 -1594
- data/assets/ableplayer/scripts/description.js +333 -256
- data/assets/ableplayer/scripts/dialog.js +145 -145
- data/assets/ableplayer/scripts/dragdrop.js +746 -749
- data/assets/ableplayer/scripts/event.js +875 -696
- data/assets/ableplayer/scripts/initialize.js +819 -912
- data/assets/ableplayer/scripts/langs.js +979 -743
- data/assets/ableplayer/scripts/metadata.js +124 -124
- data/assets/ableplayer/scripts/misc.js +170 -137
- data/assets/ableplayer/scripts/preference.js +904 -904
- data/assets/ableplayer/scripts/search.js +172 -172
- data/assets/ableplayer/scripts/sign.js +82 -78
- data/assets/ableplayer/scripts/slider.js +449 -448
- data/assets/ableplayer/scripts/track.js +409 -309
- data/assets/ableplayer/scripts/transcript.js +684 -595
- data/assets/ableplayer/scripts/translation.js +63 -67
- data/assets/ableplayer/scripts/ttml2webvtt.js +85 -85
- data/assets/ableplayer/scripts/vimeo.js +448 -0
- data/assets/ableplayer/scripts/volume.js +395 -380
- data/assets/ableplayer/scripts/vts.js +1077 -1077
- data/assets/ableplayer/scripts/webvtt.js +766 -763
- data/assets/ableplayer/scripts/youtube.js +695 -478
- data/assets/ableplayer/styles/ableplayer.css +54 -46
- data/assets/ableplayer/translations/nl.js +54 -54
- data/assets/ableplayer/translations/pt-br.js +311 -0
- data/assets/ableplayer/translations/tr.js +311 -0
- data/assets/ableplayer/translations/zh-tw.js +1 -1
- data/assets/css/style.css +1 -1
- data/assets/css/style.css.map +1 -1
- data/assets/images/icons.svg +5 -5
- data/assets/scripts/main.js +7 -0
- data/assets/search/tipuesearch.js +3 -3
- metadata +8 -3
|
@@ -1,482 +1,699 @@
|
|
|
1
1
|
|
|
2
2
|
(function ($) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
3
|
+
AblePlayer.prototype.initYouTubePlayer = function () {
|
|
4
|
+
|
|
5
|
+
var thisObj, deferred, promise, youTubeId, googleApiPromise, json;
|
|
6
|
+
thisObj = this;
|
|
7
|
+
|
|
8
|
+
deferred = new $.Deferred();
|
|
9
|
+
promise = deferred.promise();
|
|
10
|
+
|
|
11
|
+
// if a described version is available && user prefers desription
|
|
12
|
+
// init player using the described version
|
|
13
|
+
if (this.youTubeDescId && this.prefDesc) {
|
|
14
|
+
youTubeId = this.youTubeDescId;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
youTubeId = this.youTubeId;
|
|
18
|
+
}
|
|
19
|
+
this.activeYouTubeId = youTubeId;
|
|
20
|
+
if (AblePlayer.youtubeIframeAPIReady) {
|
|
21
|
+
// Script already loaded and ready.
|
|
22
|
+
this.finalizeYoutubeInit().then(function() {
|
|
23
|
+
deferred.resolve();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// Has another player already started loading the script? If so, abort...
|
|
28
|
+
if (!AblePlayer.loadingYoutubeIframeAPI) {
|
|
29
|
+
$.getScript('https://www.youtube.com/iframe_api').fail(function () {
|
|
30
|
+
deferred.fail();
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Otherwise, keeping waiting for script load event...
|
|
35
|
+
$('body').on('youtubeIframeAPIReady', function () {
|
|
36
|
+
thisObj.finalizeYoutubeInit().then(function() {
|
|
37
|
+
deferred.resolve();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return promise;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
AblePlayer.prototype.finalizeYoutubeInit = function () {
|
|
45
|
+
|
|
46
|
+
// This is called once we're sure the Youtube iFrame API is loaded -- see above
|
|
47
|
+
var deferred, promise, thisObj, containerId, ccLoadPolicy, videoDimensions, autoplay;
|
|
48
|
+
|
|
49
|
+
deferred = new $.Deferred();
|
|
50
|
+
promise = deferred.promise();
|
|
51
|
+
|
|
52
|
+
thisObj = this;
|
|
53
|
+
|
|
54
|
+
containerId = this.mediaId + '_youtube';
|
|
55
|
+
|
|
56
|
+
this.$mediaContainer.prepend($('<div>').attr('id', containerId));
|
|
57
|
+
// NOTE: Tried the following in place of the above in January 2016
|
|
58
|
+
// because in some cases two videos were being added to the DOM
|
|
59
|
+
// However, once v2.2.23 was fairly stable, unable to reproduce that problem
|
|
60
|
+
// so maybe it's not an issue. This is preserved here temporarily, just in case it's needed...
|
|
61
|
+
// thisObj.$mediaContainer.html($('<div>').attr('id', containerId));
|
|
62
|
+
|
|
63
|
+
// cc_load_policy:
|
|
64
|
+
// 0 - show captions depending on user's preference on YouTube
|
|
65
|
+
// 1 - show captions by default, even if the user has turned them off
|
|
66
|
+
// For Able Player, init player with value of 0
|
|
67
|
+
// and will turn them on or off after player is initialized
|
|
68
|
+
// based on availability of local tracks and user's Able Player prefs
|
|
69
|
+
ccLoadPolicy = 0;
|
|
70
|
+
|
|
71
|
+
videoDimensions = this.getYouTubeDimensions(this.activeYouTubeId, containerId);
|
|
72
|
+
if (videoDimensions) {
|
|
73
|
+
this.ytWidth = videoDimensions[0];
|
|
74
|
+
this.ytHeight = videoDimensions[1];
|
|
75
|
+
this.aspectRatio = thisObj.ytWidth / thisObj.ytHeight;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// dimensions are initially unknown
|
|
79
|
+
// sending null values to YouTube results in a video that uses the default YouTube dimensions
|
|
80
|
+
// these can then be scraped from the iframe and applied to this.$ableWrapper
|
|
81
|
+
this.ytWidth = null;
|
|
82
|
+
this.ytHeight = null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (this.okToPlay) {
|
|
86
|
+
autoplay = 1;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
autoplay = 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// NOTE: YouTube is changing the following parameters on or after Sep 25, 2018:
|
|
93
|
+
// rel - No longer able to prevent YouTube from showing related videos
|
|
94
|
+
// value of 0 now limits related videos to video's same channel
|
|
95
|
+
// showinfo - No longer supported (previously, value of 0 hid title, share, & watch later buttons
|
|
96
|
+
// Documentation https://developers.google.com/youtube/player_parameters
|
|
97
|
+
|
|
98
|
+
this.youTubePlayer = new YT.Player(containerId, {
|
|
99
|
+
videoId: this.activeYouTubeId,
|
|
100
|
+
host: this.youTubeNoCookie ? 'https://www.youtube-nocookie.com' : 'https://www.youtube.com',
|
|
101
|
+
width: this.ytWidth,
|
|
102
|
+
height: this.ytHeight,
|
|
103
|
+
playerVars: {
|
|
104
|
+
autoplay: autoplay,
|
|
105
|
+
enablejsapi: 1,
|
|
106
|
+
disableKb: 1, // disable keyboard shortcuts, using our own
|
|
107
|
+
playsinline: this.playsInline,
|
|
108
|
+
start: this.startTime,
|
|
109
|
+
controls: 0, // no controls, using our own
|
|
110
|
+
cc_load_policy: ccLoadPolicy,
|
|
111
|
+
hl: this.lang, // use the default language UI
|
|
112
|
+
modestbranding: 1, // no YouTube logo in controller
|
|
113
|
+
rel: 0, // do not show related videos when video ends
|
|
114
|
+
html5: 1, // force html5 if browser supports it (undocumented parameter; 0 does NOT force Flash)
|
|
115
|
+
iv_load_policy: 3 // do not show video annotations
|
|
116
|
+
},
|
|
117
|
+
events: {
|
|
118
|
+
onReady: function () {
|
|
119
|
+
if (thisObj.swappingSrc) {
|
|
120
|
+
// swap is now complete
|
|
121
|
+
thisObj.swappingSrc = false;
|
|
122
|
+
thisObj.cueingPlaylistItem = false;
|
|
123
|
+
if (thisObj.playing) {
|
|
124
|
+
// resume playing
|
|
125
|
+
thisObj.playMedia();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (thisObj.userClickedPlaylist) {
|
|
129
|
+
thisObj.userClickedPlaylist = false; // reset
|
|
130
|
+
}
|
|
131
|
+
if (typeof thisObj.aspectRatio === 'undefined') {
|
|
132
|
+
thisObj.resizeYouTubePlayer(thisObj.activeYouTubeId, containerId);
|
|
133
|
+
}
|
|
134
|
+
deferred.resolve();
|
|
135
|
+
},
|
|
136
|
+
onError: function (x) {
|
|
137
|
+
deferred.fail();
|
|
138
|
+
},
|
|
139
|
+
onStateChange: function (x) {
|
|
140
|
+
thisObj.getPlayerState().then(function(playerState) {
|
|
141
|
+
// values of playerState: 'playing','paused','buffering','ended'
|
|
142
|
+
if (playerState === 'playing') {
|
|
143
|
+
thisObj.playing = true;
|
|
144
|
+
thisObj.startedPlaying = true;
|
|
145
|
+
thisObj.paused = false;
|
|
146
|
+
}
|
|
147
|
+
else if (playerState == 'ended') {
|
|
148
|
+
thisObj.onMediaComplete();
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
thisObj.playing = false;
|
|
152
|
+
thisObj.paused = true;
|
|
153
|
+
}
|
|
154
|
+
if (thisObj.stoppingYouTube && playerState === 'paused') {
|
|
155
|
+
if (typeof thisObj.$posterImg !== 'undefined') {
|
|
156
|
+
thisObj.$posterImg.show();
|
|
157
|
+
}
|
|
158
|
+
thisObj.stoppingYouTube = false;
|
|
159
|
+
thisObj.seeking = false;
|
|
160
|
+
thisObj.playing = false;
|
|
161
|
+
thisObj.paused = true;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
onPlaybackQualityChange: function () {
|
|
166
|
+
// do something
|
|
167
|
+
},
|
|
168
|
+
onApiChange: function (x) {
|
|
169
|
+
// As of Able Player v2.2.23, we are now getting caption data via the YouTube Data API
|
|
170
|
+
// prior to calling initYouTubePlayer()
|
|
171
|
+
// Previously we got caption data via the YouTube iFrame API, and doing so was an awful mess.
|
|
172
|
+
// onApiChange fires to indicate that the player has loaded (or unloaded) a module with exposed API methods
|
|
173
|
+
// it isn't fired until the video starts playing
|
|
174
|
+
// if captions are available for this video (automated captions don't count)
|
|
175
|
+
// the 'captions' (or 'cc') module is loaded. If no captions are available, this event never fires
|
|
176
|
+
// So, to trigger this event we had to play the video briefly, then pause, then reset.
|
|
177
|
+
// During that brief moment of playback, the onApiChange event was fired and we could setup captions
|
|
178
|
+
// The 'captions' and 'cc' modules are very different, and have different data and methods
|
|
179
|
+
// NOW, in v2.2.23, we still need to initialize the caption modules in order to control captions
|
|
180
|
+
// but we don't have to do that on load in order to get caption data
|
|
181
|
+
// Instead, we can wait until the video starts playing normally, then retrieve the modules
|
|
182
|
+
thisObj.initYouTubeCaptionModule();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
this.injectPoster(this.$mediaContainer, 'youtube');
|
|
188
|
+
if (!this.hasPlaylist) {
|
|
189
|
+
// remove the media element, since YouTube replaces that with its own element in an iframe
|
|
190
|
+
// this is handled differently for playlists. See buildplayer.js > cuePlaylistItem()
|
|
191
|
+
this.$media.remove();
|
|
192
|
+
}
|
|
193
|
+
return promise;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
AblePlayer.prototype.getYouTubeDimensions = function (youTubeContainerId) {
|
|
197
|
+
|
|
198
|
+
// get dimensions of YouTube video, return array with width & height
|
|
199
|
+
// Sources, in order of priority:
|
|
200
|
+
// 1. The width and height attributes on <video>
|
|
201
|
+
// 2. YouTube (not yet supported; can't seem to get this data via YouTube Data API without OAuth!)
|
|
202
|
+
|
|
203
|
+
var d, url, $iframe, width, height;
|
|
204
|
+
|
|
205
|
+
d = [];
|
|
206
|
+
|
|
207
|
+
if (typeof this.playerMaxWidth !== 'undefined') {
|
|
208
|
+
d[0] = this.playerMaxWidth;
|
|
209
|
+
// optional: set height as well; not required though since YouTube will adjust height to match width
|
|
210
|
+
if (typeof this.playerMaxHeight !== 'undefined') {
|
|
211
|
+
d[1] = this.playerMaxHeight;
|
|
212
|
+
}
|
|
213
|
+
return d;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
if (typeof $('#' + youTubeContainerId) !== 'undefined') {
|
|
217
|
+
$iframe = $('#' + youTubeContainerId);
|
|
218
|
+
width = $iframe.width();
|
|
219
|
+
height = $iframe.height();
|
|
220
|
+
if (width > 0 && height > 0) {
|
|
221
|
+
d[0] = width;
|
|
222
|
+
d[1] = height;
|
|
223
|
+
return d;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return false;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
AblePlayer.prototype.resizeYouTubePlayer = function(youTubeId, youTubeContainerId) {
|
|
231
|
+
|
|
232
|
+
// called after player is ready, if youTube dimensions were previously unknown
|
|
233
|
+
// Now need to get them from the iframe element that YouTube injected
|
|
234
|
+
// and resize Able Player to match
|
|
235
|
+
var d, width, height;
|
|
236
|
+
if (typeof this.aspectRatio !== 'undefined') {
|
|
237
|
+
// video dimensions have already been collected
|
|
238
|
+
if (this.restoringAfterFullScreen) {
|
|
239
|
+
// restore using saved values
|
|
240
|
+
if (this.youTubePlayer) {
|
|
241
|
+
this.youTubePlayer.setSize(this.ytWidth, this.ytHeight);
|
|
242
|
+
}
|
|
243
|
+
this.restoringAfterFullScreen = false;
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
// recalculate with new wrapper size
|
|
247
|
+
width = this.$ableWrapper.parent().width();
|
|
248
|
+
height = Math.round(width / this.aspectRatio);
|
|
249
|
+
this.$ableWrapper.css({
|
|
250
|
+
'max-width': width + 'px',
|
|
251
|
+
'width': ''
|
|
252
|
+
});
|
|
253
|
+
this.youTubePlayer.setSize(width, height);
|
|
254
|
+
if (this.fullscreen) {
|
|
255
|
+
this.youTubePlayer.setSize(width, height);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
// resizing due to a change in window size, not full screen
|
|
259
|
+
this.youTubePlayer.setSize(this.ytWidth, this.ytHeight);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
d = this.getYouTubeDimensions(youTubeContainerId);
|
|
265
|
+
if (d) {
|
|
266
|
+
width = d[0];
|
|
267
|
+
height = d[1];
|
|
268
|
+
if (width > 0 && height > 0) {
|
|
269
|
+
this.aspectRatio = width / height;
|
|
270
|
+
this.ytWidth = width;
|
|
271
|
+
this.ytHeight = height;
|
|
272
|
+
if (width !== this.$ableWrapper.width()) {
|
|
273
|
+
// now that we've retrieved YouTube's default width,
|
|
274
|
+
// need to adjust to fit the current player wrapper
|
|
275
|
+
width = this.$ableWrapper.width();
|
|
276
|
+
height = Math.round(width / this.aspectRatio);
|
|
277
|
+
if (this.youTubePlayer) {
|
|
278
|
+
this.youTubePlayer.setSize(width, height);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
AblePlayer.prototype.setupYouTubeCaptions = function () {
|
|
287
|
+
|
|
288
|
+
// called from setupAltCaptions if player is YouTube and there are no <track> captions
|
|
289
|
+
|
|
290
|
+
// use YouTube Data API to get caption data from YouTube
|
|
291
|
+
// function is called only if these conditions are met:
|
|
292
|
+
// 1. this.player === 'youtube'
|
|
293
|
+
// 2. there are no <track> elements with kind="captions"
|
|
294
|
+
// 3. youTubeDataApiKey is defined
|
|
295
|
+
|
|
296
|
+
var deferred = new $.Deferred();
|
|
297
|
+
var promise = deferred.promise();
|
|
298
|
+
|
|
299
|
+
var thisObj, googleApiPromise, youTubeId, i;
|
|
300
|
+
|
|
301
|
+
thisObj = this;
|
|
302
|
+
|
|
303
|
+
// if a described version is available && user prefers desription
|
|
304
|
+
// Use the described version, and get its captions
|
|
305
|
+
if (this.youTubeDescId && this.prefDesc) {
|
|
306
|
+
youTubeId = this.youTubeDescId;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
youTubeId = this.youTubeId;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (typeof youTubeDataAPIKey !== 'undefined') {
|
|
313
|
+
// Wait until Google Client API is loaded
|
|
314
|
+
// When loaded, it sets global var googleApiReady to true
|
|
315
|
+
|
|
316
|
+
// Thanks to Paul Tavares for $.doWhen()
|
|
317
|
+
// https://gist.github.com/purtuga/8257269
|
|
318
|
+
$.doWhen({
|
|
319
|
+
when: function(){
|
|
320
|
+
return googleApiReady;
|
|
321
|
+
},
|
|
322
|
+
interval: 100, // ms
|
|
323
|
+
attempts: 1000
|
|
324
|
+
})
|
|
325
|
+
.done(function(){
|
|
326
|
+
deferred.resolve();
|
|
327
|
+
})
|
|
328
|
+
.fail(function(){
|
|
329
|
+
console.log('Unable to initialize Google API. YouTube captions are currently unavailable.');
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
deferred.resolve();
|
|
334
|
+
}
|
|
335
|
+
return promise;
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
AblePlayer.prototype.waitForGapi = function () {
|
|
339
|
+
|
|
340
|
+
// wait for Google API to initialize
|
|
341
|
+
|
|
342
|
+
var thisObj, deferred, promise, maxWaitTime, maxTries, tries, timer, interval;
|
|
343
|
+
|
|
344
|
+
thisObj = this;
|
|
345
|
+
deferred = new $.Deferred();
|
|
346
|
+
promise = deferred.promise();
|
|
347
|
+
maxWaitTime = 5000; // 5 seconds
|
|
348
|
+
maxTries = 100; // number of tries during maxWaitTime
|
|
349
|
+
tries = 0;
|
|
350
|
+
interval = Math.floor(maxWaitTime/maxTries);
|
|
351
|
+
|
|
352
|
+
timer = setInterval(function() {
|
|
353
|
+
tries++;
|
|
354
|
+
if (googleApiReady || tries >= maxTries) {
|
|
355
|
+
clearInterval(timer);
|
|
356
|
+
if (googleApiReady) { // success!
|
|
357
|
+
deferred.resolve(true);
|
|
358
|
+
}
|
|
359
|
+
else { // tired of waiting
|
|
360
|
+
deferred.resolve(false);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
thisObj.waitForGapi();
|
|
365
|
+
}
|
|
366
|
+
}, interval);
|
|
367
|
+
return promise;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
AblePlayer.prototype.getYouTubeCaptionTracks = function (youTubeId) {
|
|
371
|
+
|
|
372
|
+
// get data via YouTube Data API, and push data to this.captions
|
|
373
|
+
var deferred = new $.Deferred();
|
|
374
|
+
var promise = deferred.promise();
|
|
375
|
+
|
|
376
|
+
var thisObj, useGoogleApi, i, trackId, trackLang, trackName, trackLabel, trackKind, isDraft, isDefaultTrack;
|
|
377
|
+
|
|
378
|
+
thisObj = this;
|
|
379
|
+
|
|
380
|
+
if (typeof youTubeDataAPIKey !== 'undefined') {
|
|
381
|
+
this.waitForGapi().then(function(waitResult) {
|
|
382
|
+
|
|
383
|
+
useGoogleApi = waitResult;
|
|
384
|
+
|
|
385
|
+
// useGoogleApi returns false if API failed to initalize after max wait time
|
|
386
|
+
// Proceed only if true. Otherwise can still use fallback method (see else loop below)
|
|
387
|
+
if (useGoogleApi === true) {
|
|
388
|
+
gapi.client.setApiKey(youTubeDataAPIKey);
|
|
389
|
+
gapi.client
|
|
390
|
+
.load('youtube', 'v3')
|
|
391
|
+
.then(function() {
|
|
392
|
+
var request = gapi.client.youtube.captions.list({
|
|
393
|
+
'part': 'id, snippet',
|
|
394
|
+
'videoId': youTubeId
|
|
395
|
+
});
|
|
396
|
+
request.then(function(json) {
|
|
397
|
+
if (json.result.items.length) { // video has captions!
|
|
398
|
+
thisObj.hasCaptions = true;
|
|
399
|
+
thisObj.usingYouTubeCaptions = true;
|
|
400
|
+
if (thisObj.prefCaptions === 1) {
|
|
401
|
+
thisObj.captionsOn = true;
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
thisObj.captionsOn = false;
|
|
405
|
+
}
|
|
406
|
+
// Step through results and add them to cues array
|
|
407
|
+
for (i=0; i < json.result.items.length; i++) {
|
|
408
|
+
trackName = json.result.items[i].snippet.name; // usually seems to be empty
|
|
409
|
+
trackLang = json.result.items[i].snippet.language;
|
|
410
|
+
trackKind = json.result.items[i].snippet.trackKind; // ASR, standard, forced
|
|
411
|
+
isDraft = json.result.items[i].snippet.isDraft; // Boolean
|
|
412
|
+
// Other variables that could potentially be collected from snippet:
|
|
413
|
+
// isCC - Boolean, always seems to be false
|
|
414
|
+
// isLarge - Boolean
|
|
415
|
+
// isEasyReader - Boolean
|
|
416
|
+
// isAutoSynced Boolean
|
|
417
|
+
// status - string, always seems to be "serving"
|
|
418
|
+
|
|
419
|
+
var srcUrl = thisObj.getYouTubeTimedTextUrl(youTubeId,trackName,trackLang);
|
|
420
|
+
if (trackKind !== 'ASR' && !isDraft) {
|
|
421
|
+
|
|
422
|
+
if (trackName !== '') {
|
|
423
|
+
trackLabel = trackName;
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
// if track name is empty (it always seems to be), assign a label based on trackLang
|
|
427
|
+
trackLabel = thisObj.getLanguageName(trackLang);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// assign the default track based on language of the player
|
|
431
|
+
if (trackLang === thisObj.lang) {
|
|
432
|
+
isDefaultTrack = true;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
isDefaultTrack = false;
|
|
436
|
+
}
|
|
437
|
+
thisObj.tracks.push({
|
|
438
|
+
'kind': 'captions',
|
|
439
|
+
'src': srcUrl,
|
|
440
|
+
'language': trackLang,
|
|
441
|
+
'label': trackLabel,
|
|
442
|
+
'def': isDefaultTrack
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
// setupPopups again with new captions array, replacing original
|
|
447
|
+
thisObj.setupPopups('captions');
|
|
448
|
+
deferred.resolve();
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
thisObj.hasCaptions = false;
|
|
452
|
+
thisObj.usingYouTubeCaptions = false;
|
|
453
|
+
deferred.resolve();
|
|
454
|
+
}
|
|
455
|
+
}, function (reason) {
|
|
456
|
+
// If video has no captions, YouTube returns an error.
|
|
457
|
+
// Should still proceed, but with captions disabled
|
|
458
|
+
// The specific error, if needed: reason.result.error.message
|
|
459
|
+
// If no captions, the error is: "The video identified by the <code>videoId</code> parameter could not be found."
|
|
460
|
+
console.log('Error retrieving captions.');
|
|
461
|
+
console.log('Check your video on YouTube to be sure captions are available and published.');
|
|
462
|
+
thisObj.hasCaptions = false;
|
|
463
|
+
thisObj.usingYouTubeCaptions = false;
|
|
464
|
+
deferred.resolve();
|
|
465
|
+
});
|
|
466
|
+
})
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
// googleAPi never loaded.
|
|
470
|
+
this.getYouTubeCaptionTracks2(youTubeId).then(function() {
|
|
471
|
+
deferred.resolve();
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
// web owner hasn't provided a Google API key
|
|
478
|
+
// attempt to get YouTube captions via the backup method
|
|
479
|
+
this.getYouTubeCaptionTracks2(youTubeId).then(function() {
|
|
480
|
+
deferred.resolve();
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
return promise;
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
AblePlayer.prototype.getYouTubeCaptionTracks2 = function (youTubeId) {
|
|
487
|
+
|
|
488
|
+
// Use alternative backup method of getting caption tracks from YouTube
|
|
489
|
+
// and pushing them to this.captions
|
|
490
|
+
// Called from getYouTubeCaptionTracks if no Google API key is defined
|
|
491
|
+
// or if Google API failed to initiatlize
|
|
492
|
+
// This method seems to be undocumented, but is referenced on StackOverflow
|
|
493
|
+
// We'll use that as a fallback but it could break at any moment
|
|
494
|
+
|
|
495
|
+
var deferred = new $.Deferred();
|
|
496
|
+
var promise = deferred.promise();
|
|
497
|
+
|
|
498
|
+
var thisObj, useGoogleApi, i, trackId, trackLang, trackName, trackLabel, trackKind, isDraft, isDefaultTrack;
|
|
499
|
+
|
|
500
|
+
thisObj = this;
|
|
501
|
+
|
|
502
|
+
$.ajax({
|
|
503
|
+
type: 'get',
|
|
504
|
+
url: 'https://www.youtube.com/api/timedtext?type=list&v=' + youTubeId,
|
|
505
|
+
dataType: 'xml',
|
|
506
|
+
success: function(xml) {
|
|
507
|
+
var $tracks = $(xml).find('track');
|
|
508
|
+
if ($tracks.length > 0) { // video has captions!
|
|
509
|
+
thisObj.hasCaptions = true;
|
|
510
|
+
thisObj.usingYouTubeCaptions = true;
|
|
511
|
+
if (thisObj.prefCaptions === 1) {
|
|
512
|
+
thisObj.captionsOn = true;
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
thisObj.captionsOn = false;
|
|
516
|
+
}
|
|
517
|
+
// Step through results and add them to tracks array
|
|
518
|
+
$tracks.each(function() {
|
|
519
|
+
trackId = $(this).attr('id');
|
|
520
|
+
trackLang = $(this).attr('lang_code');
|
|
521
|
+
if ($(this).attr('name') !== '') {
|
|
522
|
+
trackName = $(this).attr('name');
|
|
523
|
+
trackLabel = trackName;
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
// @name is typically null except for default track
|
|
527
|
+
// but lang_translated seems to be reliable
|
|
528
|
+
trackName = '';
|
|
529
|
+
trackLabel = $(this).attr('lang_translated');
|
|
530
|
+
}
|
|
531
|
+
if (trackLabel === '') {
|
|
532
|
+
trackLabel = thisObj.getLanguageName(trackLang);
|
|
533
|
+
}
|
|
534
|
+
// assign the default track based on language of the player
|
|
535
|
+
if (trackLang === thisObj.lang) {
|
|
536
|
+
isDefaultTrack = true;
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
isDefaultTrack = false;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Build URL for retrieving WebVTT source via YouTube's timedtext API
|
|
543
|
+
var srcUrl = thisObj.getYouTubeTimedTextUrl(youTubeId,trackName,trackLang);
|
|
544
|
+
thisObj.tracks.push({
|
|
545
|
+
'kind': 'captions',
|
|
546
|
+
'src': srcUrl,
|
|
547
|
+
'language': trackLang,
|
|
548
|
+
'label': trackLabel,
|
|
549
|
+
'def': isDefaultTrack
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
});
|
|
553
|
+
// setupPopups again with new captions array, replacing original
|
|
554
|
+
thisObj.setupPopups('captions');
|
|
555
|
+
deferred.resolve();
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
thisObj.hasCaptions = false;
|
|
559
|
+
thisObj.usingYouTubeCaptions = false;
|
|
560
|
+
deferred.resolve();
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
error: function(xhr, status) {
|
|
564
|
+
console.log('Error retrieving YouTube caption data for video ' + youTubeId);
|
|
565
|
+
deferred.resolve();
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
return promise;
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
AblePlayer.prototype.getYouTubeTimedTextUrl = function (youTubeId, trackName, trackLang) {
|
|
572
|
+
|
|
573
|
+
// return URL for retrieving WebVTT source via YouTube's timedtext API
|
|
574
|
+
// Note: This API seems to be undocumented, and could break anytime
|
|
575
|
+
var url = 'https://www.youtube.com/api/timedtext?fmt=vtt';
|
|
576
|
+
url += '&v=' + youTubeId;
|
|
577
|
+
url += '&lang=' + trackLang;
|
|
578
|
+
// if track has a value in the name field, it's *required* in the URL
|
|
579
|
+
if (trackName !== '') {
|
|
580
|
+
url += '&name=' + trackName;
|
|
581
|
+
}
|
|
582
|
+
return url;
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
AblePlayer.prototype.getYouTubeCaptionCues = function (youTubeId) {
|
|
587
|
+
|
|
588
|
+
var deferred, promise, thisObj;
|
|
589
|
+
|
|
590
|
+
var deferred = new $.Deferred();
|
|
591
|
+
var promise = deferred.promise();
|
|
592
|
+
|
|
593
|
+
thisObj = this;
|
|
594
|
+
|
|
595
|
+
this.tracks = [];
|
|
596
|
+
this.tracks.push({
|
|
597
|
+
'kind': 'captions',
|
|
598
|
+
'src': 'some_file.vtt',
|
|
599
|
+
'language': 'en',
|
|
600
|
+
'label': 'Fake English captions'
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
deferred.resolve();
|
|
604
|
+
return promise;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
AblePlayer.prototype.initYouTubeCaptionModule = function () {
|
|
608
|
+
|
|
609
|
+
// This function is called when YouTube onApiChange event fires
|
|
610
|
+
// to indicate that the player has loaded (or unloaded) a module with exposed API methods
|
|
611
|
+
// it isn't fired until the video starts playing
|
|
612
|
+
// and only fires if captions are available for this video (automated captions don't count)
|
|
613
|
+
// If no captions are available, onApichange event never fires & this function is never called
|
|
614
|
+
|
|
615
|
+
// YouTube iFrame API documentation is incomplete related to captions
|
|
616
|
+
// Found undocumented features on user forums and by playing around
|
|
617
|
+
// Details are here: http://terrillthompson.com/blog/648
|
|
618
|
+
// Summary:
|
|
619
|
+
// User might get either the AS3 (Flash) or HTML5 YouTube player
|
|
620
|
+
// The API uses a different caption module for each player (AS3 = 'cc'; HTML5 = 'captions')
|
|
621
|
+
// There are differences in the data and methods available through these modules
|
|
622
|
+
// This function therefore is used to determine which captions module is being used
|
|
623
|
+
// If it's a known module, this.ytCaptionModule will be used elsewhere to control captions
|
|
624
|
+
var options, fontSize, displaySettings;
|
|
625
|
+
|
|
626
|
+
options = this.youTubePlayer.getOptions();
|
|
627
|
+
if (options.length) {
|
|
628
|
+
for (var i=0; i<options.length; i++) {
|
|
629
|
+
if (options[i] == 'cc') { // this is the AS3 (Flash) player
|
|
630
|
+
this.ytCaptionModule = 'cc';
|
|
631
|
+
if (!this.hasCaptions) {
|
|
632
|
+
// there are captions available via other sources (e.g., <track>)
|
|
633
|
+
// so use these
|
|
634
|
+
this.hasCaptions = true;
|
|
635
|
+
this.usingYouTubeCaptions = true;
|
|
636
|
+
}
|
|
637
|
+
break;
|
|
638
|
+
}
|
|
639
|
+
else if (options[i] == 'captions') { // this is the HTML5 player
|
|
640
|
+
this.ytCaptionModule = 'captions';
|
|
641
|
+
if (!this.hasCaptions) {
|
|
642
|
+
// there are captions available via other sources (e.g., <track>)
|
|
643
|
+
// so use these
|
|
644
|
+
this.hasCaptions = true;
|
|
645
|
+
this.usingYouTubeCaptions = true;
|
|
646
|
+
}
|
|
647
|
+
break;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
if (typeof this.ytCaptionModule !== 'undefined') {
|
|
651
|
+
if (this.usingYouTubeCaptions) {
|
|
652
|
+
// set default languaage
|
|
653
|
+
this.youTubePlayer.setOption(this.ytCaptionModule, 'track', {'languageCode': this.captionLang});
|
|
654
|
+
// set font size using Able Player prefs (values are -1, 0, 1, 2, and 3, where 0 is default)
|
|
655
|
+
this.youTubePlayer.setOption(this.ytCaptionModule,'fontSize',this.translatePrefs('size',this.prefCaptionsSize,'youtube'));
|
|
656
|
+
// ideally could set other display options too, but no others seem to be supported by setOption()
|
|
657
|
+
}
|
|
658
|
+
else {
|
|
659
|
+
// now that we know which cc module was loaded, unload it!
|
|
660
|
+
// we don't want it if we're using local <track> elements for captions
|
|
661
|
+
this.youTubePlayer.unloadModule(this.ytCaptionModule)
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
// no modules were loaded onApiChange
|
|
667
|
+
// unfortunately, gonna have to disable captions if we can't control them
|
|
668
|
+
this.hasCaptions = false;
|
|
669
|
+
this.usingYouTubeCaptions = false;
|
|
670
|
+
}
|
|
671
|
+
this.refreshControls('captions');
|
|
672
|
+
};
|
|
673
|
+
|
|
674
|
+
AblePlayer.prototype.getYouTubePosterUrl = function (youTubeId, width) {
|
|
675
|
+
|
|
676
|
+
// return a URL for retrieving a YouTube poster image
|
|
677
|
+
// supported values of width: 120, 320, 480, 640
|
|
678
|
+
|
|
679
|
+
var url = 'https://img.youtube.com/vi/' + youTubeId;
|
|
680
|
+
if (width == '120') {
|
|
681
|
+
// default (small) thumbnail, 120 x 90
|
|
682
|
+
return url + '/default.jpg';
|
|
683
|
+
}
|
|
684
|
+
else if (width == '320') {
|
|
685
|
+
// medium quality thumbnail, 320 x 180
|
|
686
|
+
return url + '/hqdefault.jpg';
|
|
687
|
+
}
|
|
688
|
+
else if (width == '480') {
|
|
689
|
+
// high quality thumbnail, 480 x 360
|
|
690
|
+
return url + '/hqdefault.jpg';
|
|
691
|
+
}
|
|
692
|
+
else if (width == '640') {
|
|
693
|
+
// standard definition poster image, 640 x 480
|
|
694
|
+
return url + '/sddefault.jpg';
|
|
695
|
+
}
|
|
696
|
+
return false;
|
|
697
|
+
};
|
|
481
698
|
|
|
482
699
|
})(jQuery);
|