wai-website-theme 0.1.0

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.
Files changed (173) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +52 -0
  4. data/_data/lang.json +730 -0
  5. data/_data/techniques.yml +180 -0
  6. data/_data/wcag.yml +125 -0
  7. data/_includes/.DS_Store +0 -0
  8. data/_includes/body-class.html +1 -0
  9. data/_includes/box.html +10 -0
  10. data/_includes/excol.html +13 -0
  11. data/_includes/footer.html +40 -0
  12. data/_includes/head.html +23 -0
  13. data/_includes/header.html +59 -0
  14. data/_includes/icon.html +6 -0
  15. data/_includes/img.html +17 -0
  16. data/_includes/multilang-list-policy-links.html +29 -0
  17. data/_includes/multilang-list.html +35 -0
  18. data/_includes/multilang-policy-title.html +5 -0
  19. data/_includes/multilang-title-full.html +1 -0
  20. data/_includes/multilang-title.html +1 -0
  21. data/_includes/navlist.html +22 -0
  22. data/_includes/notes.html +2 -0
  23. data/_includes/prevnext.html +34 -0
  24. data/_includes/resources.html +19 -0
  25. data/_includes/sidenav.html +65 -0
  26. data/_includes/sidenote.html +14 -0
  27. data/_includes/toc.html +10 -0
  28. data/_includes/video-player.html +99 -0
  29. data/_layouts/default.html +26 -0
  30. data/_layouts/home.html +14 -0
  31. data/_layouts/news.html +21 -0
  32. data/_layouts/none.html +1 -0
  33. data/_layouts/policy.html +72 -0
  34. data/_layouts/sidenav.html +27 -0
  35. data/_layouts/sidenavsidebar.html +22 -0
  36. data/assets/ableplayer/.gitattributes +14 -0
  37. data/assets/ableplayer/.gitignore +7 -0
  38. data/assets/ableplayer/Gruntfile.js +105 -0
  39. data/assets/ableplayer/LICENSE +26 -0
  40. data/assets/ableplayer/README.md +656 -0
  41. data/assets/ableplayer/build/ableplayer.dist.js +12157 -0
  42. data/assets/ableplayer/build/ableplayer.js +12157 -0
  43. data/assets/ableplayer/build/ableplayer.min.css +2 -0
  44. data/assets/ableplayer/build/ableplayer.min.js +8 -0
  45. data/assets/ableplayer/button-icons/able-icons.svg +116 -0
  46. data/assets/ableplayer/button-icons/black/captions.png +0 -0
  47. data/assets/ableplayer/button-icons/black/chapters.png +0 -0
  48. data/assets/ableplayer/button-icons/black/close.png +0 -0
  49. data/assets/ableplayer/button-icons/black/descriptions.png +0 -0
  50. data/assets/ableplayer/button-icons/black/ellipsis.png +0 -0
  51. data/assets/ableplayer/button-icons/black/faster.png +0 -0
  52. data/assets/ableplayer/button-icons/black/forward.png +0 -0
  53. data/assets/ableplayer/button-icons/black/fullscreen-collapse.png +0 -0
  54. data/assets/ableplayer/button-icons/black/fullscreen-expand.png +0 -0
  55. data/assets/ableplayer/button-icons/black/help.png +0 -0
  56. data/assets/ableplayer/button-icons/black/next.png +0 -0
  57. data/assets/ableplayer/button-icons/black/pause.png +0 -0
  58. data/assets/ableplayer/button-icons/black/pipe.png +0 -0
  59. data/assets/ableplayer/button-icons/black/play.png +0 -0
  60. data/assets/ableplayer/button-icons/black/preferences.png +0 -0
  61. data/assets/ableplayer/button-icons/black/previous.png +0 -0
  62. data/assets/ableplayer/button-icons/black/rabbit.png +0 -0
  63. data/assets/ableplayer/button-icons/black/restart.png +0 -0
  64. data/assets/ableplayer/button-icons/black/rewind.png +0 -0
  65. data/assets/ableplayer/button-icons/black/sign.png +0 -0
  66. data/assets/ableplayer/button-icons/black/slower.png +0 -0
  67. data/assets/ableplayer/button-icons/black/stop.png +0 -0
  68. data/assets/ableplayer/button-icons/black/transcript.png +0 -0
  69. data/assets/ableplayer/button-icons/black/turtle.png +0 -0
  70. data/assets/ableplayer/button-icons/black/volume-loud.png +0 -0
  71. data/assets/ableplayer/button-icons/black/volume-medium.png +0 -0
  72. data/assets/ableplayer/button-icons/black/volume-mute.png +0 -0
  73. data/assets/ableplayer/button-icons/black/volume-soft.png +0 -0
  74. data/assets/ableplayer/button-icons/fonts/able.eot +0 -0
  75. data/assets/ableplayer/button-icons/fonts/able.svg +40 -0
  76. data/assets/ableplayer/button-icons/fonts/able.ttf +0 -0
  77. data/assets/ableplayer/button-icons/fonts/able.woff +0 -0
  78. data/assets/ableplayer/button-icons/white/captions.png +0 -0
  79. data/assets/ableplayer/button-icons/white/chapters.png +0 -0
  80. data/assets/ableplayer/button-icons/white/close.png +0 -0
  81. data/assets/ableplayer/button-icons/white/descriptions.png +0 -0
  82. data/assets/ableplayer/button-icons/white/ellipsis.png +0 -0
  83. data/assets/ableplayer/button-icons/white/faster.png +0 -0
  84. data/assets/ableplayer/button-icons/white/forward.png +0 -0
  85. data/assets/ableplayer/button-icons/white/fullscreen-collapse.png +0 -0
  86. data/assets/ableplayer/button-icons/white/fullscreen-expand.png +0 -0
  87. data/assets/ableplayer/button-icons/white/help.png +0 -0
  88. data/assets/ableplayer/button-icons/white/next.png +0 -0
  89. data/assets/ableplayer/button-icons/white/pause.png +0 -0
  90. data/assets/ableplayer/button-icons/white/pipe.png +0 -0
  91. data/assets/ableplayer/button-icons/white/play.png +0 -0
  92. data/assets/ableplayer/button-icons/white/preferences.png +0 -0
  93. data/assets/ableplayer/button-icons/white/previous.png +0 -0
  94. data/assets/ableplayer/button-icons/white/rabbit.png +0 -0
  95. data/assets/ableplayer/button-icons/white/restart.png +0 -0
  96. data/assets/ableplayer/button-icons/white/rewind.png +0 -0
  97. data/assets/ableplayer/button-icons/white/sign.png +0 -0
  98. data/assets/ableplayer/button-icons/white/slower.png +0 -0
  99. data/assets/ableplayer/button-icons/white/stop.png +0 -0
  100. data/assets/ableplayer/button-icons/white/transcript.png +0 -0
  101. data/assets/ableplayer/button-icons/white/turtle.png +0 -0
  102. data/assets/ableplayer/button-icons/white/volume-loud.png +0 -0
  103. data/assets/ableplayer/button-icons/white/volume-medium.png +0 -0
  104. data/assets/ableplayer/button-icons/white/volume-mute.png +0 -0
  105. data/assets/ableplayer/button-icons/white/volume-soft.png +0 -0
  106. data/assets/ableplayer/images/wingrip.png +0 -0
  107. data/assets/ableplayer/package.json +22 -0
  108. data/assets/ableplayer/scripts/JQuery.doWhen.js +113 -0
  109. data/assets/ableplayer/scripts/ableplayer-base.js +440 -0
  110. data/assets/ableplayer/scripts/browser.js +162 -0
  111. data/assets/ableplayer/scripts/buildplayer.js +1609 -0
  112. data/assets/ableplayer/scripts/caption.js +385 -0
  113. data/assets/ableplayer/scripts/chapters.js +242 -0
  114. data/assets/ableplayer/scripts/control.js +1514 -0
  115. data/assets/ableplayer/scripts/description.js +283 -0
  116. data/assets/ableplayer/scripts/dialog.js +147 -0
  117. data/assets/ableplayer/scripts/dragdrop.js +766 -0
  118. data/assets/ableplayer/scripts/event.js +595 -0
  119. data/assets/ableplayer/scripts/initialize.js +725 -0
  120. data/assets/ableplayer/scripts/langs.js +750 -0
  121. data/assets/ableplayer/scripts/metadata.js +134 -0
  122. data/assets/ableplayer/scripts/misc.js +72 -0
  123. data/assets/ableplayer/scripts/preference.js +909 -0
  124. data/assets/ableplayer/scripts/search.js +171 -0
  125. data/assets/ableplayer/scripts/sign.js +92 -0
  126. data/assets/ableplayer/scripts/slider.js +454 -0
  127. data/assets/ableplayer/scripts/track.js +296 -0
  128. data/assets/ableplayer/scripts/transcript.js +590 -0
  129. data/assets/ableplayer/scripts/translation.js +66 -0
  130. data/assets/ableplayer/scripts/volume.js +383 -0
  131. data/assets/ableplayer/scripts/webvtt.js +765 -0
  132. data/assets/ableplayer/scripts/youtube.js +471 -0
  133. data/assets/ableplayer/styles/ableplayer.css +1241 -0
  134. data/assets/ableplayer/thirdparty/js.cookie.js +145 -0
  135. data/assets/ableplayer/thirdparty/modernizr.custom.js +4 -0
  136. data/assets/ableplayer/translations/ca.js +1 -0
  137. data/assets/ableplayer/translations/de.js +1 -0
  138. data/assets/ableplayer/translations/en.js +305 -0
  139. data/assets/ableplayer/translations/es.js +305 -0
  140. data/assets/ableplayer/translations/fr.js +305 -0
  141. data/assets/ableplayer/translations/it.js +303 -0
  142. data/assets/ableplayer/translations/ja.js +305 -0
  143. data/assets/ableplayer/translations/nl.js +305 -0
  144. data/assets/css/style.css +4360 -0
  145. data/assets/css/style.css.map +1 -0
  146. data/assets/fonts/anonymouspro-bold.woff +0 -0
  147. data/assets/fonts/anonymouspro-bold.woff2 +0 -0
  148. data/assets/fonts/anonymouspro-bolditalic.woff +0 -0
  149. data/assets/fonts/anonymouspro-bolditalic.woff2 +0 -0
  150. data/assets/fonts/anonymouspro-italic.woff +0 -0
  151. data/assets/fonts/anonymouspro-italic.woff2 +0 -0
  152. data/assets/fonts/anonymouspro-regular.woff +0 -0
  153. data/assets/fonts/anonymouspro-regular.woff2 +0 -0
  154. data/assets/fonts/notosans-bold.woff +0 -0
  155. data/assets/fonts/notosans-bold.woff2 +0 -0
  156. data/assets/fonts/notosans-bolditalic.woff +0 -0
  157. data/assets/fonts/notosans-bolditalic.woff2 +0 -0
  158. data/assets/fonts/notosans-italic.woff +0 -0
  159. data/assets/fonts/notosans-italic.woff2 +0 -0
  160. data/assets/fonts/notosans-regular.woff +0 -0
  161. data/assets/fonts/notosans-regular.woff2 +0 -0
  162. data/assets/images/.DS_Store +0 -0
  163. data/assets/images/Shape.svg +10 -0
  164. data/assets/images/icon-related-content.svg +14 -0
  165. data/assets/images/icons.svg +126 -0
  166. data/assets/images/teaser-image@1x.jpg +0 -0
  167. data/assets/images/teaser-image@2x.jpg +0 -0
  168. data/assets/images/w3c.sketch +0 -0
  169. data/assets/images/w3c.svg +10 -0
  170. data/assets/scripts/jquery.min.js +4 -0
  171. data/assets/scripts/main.js +208 -0
  172. data/assets/scripts/svg4everybody.js +1 -0
  173. metadata +257 -0
@@ -0,0 +1,385 @@
1
+ (function ($) {
2
+ AblePlayer.prototype.updateCaption = function (time) {
3
+ if (!this.usingYouTubeCaptions && (typeof this.$captionsWrapper !== 'undefined')) {
4
+ if (this.captionsOn) {
5
+ this.$captionsWrapper.show();
6
+ this.showCaptions(time || this.getElapsed());
7
+ }
8
+ else if (this.$captionsWrapper) {
9
+ this.$captionsWrapper.hide();
10
+ this.prefCaptions = 0;
11
+ }
12
+ }
13
+ };
14
+
15
+ // Returns the function used when a caption is clicked in the captions menu.
16
+ // Not called if user clicks "Captions off". Instead, that triggers getCaptionOffFunction()
17
+ AblePlayer.prototype.getCaptionClickFunction = function (track) {
18
+ var thisObj = this;
19
+ return function () {
20
+ thisObj.selectedCaptions = track;
21
+ thisObj.captionLang = track.language;
22
+ thisObj.currentCaption = -1;
23
+
24
+ if (thisObj.usingYouTubeCaptions) {
25
+ if (thisObj.captionsOn) {
26
+ if (typeof thisObj.ytCaptionModule !== 'undefined') {
27
+ // captions are already on. Just need to change the language
28
+ thisObj.youTubePlayer.setOption(thisObj.ytCaptionModule, 'track', {'languageCode': thisObj.captionLang});
29
+ }
30
+ else {
31
+ // need to wait for caption module to be loaded to change the language
32
+ // caption module will be loaded after video starts playing, triggered by onApiChange event
33
+ // at that point, thosObj.captionLang will be passed to the module as the default language
34
+ }
35
+ }
36
+ else {
37
+ // captions are off (i.e., captions module has been unloaded; need to reload it)
38
+ // user's selected language will be reset after module has successfully loaded
39
+ // (the onApiChange event will be fired -- see initialize.js > initYouTubePlayer())
40
+ thisObj.resettingYouTubeCaptions = true;
41
+ thisObj.youTubePlayer.loadModule(thisObj.ytCaptionModule);
42
+ }
43
+ }
44
+ else {
45
+ thisObj.syncTrackLanguages('captions',thisObj.captionLang);
46
+ if (!this.swappingSrc) {
47
+ thisObj.updateCaption();
48
+ thisObj.showDescription(thisObj.getElapsed());
49
+ }
50
+ }
51
+ thisObj.captionsOn = true;
52
+ // stopgap to prevent spacebar in Firefox from reopening popup
53
+ // immediately after closing it (used in handleCaptionToggle())
54
+ thisObj.hidingPopup = true;
55
+ thisObj.captionsPopup.hide();
56
+ // Ensure stopgap gets cancelled if handleCaptionToggle() isn't called
57
+ // e.g., if user triggered button with Enter or mouse click, not spacebar
58
+ setTimeout(function() {
59
+ thisObj.hidingPopup = false;
60
+ }, 100);
61
+ thisObj.$ccButton.focus();
62
+
63
+ // save preference to cookie
64
+ thisObj.prefCaptions = 1;
65
+ thisObj.updateCookie('prefCaptions');
66
+
67
+ thisObj.refreshControls();
68
+ }
69
+ };
70
+
71
+ // Returns the function used when the "Captions Off" button is clicked in the captions tooltip.
72
+ AblePlayer.prototype.getCaptionOffFunction = function () {
73
+ var thisObj = this;
74
+ return function () {
75
+ if (thisObj.player == 'youtube') {
76
+ thisObj.youTubePlayer.unloadModule(thisObj.ytCaptionModule);
77
+ }
78
+ thisObj.captionsOn = false;
79
+ thisObj.currentCaption = -1;
80
+ // stopgap to prevent spacebar in Firefox from reopening popup
81
+ // immediately after closing it (used in handleCaptionToggle())
82
+ thisObj.hidingPopup = true;
83
+ thisObj.captionsPopup.hide();
84
+ // Ensure stopgap gets cancelled if handleCaptionToggle() isn't called
85
+ // e.g., if user triggered button with Enter or mouse click, not spacebar
86
+ setTimeout(function() {
87
+ thisObj.hidingPopup = false;
88
+ }, 100);
89
+ thisObj.$ccButton.focus();
90
+
91
+ // save preference to cookie
92
+ thisObj.prefCaptions = 0;
93
+ thisObj.updateCookie('prefCaptions');
94
+ if (!this.swappingSrc) {
95
+ thisObj.refreshControls();
96
+ thisObj.updateCaption();
97
+ }
98
+ }
99
+ };
100
+
101
+ AblePlayer.prototype.showCaptions = function(now) {
102
+ var c, thisCaption, captionText;
103
+ var cues;
104
+ if (this.selectedCaptions) {
105
+ cues = this.selectedCaptions.cues;
106
+ }
107
+ else if (this.captions.length >= 1) {
108
+ cues = this.captions[0].cues;
109
+ }
110
+ else {
111
+ cues = [];
112
+ }
113
+ for (c = 0; c < cues.length; c++) {
114
+ if ((cues[c].start <= now) && (cues[c].end > now)) {
115
+ thisCaption = c;
116
+ break;
117
+ }
118
+ }
119
+ if (typeof thisCaption !== 'undefined') {
120
+ if (this.currentCaption !== thisCaption) {
121
+ // it's time to load the new caption into the container div
122
+ captionText = this.flattenCueForCaption(cues[thisCaption]).replace('\n', '<br>');
123
+ this.$captionsDiv.html(captionText);
124
+ this.currentCaption = thisCaption;
125
+ if (captionText.length === 0) {
126
+ // hide captionsDiv; otherwise background-color is visible due to padding
127
+ this.$captionsDiv.css('display','none');
128
+ }
129
+ else {
130
+ this.$captionsDiv.css('display','inline-block');
131
+ }
132
+ }
133
+ }
134
+ else {
135
+ this.$captionsDiv.html('');
136
+ this.currentCaption = -1;
137
+ }
138
+ };
139
+
140
+ AblePlayer.prototype.flattenCueForCaption = function (cue) {
141
+
142
+ // Takes a cue and returns the caption text to display
143
+ // Also used for chapters
144
+
145
+ // Support for 'i' and 'b' tags added in 2.3.66
146
+ // TODO: Add support for 'c' (class) and 'ruby'
147
+
148
+ // c (class): <c.myClass1.myClass2>Some text</c>
149
+ // Classes can be used to modify other tags too (e.g., <v.loud>)
150
+ // If <c> tag, should be rendered as a <span>
151
+
152
+ // ruby: http://www.w3schools.com/tags/tag_ruby.asp
153
+
154
+ // WebVTT also supports 'u' (underline)
155
+ // I see no reason to support that in Able Player.
156
+ // If it's available authors are likely to use it incorrectly
157
+ // where <i> or <b> should be used instead
158
+ // Here are the rare use cases where an underline is appropriate on the web:
159
+ // http://html5doctor.com/u-element/
160
+
161
+ var result = [];
162
+
163
+ var flattenComponent = function (component) {
164
+ var result = [], ii;
165
+ if (component.type === 'string') {
166
+ result.push(component.value);
167
+ }
168
+ else if (component.type === 'v') {
169
+ result.push('(' + component.value + ')');
170
+ for (ii = 0; ii < component.children.length; ii++) {
171
+ result.push(flattenComponent(component.children[ii]));
172
+ }
173
+ }
174
+ else if (component.type === 'i') {
175
+ result.push('<em>');
176
+ for (ii = 0; ii < component.children.length; ii++) {
177
+ result.push(flattenComponent(component.children[ii]));
178
+ }
179
+ result.push('</em>');
180
+ }
181
+ else if (component.type === 'b') {
182
+ result.push('<strong>');
183
+ for (ii = 0; ii < component.children.length; ii++) {
184
+ result.push(flattenComponent(component.children[ii]));
185
+ }
186
+ result.push('</strong>');
187
+ }
188
+ else {
189
+ for (ii = 0; ii < component.children.length; ii++) {
190
+ result.push(flattenComponent(component.children[ii]));
191
+ }
192
+ }
193
+ return result.join('');
194
+ };
195
+
196
+ if (typeof cue.components !== 'undefined') {
197
+ for (var ii = 0; ii < cue.components.children.length; ii++) {
198
+ result.push(flattenComponent(cue.components.children[ii]));
199
+ }
200
+ }
201
+ return result.join('');
202
+ };
203
+
204
+ AblePlayer.prototype.getCaptionsOptions = function(pref) {
205
+
206
+ var options = [];
207
+
208
+ switch (pref) {
209
+
210
+ case 'prefCaptionsFont':
211
+ options[0] = this.tt.serif;
212
+ options[1] = this.tt.sans;
213
+ options[3] = this.tt.cursive;
214
+ options[4] = this.tt.fantasy;
215
+ options[2] = this.tt.monospace;
216
+ break;
217
+
218
+ case 'prefCaptionsColor':
219
+ case 'prefCaptionsBGColor':
220
+ // HTML color values must be in English
221
+ options[0] = ['white',this.tt.white];
222
+ options[1] = ['yellow',this.tt.yellow];
223
+ options[2] = ['green',this.tt.green];
224
+ options[3] = ['cyan',this.tt.cyan];
225
+ options[4] = ['blue',this.tt.blue];
226
+ options[5] = ['magenta',this.tt.magenta];
227
+ options[6] = ['red',this.tt.red];
228
+ options[7] = ['black',this.tt.black];
229
+ break;
230
+
231
+ case 'prefCaptionsSize':
232
+ options[0] = '75%';
233
+ options[1] = '100%';
234
+ options[2] = '125%';
235
+ options[3] = '150%';
236
+ options[4] = '200%';
237
+ break;
238
+
239
+ case 'prefCaptionsOpacity':
240
+ options[0] = '0%';
241
+ options[1] = '25%';
242
+ options[2] = '50%';
243
+ options[3] = '75%';
244
+ options[4] = '100%';
245
+ break;
246
+
247
+ case 'prefCaptionsStyle':
248
+ options[0] = this.tt.captionsStylePopOn;
249
+ options[1] = this.tt.captionsStyleRollUp;
250
+ break;
251
+
252
+ case 'prefCaptionsPosition':
253
+ options[0] = 'overlay';
254
+ options[1] = 'below';
255
+ break;
256
+
257
+ }
258
+ return options;
259
+ };
260
+
261
+ AblePlayer.prototype.translatePrefs = function(pref, value, outputFormat) {
262
+
263
+ // translate current value of pref to a value supported by outputformat
264
+ if (outputFormat == 'youtube') {
265
+ if (pref === 'size') {
266
+ // YouTube font sizes are a range from -1 to 3 (0 = default)
267
+ switch (value) {
268
+ case '75%':
269
+ return -1;
270
+ case '100%':
271
+ return 0;
272
+ case '125%':
273
+ return 1;
274
+ case '150%':
275
+ return 2;
276
+ case '200%':
277
+ return 3;
278
+ }
279
+ }
280
+ }
281
+ return false;
282
+ }
283
+
284
+ AblePlayer.prototype.stylizeCaptions = function($element, pref) {
285
+ // $element is the jQuery element containing the captions
286
+ // this function handles stylizing of the sample caption text in the Prefs dialog
287
+ // plus the actual production captions
288
+ // TODO: consider applying the same user prefs to visible text-based description
289
+ var property, newValue, opacity, lineHeight;
290
+
291
+ if (typeof $element !== 'undefined') {
292
+ if (pref == 'prefCaptionsPosition') {
293
+ this.positionCaptions();
294
+ }
295
+ else if (typeof pref !== 'undefined') {
296
+ // just change the one property that user just changed
297
+ if (pref === 'prefCaptionsFont') {
298
+ property = 'font-family';
299
+ }
300
+ else if (pref === 'prefCaptionsSize') {
301
+ property = 'font-size';
302
+ }
303
+ else if (pref === 'prefCaptionsColor') {
304
+ property = 'color';
305
+ }
306
+ else if (pref === 'prefCaptionsBGColor') {
307
+ property = 'background-color';
308
+ }
309
+ else if (pref === 'prefCaptionsOpacity') {
310
+ property = 'opacity';
311
+ }
312
+ if (pref === 'prefCaptionsOpacity') {
313
+ newValue = parseFloat($('#' + this.mediaId + '_' + pref).val()) / 100.0;
314
+ }
315
+ else {
316
+ newValue = $('#' + this.mediaId + '_' + pref).val();
317
+ }
318
+ $element.css(property, newValue);
319
+ }
320
+ else { // no property was specified, update all styles with current saved prefs
321
+ opacity = parseFloat(this.prefCaptionsOpacity) / 100.0;
322
+ $element.css({
323
+ 'font-family': this.prefCaptionsFont,
324
+ 'font-size': this.prefCaptionsSize,
325
+ 'color': this.prefCaptionsColor,
326
+ 'background-color': this.prefCaptionsBGColor,
327
+ 'opacity': opacity
328
+ });
329
+ if ($element === this.$captionsDiv) {
330
+ if (typeof this.$captionsWrapper !== 'undefined') {
331
+ lineHeight = parseInt(this.prefCaptionsSize,10) + 25;
332
+ this.$captionsWrapper.css('line-height',lineHeight + '%');
333
+ }
334
+ }
335
+ if (this.prefCaptionsPosition === 'below') {
336
+ // also need to add the background color to the wrapper div
337
+ if (typeof this.$captionsWrapper !== 'undefined') {
338
+ this.$captionsWrapper.css({
339
+ 'background-color': this.prefCaptionsBGColor,
340
+ 'opacity': '1'
341
+ });
342
+ }
343
+ }
344
+ else if (this.prefCaptionsPosition === 'overlay') {
345
+ // no background color for overlay wrapper, captions are displayed in-line
346
+ if (typeof this.$captionsWrapper !== 'undefined') {
347
+ this.$captionsWrapper.css({
348
+ 'background-color': 'transparent',
349
+ 'opacity': ''
350
+ });
351
+ }
352
+ }
353
+ this.positionCaptions();
354
+ }
355
+ }
356
+ };
357
+ AblePlayer.prototype.positionCaptions = function(position) {
358
+
359
+ // set caption position to either 'overlay' or 'below'
360
+ // if position parameter was passed to this function, use that
361
+ // otherwise use user preference
362
+ if (typeof position === 'undefined') {
363
+ position = this.prefCaptionsPosition;
364
+ }
365
+ if (typeof this.$captionsWrapper !== 'undefined') {
366
+
367
+ if (position == 'below') {
368
+ this.$captionsWrapper.removeClass('able-captions-overlay').addClass('able-captions-below');
369
+ // also need to update in-line styles
370
+ this.$captionsWrapper.css({
371
+ 'background-color': this.prefCaptionsBGColor,
372
+ 'opacity': '1'
373
+ });
374
+ }
375
+ else {
376
+ this.$captionsWrapper.removeClass('able-captions-below').addClass('able-captions-overlay');
377
+ this.$captionsWrapper.css({
378
+ 'background-color': 'transparent',
379
+ 'opacity': ''
380
+ });
381
+ }
382
+ }
383
+ };
384
+
385
+ })(jQuery);
@@ -0,0 +1,242 @@
1
+ (function ($) {
2
+
3
+ AblePlayer.prototype.populateChaptersDiv = function() {
4
+
5
+ var headingLevel, headingType, headingId, $chaptersHeading,
6
+ $chaptersList;
7
+
8
+ if ($('#' + this.chaptersDivLocation)) {
9
+ this.$chaptersDiv = $('#' + this.chaptersDivLocation);
10
+ this.$chaptersDiv.addClass('able-chapters-div');
11
+
12
+ // add optional header
13
+ if (this.chaptersTitle) {
14
+ headingLevel = this.getNextHeadingLevel(this.$chaptersDiv);
15
+ headingType = 'h' + headingLevel.toString();
16
+ headingId = this.mediaId + '-chapters-heading';
17
+ $chaptersHeading = $('<' + headingType + '>', {
18
+ 'class': 'able-chapters-heading',
19
+ 'id': headingId
20
+ }).text(this.chaptersTitle);
21
+ this.$chaptersDiv.append($chaptersHeading);
22
+ }
23
+
24
+ this.$chaptersNav = $('<nav>');
25
+ if (this.chaptersTitle) {
26
+ this.$chaptersNav.attr('aria-labelledby',headingId);
27
+ }
28
+ else {
29
+ this.$chaptersNav.attr('aria-label',this.tt.chapters);
30
+ }
31
+ this.$chaptersDiv.append(this.$chaptersNav);
32
+
33
+ // populate this.$chaptersNav with a list of chapters
34
+ this.updateChaptersList();
35
+ }
36
+ };
37
+
38
+ AblePlayer.prototype.updateChaptersList = function() {
39
+
40
+ var thisObj, cues, $chaptersList, c, thisChapter,
41
+ $chapterItem, $chapterButton, buttonId, hasDefault,
42
+ getClickFunction, $clickedItem, $chaptersList, thisChapterIndex;
43
+
44
+ thisObj = this;
45
+
46
+ if (!this.$chaptersNav) {
47
+ return false;
48
+ }
49
+
50
+ if (typeof this.useChapterTimes === 'undefined') {
51
+ if (this.seekbarScope === 'chapter' && this.selectedChapters.cues.length) {
52
+ this.useChapterTimes = true;
53
+ }
54
+ else {
55
+ this.useChapterTimes = false;
56
+ }
57
+ }
58
+
59
+ if (this.useChapterTimes) {
60
+ cues = this.selectedChapters.cues;
61
+ }
62
+ else if (this.chapters.length >= 1) {
63
+ cues = this.chapters[0].cues;
64
+ }
65
+ else {
66
+ cues = [];
67
+ }
68
+ if (cues.length > 0) {
69
+ $chaptersList = $('<ul>');
70
+ for (c = 0; c < cues.length; c++) {
71
+ thisChapter = c;
72
+ $chapterItem = $('<li></li>');
73
+ $chapterButton = $('<button>',{
74
+ 'type': 'button',
75
+ 'val': thisChapter
76
+ }).text(this.flattenCueForCaption(cues[thisChapter]));
77
+
78
+ // add event listeners
79
+ getClickFunction = function (time) {
80
+ return function () {
81
+ $clickedItem = $(this).closest('li');
82
+ $chaptersList = $(this).closest('ul').find('li');
83
+ thisChapterIndex = $chaptersList.index($clickedItem);
84
+ $chaptersList.removeClass('able-current-chapter').attr('aria-selected','');
85
+ $clickedItem.addClass('able-current-chapter').attr('aria-selected','true');
86
+ // Need to updateChapter before seeking to it
87
+ // Otherwise seekBar is redrawn with wrong chapterDuration and/or chapterTime
88
+ thisObj.updateChapter(time);
89
+ thisObj.seekTo(time);
90
+ }
91
+ };
92
+ $chapterButton.on('click',getClickFunction(cues[thisChapter].start)); // works with Enter too
93
+ $chapterButton.on('focus',function() {
94
+ $(this).closest('ul').find('li').removeClass('able-focus');
95
+ $(this).closest('li').addClass('able-focus');
96
+ });
97
+ $chapterItem.on('hover',function() {
98
+ $(this).closest('ul').find('li').removeClass('able-focus');
99
+ $(this).addClass('able-focus');
100
+ });
101
+ $chapterItem.on('mouseleave',function() {
102
+ $(this).removeClass('able-focus');
103
+ });
104
+ $chapterButton.on('blur',function() {
105
+ $(this).closest('li').removeClass('able-focus');
106
+ });
107
+
108
+ // put it all together
109
+ $chapterItem.append($chapterButton);
110
+ $chaptersList.append($chapterItem);
111
+ if (this.defaultChapter === cues[thisChapter].id) {
112
+ $chapterButton.attr('aria-selected','true').parent('li').addClass('able-current-chapter');
113
+ this.currentChapter = cues[thisChapter];
114
+ hasDefault = true;
115
+ }
116
+ }
117
+ if (!hasDefault) {
118
+ // select the first chapter
119
+ this.currentChapter = cues[0];
120
+ $chaptersList.find('button').first().attr('aria-selected','true')
121
+ .parent('li').addClass('able-current-chapter');
122
+ }
123
+ this.$chaptersNav.html($chaptersList);
124
+ }
125
+ return false;
126
+ };
127
+
128
+ AblePlayer.prototype.seekToChapter = function(chapterId) {
129
+
130
+ // step through chapters looking for matching ID
131
+ var i=0;
132
+ while (i < this.selectedChapters.cues.length) {
133
+ if (this.selectedChapters.cues[i].id == chapterId) {
134
+ // found the target chapter! Seek to it
135
+ this.seekTo(this.selectedChapters.cues[i].start);
136
+ this.updateChapter(this.selectedChapters.cues[i].start);
137
+ break;
138
+ }
139
+ i++;
140
+ }
141
+ };
142
+
143
+ AblePlayer.prototype.updateChapter = function (now) {
144
+
145
+ // as time-synced chapters change during playback, track changes in current chapter
146
+ if (typeof this.selectedChapters === 'undefined') {
147
+ return;
148
+ }
149
+
150
+ var chapters, i, thisChapterIndex, chapterLabel;
151
+
152
+ chapters = this.selectedChapters.cues;
153
+ for (i = 0; i < chapters.length; i++) {
154
+ if ((chapters[i].start <= now) && (chapters[i].end > now)) {
155
+ thisChapterIndex = i;
156
+ break;
157
+ }
158
+ }
159
+ if (typeof thisChapterIndex !== 'undefined') {
160
+ if (this.currentChapter !== chapters[thisChapterIndex]) {
161
+ // this is a new chapter
162
+ this.currentChapter = chapters[thisChapterIndex];
163
+ if (this.useChapterTimes) {
164
+ this.chapterDuration = this.getChapterDuration();
165
+ this.seekIntervalCalculated = false; // will be recalculated in setSeekInterval()
166
+ }
167
+ if (typeof this.$chaptersDiv !== 'undefined') {
168
+ // chapters are listed in an external container
169
+ this.$chaptersDiv.find('ul').find('li').removeClass('able-current-chapter').attr('aria-selected','');
170
+ this.$chaptersDiv.find('ul').find('li').eq(thisChapterIndex)
171
+ .addClass('able-current-chapter').attr('aria-selected','true');
172
+ }
173
+ }
174
+ }
175
+ };
176
+
177
+ AblePlayer.prototype.getChapterDuration = function () {
178
+
179
+ // called if this.seekbarScope === 'chapter'
180
+ // get duration of the current chapter
181
+
182
+ var videoDuration, lastChapterIndex, chapterEnd;
183
+
184
+ if (typeof this.currentChapter === 'undefined') {
185
+ return 0;
186
+ }
187
+ videoDuration = this.getDuration();
188
+ lastChapterIndex = this.selectedChapters.cues.length-1;
189
+
190
+ if (this.selectedChapters.cues[lastChapterIndex] == this.currentChapter) {
191
+ // this is the last chapter
192
+ if (this.currentChapter.end !== videoDuration) {
193
+ // chapter ends before or after video ends, adjust chapter end to match video end
194
+ chapterEnd = videoDuration;
195
+ this.currentChapter.end = videoDuration;
196
+ }
197
+ else {
198
+ chapterEnd = this.currentChapter.end;
199
+ }
200
+ }
201
+ else { // this is not the last chapter
202
+ chapterEnd = this.currentChapter.end;
203
+ }
204
+ return chapterEnd - this.currentChapter.start;
205
+ };
206
+
207
+ AblePlayer.prototype.getChapterElapsed = function () {
208
+
209
+ // called if this.seekbarScope === 'chapter'
210
+ // get current elapsed time, relative to the current chapter duration
211
+ if (typeof this.currentChapter === 'undefined') {
212
+ return 0;
213
+ }
214
+ var videoDuration = this.getDuration();
215
+ var videoElapsed = this.getElapsed();
216
+ if (videoElapsed > this.currentChapter.start) {
217
+ return videoElapsed - this.currentChapter.start;
218
+ }
219
+ else {
220
+ return 0;
221
+ }
222
+ };
223
+
224
+ AblePlayer.prototype.convertChapterTimeToVideoTime = function (chapterTime) {
225
+
226
+ // chapterTime is the time within the current chapter
227
+ // return the same time, relative to the entire video
228
+ if (typeof this.currentChapter !== 'undefined') {
229
+ var newTime = this.currentChapter.start + chapterTime;
230
+ if (newTime > this.currentChapter.end) {
231
+ return this.currentChapter.end;
232
+ }
233
+ else {
234
+ return newTime;
235
+ }
236
+ }
237
+ else {
238
+ return chapterTime;
239
+ }
240
+ };
241
+
242
+ })(jQuery);