wai-website-theme 1.3.1 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/_includes/different.html +2 -1
  3. data/_includes/external.html +2 -1
  4. data/_includes/header.html +2 -1
  5. data/_includes/menuitem.html +6 -2
  6. data/_includes/peoplelist.html +21 -0
  7. data/_includes/prevnext-navigation.html +56 -0
  8. data/_includes/{prevnext.html → prevnext-order.html} +9 -0
  9. data/_includes/translation-note-msg.html +5 -3
  10. data/_includes/video-player.html +2 -2
  11. data/_layouts/default.html +8 -1
  12. data/_layouts/news.html +7 -1
  13. data/_layouts/policy.html +7 -1
  14. data/_layouts/sidenav.html +8 -1
  15. data/_layouts/sidenavsidebar.html +8 -1
  16. data/assets/ableplayer/Gruntfile.js +2 -1
  17. data/assets/ableplayer/README.md +158 -85
  18. data/assets/ableplayer/build/ableplayer.dist.js +15445 -13823
  19. data/assets/ableplayer/build/ableplayer.js +15445 -13823
  20. data/assets/ableplayer/build/ableplayer.min.css +1 -2
  21. data/assets/ableplayer/build/ableplayer.min.js +3 -10
  22. data/assets/ableplayer/package-lock.json +944 -346
  23. data/assets/ableplayer/package.json +8 -8
  24. data/assets/ableplayer/scripts/ableplayer-base.js +515 -524
  25. data/assets/ableplayer/scripts/browser.js +158 -158
  26. data/assets/ableplayer/scripts/buildplayer.js +1750 -1682
  27. data/assets/ableplayer/scripts/caption.js +424 -401
  28. data/assets/ableplayer/scripts/chapters.js +259 -259
  29. data/assets/ableplayer/scripts/control.js +1831 -1594
  30. data/assets/ableplayer/scripts/description.js +333 -256
  31. data/assets/ableplayer/scripts/dialog.js +145 -145
  32. data/assets/ableplayer/scripts/dragdrop.js +746 -749
  33. data/assets/ableplayer/scripts/event.js +875 -696
  34. data/assets/ableplayer/scripts/initialize.js +819 -912
  35. data/assets/ableplayer/scripts/langs.js +979 -743
  36. data/assets/ableplayer/scripts/metadata.js +124 -124
  37. data/assets/ableplayer/scripts/misc.js +170 -137
  38. data/assets/ableplayer/scripts/preference.js +904 -904
  39. data/assets/ableplayer/scripts/search.js +172 -172
  40. data/assets/ableplayer/scripts/sign.js +82 -78
  41. data/assets/ableplayer/scripts/slider.js +449 -448
  42. data/assets/ableplayer/scripts/track.js +409 -309
  43. data/assets/ableplayer/scripts/transcript.js +684 -595
  44. data/assets/ableplayer/scripts/translation.js +63 -67
  45. data/assets/ableplayer/scripts/ttml2webvtt.js +85 -85
  46. data/assets/ableplayer/scripts/vimeo.js +448 -0
  47. data/assets/ableplayer/scripts/volume.js +395 -380
  48. data/assets/ableplayer/scripts/vts.js +1077 -1077
  49. data/assets/ableplayer/scripts/webvtt.js +766 -763
  50. data/assets/ableplayer/scripts/youtube.js +695 -478
  51. data/assets/ableplayer/styles/ableplayer.css +54 -46
  52. data/assets/ableplayer/translations/nl.js +54 -54
  53. data/assets/ableplayer/translations/pt-br.js +311 -0
  54. data/assets/ableplayer/translations/tr.js +311 -0
  55. data/assets/ableplayer/translations/zh-tw.js +1 -1
  56. data/assets/css/style.css +1 -1
  57. data/assets/css/style.css.map +1 -1
  58. data/assets/images/icons.svg +5 -5
  59. data/assets/scripts/main.js +7 -0
  60. data/assets/search/tipuesearch.js +3 -3
  61. metadata +8 -3
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ableplayer",
3
- "version": "3.2.0",
3
+ "version": "4.0.00",
4
4
  "description": "fully accessible HTML5 media player",
5
5
  "homepage": "http://ableplayer.github.io/ableplayer",
6
6
  "bugs": "https://github.com/ableplayer/ableplayer/issues",
@@ -19,13 +19,13 @@
19
19
  "xml-js": "1.6.2"
20
20
  },
21
21
  "devDependencies": {
22
- "grunt": ">=0.4.1",
23
- "grunt-contrib-clean": ">=0.6.0",
24
- "grunt-contrib-concat": ">=0.3.0",
25
- "grunt-contrib-copy": ">=0.4.1",
26
- "grunt-contrib-cssmin": ">=0.6.1",
27
- "grunt-contrib-jshint": "^0.10.0",
28
- "grunt-contrib-uglify": ">=0.2.2",
22
+ "grunt": "^1.0.4",
23
+ "grunt-contrib-clean": "^2.0.0",
24
+ "grunt-contrib-concat": "^1.0.1",
25
+ "grunt-contrib-copy": "^1.0.0",
26
+ "grunt-contrib-cssmin": "^3.0.0",
27
+ "grunt-contrib-jshint": "^2.1.0",
28
+ "grunt-contrib-uglify": "^4.0.1",
29
29
  "grunt-remove-logging": ">=0.2.0"
30
30
  }
31
31
  }
@@ -1,33 +1,33 @@
1
1
  /*
2
- // JavaScript for Able Player
2
+ // JavaScript for Able Player
3
3
 
4
- // HTML5 Media API:
5
- // http://www.w3.org/TR/html5/embedded-content-0.html#htmlmediaelement
6
- // http://dev.w3.org/html5/spec-author-view/video.html
4
+ // HTML5 Media API:
5
+ // http://www.w3.org/TR/html5/embedded-content-0.html#htmlmediaelement
6
+ // http://dev.w3.org/html5/spec-author-view/video.html
7
7
 
8
- // W3C API Test Page:
9
- // http://www.w3.org/2010/05/video/mediaevents.html
8
+ // W3C API Test Page:
9
+ // http://www.w3.org/2010/05/video/mediaevents.html
10
10
 
11
- // Uses JW Player as fallback
12
- // JW Player configuration options:
13
- // http://support.jwplayer.com/customer/portal/articles/1413113-configuration-options-reference
14
- // (NOTE: some options are not documented, e.g., volume)
15
- // JW Player 6 API reference:
16
- // http://support.jwplayer.com/customer/portal/articles/1413089-javascript-api-reference
11
+ // YouTube Player API for iframe Embeds
12
+ https://developers.google.com/youtube/iframe_api_reference
13
+ // YouTube Player Parameters
14
+ https://developers.google.com/youtube/player_parameters?playerVersion=HTML5
17
15
 
18
- // YouTube Player API for iframe Embeds
19
- https://developers.google.com/youtube/iframe_api_reference
20
- // YouTube Player Parameters
21
- https://developers.google.com/youtube/player_parameters?playerVersion=HTML5
16
+ // YouTube Data API
17
+ https://developers.google.com/youtube/v3
22
18
 
23
- // YouTube Data API
24
- https://developers.google.com/youtube/v3
19
+ // Vimeo Player API
20
+ https://github.com/vimeo/player.js
25
21
 
26
- // Google API Client Library for JavaScript
27
- https://developers.google.com/api-client-library/javascript/dev/dev_jscript
22
+ // Google API Client Library for JavaScript
23
+ https://developers.google.com/api-client-library/javascript/dev/dev_jscript
28
24
 
29
- // Google API Explorer: YouTube services and methods
30
- https://developers.google.com/apis-explorer/#s/youtube/v3/
25
+ // Google API Explorer: YouTube services and methods
26
+ https://developers.google.com/apis-explorer/#s/youtube/v3/
27
+
28
+ // Web Speech API (Speech Synthesis)
29
+ // https://w3c.github.io/speech-api/#tts-section
30
+ // https://developer.mozilla.org/en-US/docs/Web/API/Window/speechSynthesis
31
31
  */
32
32
 
33
33
  /*jslint node: true, browser: true, white: true, indent: 2, unparam: true, plusplus: true */
@@ -35,506 +35,497 @@
35
35
  "use strict";
36
36
 
37
37
  (function ($) {
38
- $(document).ready(function () {
39
- $('video, audio').each(function (index, element) {
40
- if ($(element).data('able-player') !== undefined) {
41
- new AblePlayer($(this),$(element));
42
- }
43
- });
44
- });
45
-
46
- // YouTube player support; pass ready event to jQuery so we can catch in player.
47
- window.onYouTubeIframeAPIReady = function() {
48
- AblePlayer.youtubeIframeAPIReady = true;
49
- $('body').trigger('youtubeIframeAPIReady', []);
50
- };
51
-
52
- // If there is only one player on the page, dispatch global keydown events to it
53
- // Otherwise, keydowwn events are handled locally (see event.js > handleEventListeners())
54
- $(window).keydown(function(e) {
55
- if (AblePlayer.nextIndex === 1) {
56
- AblePlayer.lastCreated.onPlayerKeyPress(e);
57
- }
58
- });
59
-
60
- // Construct an AblePlayer object
61
- // Parameters are:
62
- // media - jQuery selector or element identifying the media.
63
- window.AblePlayer = function(media) {
64
-
65
- // Keep track of the last player created for use with global events.
66
- AblePlayer.lastCreated = this;
67
-
68
- this.media = media;
69
- if ($(media).length === 0) {
70
- this.provideFallback();
71
- return;
72
- }
73
-
74
- ///////////////////////////////
75
- //
76
- // Default variables assignment
77
- //
78
- ///////////////////////////////
79
-
80
- // The following variables CAN be overridden with HTML attributes
81
-
82
- // autoplay (Boolean; if present always resolves to true, regardless of value)
83
- if ($(media).attr('autoplay') !== undefined) {
84
- this.autoplay = true;
85
- }
86
- else {
87
- this.autoplay = false;
88
- }
89
-
90
- // loop (Boolean; if present always resolves to true, regardless of value)
91
- if ($(media).attr('loop') !== undefined) {
92
- this.loop = true;
93
- }
94
- else {
95
- this.loop = false;
96
- }
97
-
98
- // playsinline (Boolean; if present always resolves to true, regardless of value)
99
- if ($(media).attr('playsinline') !== undefined) {
100
- this.playsInline = '1'; // this value gets passed to YT.Player contructor in youtube.js
101
- }
102
- else {
103
- this.playsInline = '0';
104
- }
105
-
106
- // start-time
107
- if ($(media).data('start-time') !== undefined && $.isNumeric($(media).data('start-time'))) {
108
- this.startTime = $(media).data('start-time');
109
- }
110
- else {
111
- this.startTime = 0;
112
- }
113
-
114
- // debug
115
- if ($(media).data('debug') !== undefined && $(media).data('debug') !== false) {
116
- this.debug = true;
117
- }
118
- else {
119
- this.debug = false;
120
- }
121
-
122
- // Path to root directory of Able Player code
123
- if ($(media).data('root-path') !== undefined) {
124
- // add a trailing slash if there is none
125
- this.rootPath = $(media).data('root-path').replace(/\/?$/, '/');
126
- }
127
- else {
128
- this.rootPath = this.getRootPath();
129
- }
130
-
131
- // Volume
132
- // Range is 0 to 10. Best not to crank it to avoid overpowering screen readers
133
- this.defaultVolume = 7;
134
- if ($(media).data('volume') !== undefined && $(media).data('volume') !== "") {
135
- var volume = $(media).data('volume');
136
- if (volume >= 0 && volume <= 10) {
137
- this.defaultVolume = volume;
138
- }
139
- }
140
- this.volume = this.defaultVolume;
141
-
142
- // Optional Buttons
143
- // Buttons are added to the player controller if relevant media is present
144
- // However, in some applications it might be undesirable to show buttons
145
- // (e.g., if chapters or transcripts are provided in an external container)
146
-
147
- if ($(media).data('use-chapters-button') !== undefined && $(media).data('use-chapters-button') === false) {
148
- this.useChaptersButton = false;
149
- }
150
- else {
151
- this.useChaptersButton = true;
152
- }
153
-
154
- if ($(media).data('use-descriptions-button') !== undefined && $(media).data('use-descriptions-button') === false) {
155
- this.useDescriptionsButton = false;
156
- }
157
- else {
158
- this.useDescriptionsButton = true;
159
- }
160
-
161
- // Headings
162
- // By default, an off-screen heading is automatically added to the top of the media player
163
- // It is intelligently assigned a heading level based on context, via misc.js > getNextHeadingLevel()
164
- // Authors can override this behavior by manually assigning a heading level using data-heading-level
165
- // Accepted values are 1-6, or 0 which indicates "no heading"
166
- // (i.e., author has already hard-coded a heading before the media player; Able Player doesn't need to do this)
167
- if ($(media).data('heading-level') !== undefined && $(media).data('heading-level') !== "") {
168
- var headingLevel = $(media).data('heading-level');
169
- if (/^[0-6]*$/.test(headingLevel)) { // must be a valid HTML heading level 1-6; or 0
170
- this.playerHeadingLevel = headingLevel;
171
- }
172
- }
173
-
174
- // Transcripts
175
- // There are three types of interactive transcripts.
176
- // In descending of order of precedence (in case there are conflicting tags), they are:
177
- // 1. "manual" - A manually coded external transcript (requires data-transcript-src)
178
- // 2. "external" - Automatically generated, written to an external div (requires data-transcript-div)
179
- // 3. "popup" - Automatically generated, written to a draggable, resizable popup window that can be toggled on/off with a button
180
- // If data-include-transcript="false", there is no "popup" transcript
181
-
182
- this.transcriptType = null;
183
- if ($(media).data('transcript-src') !== undefined) {
184
- this.transcriptSrc = $(media).data('transcript-src');
185
- if (this.transcriptSrcHasRequiredParts()) {
186
- this.transcriptType = 'manual';
187
- }
188
- else {
189
- this.transcriptType = null;
190
- }
191
- }
192
- else if ($(media).find('track[kind="captions"], track[kind="subtitles"]').length > 0) {
193
- // required tracks are present. COULD automatically generate a transcript
194
- if ($(media).data('transcript-div') !== undefined && $(media).data('transcript-div') !== "") {
195
- this.transcriptDivLocation = $(media).data('transcript-div');
196
- this.transcriptType = 'external';
197
- }
198
- else if ($(media).data('include-transcript') !== undefined) {
199
- if ($(media).data('include-transcript') !== false) {
200
- this.transcriptType = 'popup';
201
- }
202
- }
203
- else {
204
- this.transcriptType = 'popup';
205
- }
206
- }
207
-
208
- // In "Lyrics Mode", line breaks in WebVTT caption files are supported in the transcript
209
- // If false (default), line breaks are are removed from transcripts in order to provide a more seamless reading experience
210
- // If true, line breaks are preserved, so content can be presented karaoke-style, or as lines in a poem
211
- if ($(media).data('lyrics-mode') !== undefined && $(media).data('lyrics-mode') !== false) {
212
- this.lyricsMode = true;
213
- }
214
- else {
215
- this.lyricsMode = false;
216
- }
217
-
218
- // Transcript Title
219
- if ($(media).data('transcript-title') !== undefined && $(media).data('transcript-title') !== "") {
220
- this.transcriptTitle = $(media).data('transcript-title');
221
- }
222
- else {
223
- // do nothing. The default title will be defined later (see transcript.js)
224
- }
225
-
226
- // Captions
227
- // data-captions-position can be used to set the default captions position
228
- // this is only the default, and can be overridden by user preferences
229
- // valid values of data-captions-position are 'below' and 'overlay'
230
- if ($(media).data('captions-position') === 'overlay') {
231
- this.defaultCaptionsPosition = 'overlay';
232
- }
233
- else { // the default, even if not specified
234
- this.defaultCaptionsPosition = 'below';
235
- }
236
-
237
- // Chapters
238
- if ($(media).data('chapters-div') !== undefined && $(media).data('chapters-div') !== "") {
239
- this.chaptersDivLocation = $(media).data('chapters-div');
240
- }
241
-
242
- if ($(media).data('chapters-title') !== undefined) {
243
- // NOTE: empty string is valid; results in no title being displayed
244
- this.chaptersTitle = $(media).data('chapters-title');
245
- }
246
-
247
- if ($(media).data('chapters-default') !== undefined && $(media).data('chapters-default') !== "") {
248
- this.defaultChapter = $(media).data('chapters-default');
249
- }
250
- else {
251
- this.defaultChapter = null;
252
- }
253
-
254
- // Previous/Next buttons
255
- // valid values of data-prevnext-unit are 'playlist' and 'chapter'; will also accept 'chapters'
256
- if ($(media).data('prevnext-unit') === 'chapter' || $(media).data('prevnext-unit') === 'chapters') {
257
- this.prevNextUnit = 'chapter';
258
- }
259
- else if ($(media).data('prevnext-unit') === 'playlist') {
260
- this.prevNextUnit = 'playlist';
261
- }
262
- else {
263
- this.prevNextUnit = false;
264
- }
265
-
266
- // Slower/Faster buttons
267
- // valid values of data-speed-icons are 'animals' (default) and 'arrows'
268
- // 'animals' uses turtle and rabbit; 'arrows' uses up/down arrows
269
- if ($(media).data('speed-icons') === 'arrows') {
270
- this.speedIcons = 'arrows';
271
- }
272
- else {
273
- this.speedIcons = 'animals';
274
- }
275
-
276
- // Seekbar
277
- // valid values of data-seekbar-scope are 'chapter' and 'video'; will also accept 'chapters'
278
- if ($(media).data('seekbar-scope') === 'chapter' || $(media).data('seekbar-scope') === 'chapters') {
279
- this.seekbarScope = 'chapter';
280
- }
281
- else {
282
- this.seekbarScope = 'video';
283
- }
284
-
285
- // YouTube
286
- if ($(media).data('youtube-id') !== undefined && $(media).data('youtube-id') !== "") {
287
- this.youTubeId = $(media).data('youtube-id');
288
- }
289
-
290
- if ($(media).data('youtube-desc-id') !== undefined && $(media).data('youtube-desc-id') !== "") {
291
- this.youTubeDescId = $(media).data('youtube-desc-id');
292
- }
293
-
294
- if ($(media).data('youtube-nocookie') !== undefined && $(media).data('youtube-nocookie')) {
295
- this.youTubeNoCookie = true;
296
- }
297
- else {
298
- this.youTubeNoCookie = false;
299
- }
300
-
301
- // Icon type
302
- // By default, AblePlayer 3.0.33 and higher uses SVG icons for the player controls
303
- // Fallback for browsers that don't support SVG is scalable icomoon fonts
304
- // Ultimate fallback is images, if the user has a custom style sheet that overrides font-family
305
- // Use data-icon-type to force controls to use either 'svg', 'font', or 'images'
306
- this.iconType = 'font';
307
- this.forceIconType = false;
308
- if ($(media).data('icon-type') !== undefined && $(media).data('icon-type') !== "") {
309
- var iconType = $(media).data('icon-type');
310
- if (iconType === 'font' || iconType == 'image' || iconType == 'svg') {
311
- this.iconType = iconType;
312
- this.forceIconType = true;
313
- }
314
- }
315
-
316
- if ($(media).data('allow-fullscreen') !== undefined && $(media).data('allow-fullscreen') === false) {
317
- this.allowFullScreen = false;
318
- }
319
- else {
320
- this.allowFullScreen = true;
321
- }
322
-
323
- // Seek interval
324
- // Number of seconds to seek forward or back with Rewind & Forward buttons
325
- // Unless specified with data-seek-interval, the default value is re-calculated in initialize.js > setSeekInterval();
326
- // Calculation attempts to intelligently assign a reasonable interval based on media length
327
- this.defaultSeekInterval = 10;
328
- this.useFixedSeekInterval = false;
329
- if ($(media).data('seek-interval') !== undefined && $(media).data('seek-interval') !== "") {
330
- var seekInterval = $(media).data('seek-interval');
331
- if (/^[1-9][0-9]*$/.test(seekInterval)) { // must be a whole number greater than 0
332
- this.seekInterval = seekInterval;
333
- this.useFixedSeekInterval = true; // do not override with calculuation
334
- }
335
- }
336
-
337
- // Now Playing
338
- // Shows "Now Playing:" plus the title of the current track above player
339
- // Only used if there is a playlist
340
- if ($(media).data('show-now-playing') !== undefined && $(media).data('show-now-playing') === false) {
341
- this.showNowPlaying = false;
342
- }
343
- else {
344
- this.showNowPlaying = true;
345
- }
346
-
347
- // TTML support (experimental); enabled for testing with data-use-ttml (Boolean)
348
- if ($(media).data('use-ttml') !== undefined) {
349
- this.useTtml = true;
350
- // The following may result in a console error.
351
- this.convert = require('xml-js');
352
- }
353
- else {
354
- this.useTtml = false;
355
- }
356
-
357
- // Fallback Player
358
- // The only supported fallback is JW Player, licensed separately
359
- // JW Player files must be included in folder specified in this.fallbackPath
360
- // JW Player will be loaded as needed in browsers that don't support HTML5 media
361
- // NOTE: As of 2.3.44, NO FALLBACK is used unless data-fallback='jw'
362
-
363
- this.fallback = null;
364
- this.fallbackPath = null;
365
- this.fallbackJwKey = null;
366
- this.testFallback = false;
367
-
368
- if ($(media).data('fallback') !== undefined && $(media).data('fallback') !== "") {
369
- var fallback = $(media).data('fallback');
370
- if (fallback === 'jw') {
371
- this.fallback = fallback;
372
- }
373
- }
374
-
375
- if (this.fallback === 'jw') {
376
-
377
- if ($(media).data('fallback-path') !== undefined && $(media).data('fallback-path') !== false) {
378
- this.fallbackPath = $(media).data('fallback-path');
379
-
380
- var path = $(media).data('fallback-path');
381
-
382
- // remove js file is specified.
383
- var playerJs = 'jwplayer.js';
384
- if (path.endsWith(playerJs)) {
385
- path = path.slice(0, path.length - playerJs.length);
386
- }
387
- this.fallbackPath = path;
388
- } else {
389
- this.fallbackPath = this.rootPath + 'thirdparty/';
390
- }
391
-
392
- if ($(media).data('fallback-jwkey') !== undefined) {
393
- this.fallbackJwKey = $(media).data('fallback-jwkey');
394
- }
395
-
396
- if ($(media).data('test-fallback') !== undefined && $(media).data('test-fallback') !== false) {
397
- this.testFallback = true;
398
- }
399
- }
400
-
401
- // Language
402
- this.lang = 'en';
403
- if ($(media).data('lang') !== undefined && $(media).data('lang') !== "") {
404
- var lang = $(media).data('lang');
405
- if (lang.length == 2) {
406
- this.lang = lang;
407
- }
408
- }
409
- // Player language is determined as follows (in translation.js > getTranslationText() ):
410
- // 1. Lang attributes on <html> or <body>, if a matching translation file is available
411
- // 2. The value of this.lang, if a matching translation file is available
412
- // 3. English
413
- // To override this formula and force #2 to take precedence over #1, set data-force-lang="true"
414
- if ($(media).data('force-lang') !== undefined && $(media).data('force-lang') !== false) {
415
- this.forceLang = true;
416
- }
417
- else {
418
- this.forceLang = false;
419
- }
420
-
421
- // Metadata Tracks
422
- if ($(media).data('meta-type') !== undefined && $(media).data('meta-type') !== "") {
423
- this.metaType = $(media).data('meta-type');
424
- }
425
-
426
- if ($(media).data('meta-div') !== undefined && $(media).data('meta-div') !== "") {
427
- this.metaDiv = $(media).data('meta-div');
428
- }
429
-
430
- // Search
431
- if ($(media).data('search') !== undefined && $(media).data('search') !== "") {
432
- // conducting a search currently requires an external div in which to write the results
433
- if ($(media).data('search-div') !== undefined && $(media).data('search-div') !== "") {
434
- this.searchString = $(media).data('search');
435
- this.searchDiv = $(media).data('search-div');
436
- }
437
-
438
- // Search Language
439
- if ($(media).data('search-lang') !== undefined && $(media).data('search-lang') !== "") {
440
- this.searchLang = $(media).data('search-lang');
441
- }
442
- else {
443
- this.searchLang = null; // will change to final value of this.lang in translation.js > getTranslationText()
444
- }
445
-
446
- // conducting a search currently requires an external div in which to write the results
447
- if ($(media).data('search-div') !== undefined && $(media).data('search-div') !== "") {
448
- this.searchString = $(media).data('search');
449
- this.searchDiv = $(media).data('search-div');
450
- }
451
- }
452
-
453
- // Hide controls when video starts playing
454
- // They will reappear again when user presses a key or moves the mouse
455
- if ($(media).data('hide-controls') !== undefined && $(media).data('hide-controls') !== false) {
456
- this.hideControls = true;
457
- }
458
- else {
459
- this.hideControls = false;
460
- }
461
-
462
- // Define built-in variables that CANNOT be overridden with HTML attributes
463
- this.setDefaults();
464
-
465
- ////////////////////////////////////////
466
- //
467
- // End assignment of default variables
468
- //
469
- ////////////////////////////////////////
470
-
471
- this.ableIndex = AblePlayer.nextIndex;
472
- AblePlayer.nextIndex += 1;
473
-
474
- this.title = $(media).attr('title');
475
-
476
- // populate translation object with localized versions of all labels and prompts
477
- // use defer method to defer additional processing until text is retrieved
478
- this.tt = {};
479
- var thisObj = this;
480
- $.when(this.getTranslationText()).then(
481
- function () {
482
- if (thisObj.countProperties(thisObj.tt) > 50) {
483
- // close enough to ensure that most text variables are populated
484
- thisObj.setup();
485
- }
486
- else {
487
- // can't continue loading player with no text
488
- thisObj.provideFallback();
489
- }
490
- }
491
- );
492
- };
493
-
494
- // Index to increment every time new player is created.
495
- AblePlayer.nextIndex = 0;
496
-
497
- AblePlayer.prototype.setup = function() {
498
- var thisObj = this;
499
- this.reinitialize().then(function () {
500
- if (!thisObj.player) {
501
- // No player for this media, show last-line fallback.
502
- thisObj.provideFallback();
503
- }
504
- else {
505
- thisObj.setupInstance().then(function () {
506
- thisObj.recreatePlayer();
507
- });
508
- }
509
- });
510
- };
511
-
512
- AblePlayer.getActiveDOMElement = function () {
513
- var activeElement = document.activeElement;
514
-
515
- // For shadow DOMs we need to keep digging down through the DOMs
516
- while (activeElement.shadowRoot && activeElement.shadowRoot.activeElement) {
517
- activeElement = activeElement.shadowRoot.activeElement;
518
- }
519
-
520
- return activeElement;
521
- };
522
-
523
- AblePlayer.localGetElementById = function(element, id) {
524
- if (element.getRootNode)
525
- {
526
- // Use getRootNode() and querySelector() where supported (for shadow DOM support)
527
- return $(element.getRootNode().querySelector('#' + id));
528
- }
529
- else
530
- {
531
- // If getRootNode is not supported it should be safe to use document.getElementById (since there is no shadow DOM support)
532
- return $(document.getElementById(id));
533
- }
534
- };
535
-
536
-
537
-
538
- AblePlayer.youtubeIframeAPIReady = false;
539
- AblePlayer.loadingYoutubeIframeAPI = false;
38
+ $(document).ready(function () {
39
+ $('video, audio').each(function (index, element) {
40
+ if ($(element).data('able-player') !== undefined) {
41
+ new AblePlayer($(this),$(element));
42
+ }
43
+ });
44
+ });
45
+
46
+ // YouTube player support; pass ready event to jQuery so we can catch in player.
47
+ window.onYouTubeIframeAPIReady = function() {
48
+ AblePlayer.youtubeIframeAPIReady = true;
49
+ $('body').trigger('youtubeIframeAPIReady', []);
50
+ };
51
+
52
+ // If there is only one player on the page, dispatch global keydown events to it
53
+ // Otherwise, keydowwn events are handled locally (see event.js > handleEventListeners())
54
+ $(window).keydown(function(e) {
55
+ if (AblePlayer.nextIndex === 1) {
56
+ AblePlayer.lastCreated.onPlayerKeyPress(e);
57
+ }
58
+ });
59
+
60
+ // Construct an AblePlayer object
61
+ // Parameters are:
62
+ // media - jQuery selector or element identifying the media.
63
+ window.AblePlayer = function(media) {
64
+
65
+ // Keep track of the last player created for use with global events.
66
+ AblePlayer.lastCreated = this;
67
+
68
+ this.media = media;
69
+ if ($(media).length === 0) {
70
+ this.provideFallback();
71
+ return;
72
+ }
73
+
74
+ ///////////////////////////////
75
+ //
76
+ // Default variables assignment
77
+ //
78
+ ///////////////////////////////
79
+
80
+ // The following variables CAN be overridden with HTML attributes
81
+
82
+ // autoplay (Boolean; if present always resolves to true, regardless of value)
83
+ if ($(media).attr('autoplay') !== undefined) {
84
+ this.autoplay = true; // this value remains constant
85
+ this.okToPlay = true; // this value can change dynamically
86
+ }
87
+ else {
88
+ this.autoplay = false;
89
+ this.okToPlay = false;
90
+ }
91
+
92
+ // loop (Boolean; if present always resolves to true, regardless of value)
93
+ if ($(media).attr('loop') !== undefined) {
94
+ this.loop = true;
95
+ }
96
+ else {
97
+ this.loop = false;
98
+ }
99
+
100
+ // playsinline (Boolean; if present always resolves to true, regardless of value)
101
+ if ($(media).attr('playsinline') !== undefined) {
102
+ this.playsInline = '1'; // this value gets passed to YT.Player contructor in youtube.js
103
+ }
104
+ else {
105
+ this.playsInline = '0';
106
+ }
107
+
108
+ // poster (Boolean, indicating whether media element has a poster attribute)
109
+ if ($(media).attr('poster')) {
110
+ this.hasPoster = true;
111
+ }
112
+ else {
113
+ this.hasPoster = false;
114
+ }
115
+
116
+ // start-time
117
+ if ($(media).data('start-time') !== undefined && $.isNumeric($(media).data('start-time'))) {
118
+ this.startTime = $(media).data('start-time');
119
+ }
120
+ else {
121
+ this.startTime = 0;
122
+ }
123
+
124
+ // debug
125
+ if ($(media).data('debug') !== undefined && $(media).data('debug') !== false) {
126
+ this.debug = true;
127
+ }
128
+ else {
129
+ this.debug = false;
130
+ }
131
+
132
+ // Path to root directory of Able Player code
133
+ if ($(media).data('root-path') !== undefined) {
134
+ // add a trailing slash if there is none
135
+ this.rootPath = $(media).data('root-path').replace(/\/?$/, '/');
136
+ }
137
+ else {
138
+ this.rootPath = this.getRootPath();
139
+ }
140
+
141
+ // Volume
142
+ // Range is 0 to 10. Best not to crank it to avoid overpowering screen readers
143
+ this.defaultVolume = 7;
144
+ if ($(media).data('volume') !== undefined && $(media).data('volume') !== "") {
145
+ var volume = $(media).data('volume');
146
+ if (volume >= 0 && volume <= 10) {
147
+ this.defaultVolume = volume;
148
+ }
149
+ }
150
+ this.volume = this.defaultVolume;
151
+
152
+ // Optional Buttons
153
+ // Buttons are added to the player controller if relevant media is present
154
+ // However, in some applications it might be undesirable to show buttons
155
+ // (e.g., if chapters or transcripts are provided in an external container)
156
+
157
+ if ($(media).data('use-chapters-button') !== undefined && $(media).data('use-chapters-button') === false) {
158
+ this.useChaptersButton = false;
159
+ }
160
+ else {
161
+ this.useChaptersButton = true;
162
+ }
163
+
164
+ if ($(media).data('use-descriptions-button') !== undefined && $(media).data('use-descriptions-button') === false) {
165
+ this.useDescriptionsButton = false;
166
+ }
167
+ else {
168
+ this.useDescriptionsButton = true;
169
+ }
170
+
171
+ // Headings
172
+ // By default, an off-screen heading is automatically added to the top of the media player
173
+ // It is intelligently assigned a heading level based on context, via misc.js > getNextHeadingLevel()
174
+ // Authors can override this behavior by manually assigning a heading level using data-heading-level
175
+ // Accepted values are 1-6, or 0 which indicates "no heading"
176
+ // (i.e., author has already hard-coded a heading before the media player; Able Player doesn't need to do this)
177
+ if ($(media).data('heading-level') !== undefined && $(media).data('heading-level') !== "") {
178
+ var headingLevel = $(media).data('heading-level');
179
+ if (/^[0-6]*$/.test(headingLevel)) { // must be a valid HTML heading level 1-6; or 0
180
+ this.playerHeadingLevel = headingLevel;
181
+ }
182
+ }
183
+
184
+ // Transcripts
185
+ // There are three types of interactive transcripts.
186
+ // In descending of order of precedence (in case there are conflicting tags), they are:
187
+ // 1. "manual" - A manually coded external transcript (requires data-transcript-src)
188
+ // 2. "external" - Automatically generated, written to an external div (requires data-transcript-div)
189
+ // 3. "popup" - Automatically generated, written to a draggable, resizable popup window that can be toggled on/off with a button
190
+ // If data-include-transcript="false", there is no "popup" transcript
191
+
192
+ this.transcriptType = null;
193
+ if ($(media).data('transcript-src') !== undefined) {
194
+ this.transcriptSrc = $(media).data('transcript-src');
195
+ if (this.transcriptSrcHasRequiredParts()) {
196
+ this.transcriptType = 'manual';
197
+ }
198
+ }
199
+ else if ($(media).find('track[kind="captions"], track[kind="subtitles"]').length > 0) {
200
+ // required tracks are present. COULD automatically generate a transcript
201
+ if ($(media).data('transcript-div') !== undefined && $(media).data('transcript-div') !== "") {
202
+ this.transcriptDivLocation = $(media).data('transcript-div');
203
+ this.transcriptType = 'external';
204
+ }
205
+ else if ($(media).data('include-transcript') !== undefined) {
206
+ if ($(media).data('include-transcript') !== false) {
207
+ this.transcriptType = 'popup';
208
+ }
209
+ }
210
+ else {
211
+ this.transcriptType = 'popup';
212
+ }
213
+ }
214
+
215
+ // In "Lyrics Mode", line breaks in WebVTT caption files are supported in the transcript
216
+ // If false (default), line breaks are are removed from transcripts in order to provide a more seamless reading experience
217
+ // If true, line breaks are preserved, so content can be presented karaoke-style, or as lines in a poem
218
+ if ($(media).data('lyrics-mode') !== undefined && $(media).data('lyrics-mode') !== false) {
219
+ this.lyricsMode = true;
220
+ }
221
+ else {
222
+ this.lyricsMode = false;
223
+ }
224
+
225
+ // Transcript Title
226
+ if ($(media).data('transcript-title') !== undefined && $(media).data('transcript-title') !== "") {
227
+ this.transcriptTitle = $(media).data('transcript-title');
228
+ }
229
+ else {
230
+ // do nothing. The default title will be defined later (see transcript.js)
231
+ }
232
+
233
+ // Captions
234
+ // data-captions-position can be used to set the default captions position
235
+ // this is only the default, and can be overridden by user preferences
236
+ // valid values of data-captions-position are 'below' and 'overlay'
237
+ if ($(media).data('captions-position') === 'overlay') {
238
+ this.defaultCaptionsPosition = 'overlay';
239
+ }
240
+ else { // the default, even if not specified
241
+ this.defaultCaptionsPosition = 'below';
242
+ }
243
+
244
+ // Chapters
245
+ if ($(media).data('chapters-div') !== undefined && $(media).data('chapters-div') !== "") {
246
+ this.chaptersDivLocation = $(media).data('chapters-div');
247
+ }
248
+
249
+ if ($(media).data('chapters-title') !== undefined) {
250
+ // NOTE: empty string is valid; results in no title being displayed
251
+ this.chaptersTitle = $(media).data('chapters-title');
252
+ }
253
+
254
+ if ($(media).data('chapters-default') !== undefined && $(media).data('chapters-default') !== "") {
255
+ this.defaultChapter = $(media).data('chapters-default');
256
+ }
257
+ else {
258
+ this.defaultChapter = null;
259
+ }
260
+
261
+ // Previous/Next buttons
262
+ // valid values of data-prevnext-unit are 'playlist' and 'chapter'; will also accept 'chapters'
263
+ if ($(media).data('prevnext-unit') === 'chapter' || $(media).data('prevnext-unit') === 'chapters') {
264
+ this.prevNextUnit = 'chapter';
265
+ }
266
+ else if ($(media).data('prevnext-unit') === 'playlist') {
267
+ this.prevNextUnit = 'playlist';
268
+ }
269
+ else {
270
+ this.prevNextUnit = false;
271
+ }
272
+
273
+ // Slower/Faster buttons
274
+ // valid values of data-speed-icons are 'animals' (default) and 'arrows'
275
+ // 'animals' uses turtle and rabbit; 'arrows' uses up/down arrows
276
+ if ($(media).data('speed-icons') === 'arrows') {
277
+ this.speedIcons = 'arrows';
278
+ }
279
+ else {
280
+ this.speedIcons = 'animals';
281
+ }
282
+
283
+ // Seekbar
284
+ // valid values of data-seekbar-scope are 'chapter' and 'video'; will also accept 'chapters'
285
+ if ($(media).data('seekbar-scope') === 'chapter' || $(media).data('seekbar-scope') === 'chapters') {
286
+ this.seekbarScope = 'chapter';
287
+ }
288
+ else {
289
+ this.seekbarScope = 'video';
290
+ }
291
+
292
+ // YouTube
293
+ if ($(media).data('youtube-id') !== undefined && $(media).data('youtube-id') !== "") {
294
+ this.youTubeId = $(media).data('youtube-id');
295
+ }
296
+
297
+ if ($(media).data('youtube-desc-id') !== undefined && $(media).data('youtube-desc-id') !== "") {
298
+ this.youTubeDescId = $(media).data('youtube-desc-id');
299
+ }
300
+
301
+ if ($(media).data('youtube-nocookie') !== undefined && $(media).data('youtube-nocookie')) {
302
+ this.youTubeNoCookie = true;
303
+ }
304
+ else {
305
+ this.youTubeNoCookie = false;
306
+ }
307
+
308
+ // Vimeo
309
+ if ($(media).data('vimeo-id') !== undefined && $(media).data('vimeo-id') !== "") {
310
+ this.vimeoId = $(media).data('vimeo-id');
311
+ }
312
+ if ($(media).data('vimeo-desc-id') !== undefined && $(media).data('vimeo-desc-id') !== "") {
313
+ this.vimeoDescId = $(media).data('vimeo-desc-id');
314
+ }
315
+
316
+ // Icon type
317
+ // By default, AblePlayer 3.0.33 and higher uses SVG icons for the player controls
318
+ // Fallback for browsers that don't support SVG is scalable icomoon fonts
319
+ // Ultimate fallback is images, if the user has a custom style sheet that overrides font-family
320
+ // Use data-icon-type to force controls to use either 'svg', 'font', or 'images'
321
+ this.iconType = 'font';
322
+ this.forceIconType = false;
323
+ if ($(media).data('icon-type') !== undefined && $(media).data('icon-type') !== "") {
324
+ var iconType = $(media).data('icon-type');
325
+ if (iconType === 'font' || iconType == 'image' || iconType == 'svg') {
326
+ this.iconType = iconType;
327
+ this.forceIconType = true;
328
+ }
329
+ }
330
+
331
+ if ($(media).data('allow-fullscreen') !== undefined && $(media).data('allow-fullscreen') === false) {
332
+ this.allowFullScreen = false;
333
+ }
334
+ else {
335
+ this.allowFullScreen = true;
336
+ }
337
+
338
+ // Seek interval
339
+ // Number of seconds to seek forward or back with Rewind & Forward buttons
340
+ // Unless specified with data-seek-interval, the default value is re-calculated in initialize.js > setSeekInterval();
341
+ // Calculation attempts to intelligently assign a reasonable interval based on media length
342
+ this.defaultSeekInterval = 10;
343
+ this.useFixedSeekInterval = false;
344
+ if ($(media).data('seek-interval') !== undefined && $(media).data('seek-interval') !== "") {
345
+ var seekInterval = $(media).data('seek-interval');
346
+ if (/^[1-9][0-9]*$/.test(seekInterval)) { // must be a whole number greater than 0
347
+ this.seekInterval = seekInterval;
348
+ this.useFixedSeekInterval = true; // do not override with calculuation
349
+ }
350
+ }
351
+
352
+ // Now Playing
353
+ // Shows "Now Playing:" plus the title of the current track above player
354
+ // Only used if there is a playlist
355
+ if ($(media).data('show-now-playing') !== undefined && $(media).data('show-now-playing') === false) {
356
+ this.showNowPlaying = false;
357
+ }
358
+ else {
359
+ this.showNowPlaying = true;
360
+ }
361
+
362
+ // TTML support (experimental); enabled for testing with data-use-ttml (Boolean)
363
+ if ($(media).data('use-ttml') !== undefined) {
364
+ this.useTtml = true;
365
+ // The following may result in a console error.
366
+ this.convert = require('xml-js');
367
+ }
368
+ else {
369
+ this.useTtml = false;
370
+ }
371
+
372
+ // Fallback
373
+ // The only supported fallback content as of version 4.0 is:
374
+ // 1. Content nested within the <audio> or <video> element.
375
+ // 2. A standard localized message (see buildplayer.js > provideFallback()
376
+ // The data-test-fallback attribute can be used to test the fallback solution in any browser
377
+ if ($(media).data('test-fallback') !== undefined && $(media).data('test-fallback') !== false) {
378
+ this.testFallback = true;
379
+ }
380
+
381
+ // Language
382
+ this.lang = 'en';
383
+ if ($(media).data('lang') !== undefined && $(media).data('lang') !== "") {
384
+ var lang = $(media).data('lang');
385
+ if (lang.length == 2) {
386
+ this.lang = lang;
387
+ }
388
+ }
389
+ // Player language is determined as follows (in translation.js > getTranslationText() ):
390
+ // 1. Lang attributes on <html> or <body>, if a matching translation file is available
391
+ // 2. The value of this.lang, if a matching translation file is available
392
+ // 3. English
393
+ // To override this formula and force #2 to take precedence over #1, set data-force-lang="true"
394
+ if ($(media).data('force-lang') !== undefined && $(media).data('force-lang') !== false) {
395
+ this.forceLang = true;
396
+ }
397
+ else {
398
+ this.forceLang = false;
399
+ }
400
+
401
+ // Metadata Tracks
402
+ if ($(media).data('meta-type') !== undefined && $(media).data('meta-type') !== "") {
403
+ this.metaType = $(media).data('meta-type');
404
+ }
405
+
406
+ if ($(media).data('meta-div') !== undefined && $(media).data('meta-div') !== "") {
407
+ this.metaDiv = $(media).data('meta-div');
408
+ }
409
+
410
+ // Search
411
+ if ($(media).data('search') !== undefined && $(media).data('search') !== "") {
412
+ // conducting a search currently requires an external div in which to write the results
413
+ if ($(media).data('search-div') !== undefined && $(media).data('search-div') !== "") {
414
+ this.searchString = $(media).data('search');
415
+ this.searchDiv = $(media).data('search-div');
416
+ }
417
+
418
+ // Search Language
419
+ if ($(media).data('search-lang') !== undefined && $(media).data('search-lang') !== "") {
420
+ this.searchLang = $(media).data('search-lang');
421
+ }
422
+ else {
423
+ this.searchLang = null; // will change to final value of this.lang in translation.js > getTranslationText()
424
+ }
425
+
426
+ // conducting a search currently requires an external div in which to write the results
427
+ if ($(media).data('search-div') !== undefined && $(media).data('search-div') !== "") {
428
+ this.searchString = $(media).data('search');
429
+ this.searchDiv = $(media).data('search-div');
430
+ }
431
+ }
432
+
433
+ // Hide controls when video starts playing
434
+ // They will reappear again when user presses a key or moves the mouse
435
+ // As of v4.0, controls are hidden automatically on playback in fullscreen mode
436
+ if ($(media).data('hide-controls') !== undefined && $(media).data('hide-controls') !== false) {
437
+ this.hideControls = true;
438
+ this.hideControlsOriginal = true; // a copy of hideControls, since the former may change if user enters full screen mode
439
+ }
440
+ else {
441
+ this.hideControls = false;
442
+ this.hideControlsOriginal = false;
443
+ }
444
+
445
+ // Define built-in variables that CANNOT be overridden with HTML attributes
446
+ this.setDefaults();
447
+
448
+ ////////////////////////////////////////
449
+ //
450
+ // End assignment of default variables
451
+ //
452
+ ////////////////////////////////////////
453
+
454
+ this.ableIndex = AblePlayer.nextIndex;
455
+ AblePlayer.nextIndex += 1;
456
+
457
+ this.title = $(media).attr('title');
458
+
459
+ // populate translation object with localized versions of all labels and prompts
460
+ // use defer method to defer additional processing until text is retrieved
461
+ this.tt = {};
462
+ var thisObj = this;
463
+ $.when(this.getTranslationText()).then(
464
+ function () {
465
+ if (thisObj.countProperties(thisObj.tt) > 50) {
466
+ // close enough to ensure that most text variables are populated
467
+ thisObj.setup();
468
+ }
469
+ else {
470
+ // can't continue loading player with no text
471
+ thisObj.provideFallback();
472
+ }
473
+ }
474
+ );
475
+ };
476
+
477
+ // Index to increment every time new player is created.
478
+ AblePlayer.nextIndex = 0;
479
+
480
+ AblePlayer.prototype.setup = function() {
481
+
482
+ var thisObj = this;
483
+ this.initializing = true; // will remain true until entire sequence of function calls is complete
484
+ this.reinitialize().then(function () {
485
+ if (!thisObj.player) {
486
+ // No player for this media, show last-line fallback.
487
+ thisObj.provideFallback();
488
+ }
489
+ else {
490
+ thisObj.setupInstance().then(function () {
491
+ thisObj.setupInstancePlaylist();
492
+ if (!thisObj.hasPlaylist) {
493
+ // for playlists, recreatePlayer() is called from within cuePlaylistItem()
494
+ thisObj.recreatePlayer();
495
+ }
496
+ thisObj.initializing = false;
497
+ thisObj.playerCreated = true; // remains true until browser is refreshed
498
+ });
499
+ }
500
+ });
501
+ };
502
+
503
+ AblePlayer.getActiveDOMElement = function () {
504
+ var activeElement = document.activeElement;
505
+
506
+ // For shadow DOMs we need to keep digging down through the DOMs
507
+ while (activeElement.shadowRoot && activeElement.shadowRoot.activeElement) {
508
+ activeElement = activeElement.shadowRoot.activeElement;
509
+ }
510
+
511
+ return activeElement;
512
+ };
513
+
514
+ AblePlayer.localGetElementById = function(element, id) {
515
+ if (element.getRootNode)
516
+ {
517
+ // Use getRootNode() and querySelector() where supported (for shadow DOM support)
518
+ return $(element.getRootNode().querySelector('#' + id));
519
+ }
520
+ else
521
+ {
522
+ // If getRootNode is not supported it should be safe to use document.getElementById (since there is no shadow DOM support)
523
+ return $(document.getElementById(id));
524
+ }
525
+ };
526
+
527
+
528
+
529
+ AblePlayer.youtubeIframeAPIReady = false;
530
+ AblePlayer.loadingYoutubeIframeAPI = false;
540
531
  })(jQuery);