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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +52 -0
- data/_data/lang.json +730 -0
- data/_data/techniques.yml +180 -0
- data/_data/wcag.yml +125 -0
- data/_includes/.DS_Store +0 -0
- data/_includes/body-class.html +1 -0
- data/_includes/box.html +10 -0
- data/_includes/excol.html +13 -0
- data/_includes/footer.html +40 -0
- data/_includes/head.html +23 -0
- data/_includes/header.html +59 -0
- data/_includes/icon.html +6 -0
- data/_includes/img.html +17 -0
- data/_includes/multilang-list-policy-links.html +29 -0
- data/_includes/multilang-list.html +35 -0
- data/_includes/multilang-policy-title.html +5 -0
- data/_includes/multilang-title-full.html +1 -0
- data/_includes/multilang-title.html +1 -0
- data/_includes/navlist.html +22 -0
- data/_includes/notes.html +2 -0
- data/_includes/prevnext.html +34 -0
- data/_includes/resources.html +19 -0
- data/_includes/sidenav.html +65 -0
- data/_includes/sidenote.html +14 -0
- data/_includes/toc.html +10 -0
- data/_includes/video-player.html +99 -0
- data/_layouts/default.html +26 -0
- data/_layouts/home.html +14 -0
- data/_layouts/news.html +21 -0
- data/_layouts/none.html +1 -0
- data/_layouts/policy.html +72 -0
- data/_layouts/sidenav.html +27 -0
- data/_layouts/sidenavsidebar.html +22 -0
- data/assets/ableplayer/.gitattributes +14 -0
- data/assets/ableplayer/.gitignore +7 -0
- data/assets/ableplayer/Gruntfile.js +105 -0
- data/assets/ableplayer/LICENSE +26 -0
- data/assets/ableplayer/README.md +656 -0
- data/assets/ableplayer/build/ableplayer.dist.js +12157 -0
- data/assets/ableplayer/build/ableplayer.js +12157 -0
- data/assets/ableplayer/build/ableplayer.min.css +2 -0
- data/assets/ableplayer/build/ableplayer.min.js +8 -0
- data/assets/ableplayer/button-icons/able-icons.svg +116 -0
- data/assets/ableplayer/button-icons/black/captions.png +0 -0
- data/assets/ableplayer/button-icons/black/chapters.png +0 -0
- data/assets/ableplayer/button-icons/black/close.png +0 -0
- data/assets/ableplayer/button-icons/black/descriptions.png +0 -0
- data/assets/ableplayer/button-icons/black/ellipsis.png +0 -0
- data/assets/ableplayer/button-icons/black/faster.png +0 -0
- data/assets/ableplayer/button-icons/black/forward.png +0 -0
- data/assets/ableplayer/button-icons/black/fullscreen-collapse.png +0 -0
- data/assets/ableplayer/button-icons/black/fullscreen-expand.png +0 -0
- data/assets/ableplayer/button-icons/black/help.png +0 -0
- data/assets/ableplayer/button-icons/black/next.png +0 -0
- data/assets/ableplayer/button-icons/black/pause.png +0 -0
- data/assets/ableplayer/button-icons/black/pipe.png +0 -0
- data/assets/ableplayer/button-icons/black/play.png +0 -0
- data/assets/ableplayer/button-icons/black/preferences.png +0 -0
- data/assets/ableplayer/button-icons/black/previous.png +0 -0
- data/assets/ableplayer/button-icons/black/rabbit.png +0 -0
- data/assets/ableplayer/button-icons/black/restart.png +0 -0
- data/assets/ableplayer/button-icons/black/rewind.png +0 -0
- data/assets/ableplayer/button-icons/black/sign.png +0 -0
- data/assets/ableplayer/button-icons/black/slower.png +0 -0
- data/assets/ableplayer/button-icons/black/stop.png +0 -0
- data/assets/ableplayer/button-icons/black/transcript.png +0 -0
- data/assets/ableplayer/button-icons/black/turtle.png +0 -0
- data/assets/ableplayer/button-icons/black/volume-loud.png +0 -0
- data/assets/ableplayer/button-icons/black/volume-medium.png +0 -0
- data/assets/ableplayer/button-icons/black/volume-mute.png +0 -0
- data/assets/ableplayer/button-icons/black/volume-soft.png +0 -0
- data/assets/ableplayer/button-icons/fonts/able.eot +0 -0
- data/assets/ableplayer/button-icons/fonts/able.svg +40 -0
- data/assets/ableplayer/button-icons/fonts/able.ttf +0 -0
- data/assets/ableplayer/button-icons/fonts/able.woff +0 -0
- data/assets/ableplayer/button-icons/white/captions.png +0 -0
- data/assets/ableplayer/button-icons/white/chapters.png +0 -0
- data/assets/ableplayer/button-icons/white/close.png +0 -0
- data/assets/ableplayer/button-icons/white/descriptions.png +0 -0
- data/assets/ableplayer/button-icons/white/ellipsis.png +0 -0
- data/assets/ableplayer/button-icons/white/faster.png +0 -0
- data/assets/ableplayer/button-icons/white/forward.png +0 -0
- data/assets/ableplayer/button-icons/white/fullscreen-collapse.png +0 -0
- data/assets/ableplayer/button-icons/white/fullscreen-expand.png +0 -0
- data/assets/ableplayer/button-icons/white/help.png +0 -0
- data/assets/ableplayer/button-icons/white/next.png +0 -0
- data/assets/ableplayer/button-icons/white/pause.png +0 -0
- data/assets/ableplayer/button-icons/white/pipe.png +0 -0
- data/assets/ableplayer/button-icons/white/play.png +0 -0
- data/assets/ableplayer/button-icons/white/preferences.png +0 -0
- data/assets/ableplayer/button-icons/white/previous.png +0 -0
- data/assets/ableplayer/button-icons/white/rabbit.png +0 -0
- data/assets/ableplayer/button-icons/white/restart.png +0 -0
- data/assets/ableplayer/button-icons/white/rewind.png +0 -0
- data/assets/ableplayer/button-icons/white/sign.png +0 -0
- data/assets/ableplayer/button-icons/white/slower.png +0 -0
- data/assets/ableplayer/button-icons/white/stop.png +0 -0
- data/assets/ableplayer/button-icons/white/transcript.png +0 -0
- data/assets/ableplayer/button-icons/white/turtle.png +0 -0
- data/assets/ableplayer/button-icons/white/volume-loud.png +0 -0
- data/assets/ableplayer/button-icons/white/volume-medium.png +0 -0
- data/assets/ableplayer/button-icons/white/volume-mute.png +0 -0
- data/assets/ableplayer/button-icons/white/volume-soft.png +0 -0
- data/assets/ableplayer/images/wingrip.png +0 -0
- data/assets/ableplayer/package.json +22 -0
- data/assets/ableplayer/scripts/JQuery.doWhen.js +113 -0
- data/assets/ableplayer/scripts/ableplayer-base.js +440 -0
- data/assets/ableplayer/scripts/browser.js +162 -0
- data/assets/ableplayer/scripts/buildplayer.js +1609 -0
- data/assets/ableplayer/scripts/caption.js +385 -0
- data/assets/ableplayer/scripts/chapters.js +242 -0
- data/assets/ableplayer/scripts/control.js +1514 -0
- data/assets/ableplayer/scripts/description.js +283 -0
- data/assets/ableplayer/scripts/dialog.js +147 -0
- data/assets/ableplayer/scripts/dragdrop.js +766 -0
- data/assets/ableplayer/scripts/event.js +595 -0
- data/assets/ableplayer/scripts/initialize.js +725 -0
- data/assets/ableplayer/scripts/langs.js +750 -0
- data/assets/ableplayer/scripts/metadata.js +134 -0
- data/assets/ableplayer/scripts/misc.js +72 -0
- data/assets/ableplayer/scripts/preference.js +909 -0
- data/assets/ableplayer/scripts/search.js +171 -0
- data/assets/ableplayer/scripts/sign.js +92 -0
- data/assets/ableplayer/scripts/slider.js +454 -0
- data/assets/ableplayer/scripts/track.js +296 -0
- data/assets/ableplayer/scripts/transcript.js +590 -0
- data/assets/ableplayer/scripts/translation.js +66 -0
- data/assets/ableplayer/scripts/volume.js +383 -0
- data/assets/ableplayer/scripts/webvtt.js +765 -0
- data/assets/ableplayer/scripts/youtube.js +471 -0
- data/assets/ableplayer/styles/ableplayer.css +1241 -0
- data/assets/ableplayer/thirdparty/js.cookie.js +145 -0
- data/assets/ableplayer/thirdparty/modernizr.custom.js +4 -0
- data/assets/ableplayer/translations/ca.js +1 -0
- data/assets/ableplayer/translations/de.js +1 -0
- data/assets/ableplayer/translations/en.js +305 -0
- data/assets/ableplayer/translations/es.js +305 -0
- data/assets/ableplayer/translations/fr.js +305 -0
- data/assets/ableplayer/translations/it.js +303 -0
- data/assets/ableplayer/translations/ja.js +305 -0
- data/assets/ableplayer/translations/nl.js +305 -0
- data/assets/css/style.css +4360 -0
- data/assets/css/style.css.map +1 -0
- data/assets/fonts/anonymouspro-bold.woff +0 -0
- data/assets/fonts/anonymouspro-bold.woff2 +0 -0
- data/assets/fonts/anonymouspro-bolditalic.woff +0 -0
- data/assets/fonts/anonymouspro-bolditalic.woff2 +0 -0
- data/assets/fonts/anonymouspro-italic.woff +0 -0
- data/assets/fonts/anonymouspro-italic.woff2 +0 -0
- data/assets/fonts/anonymouspro-regular.woff +0 -0
- data/assets/fonts/anonymouspro-regular.woff2 +0 -0
- data/assets/fonts/notosans-bold.woff +0 -0
- data/assets/fonts/notosans-bold.woff2 +0 -0
- data/assets/fonts/notosans-bolditalic.woff +0 -0
- data/assets/fonts/notosans-bolditalic.woff2 +0 -0
- data/assets/fonts/notosans-italic.woff +0 -0
- data/assets/fonts/notosans-italic.woff2 +0 -0
- data/assets/fonts/notosans-regular.woff +0 -0
- data/assets/fonts/notosans-regular.woff2 +0 -0
- data/assets/images/.DS_Store +0 -0
- data/assets/images/Shape.svg +10 -0
- data/assets/images/icon-related-content.svg +14 -0
- data/assets/images/icons.svg +126 -0
- data/assets/images/teaser-image@1x.jpg +0 -0
- data/assets/images/teaser-image@2x.jpg +0 -0
- data/assets/images/w3c.sketch +0 -0
- data/assets/images/w3c.svg +10 -0
- data/assets/scripts/jquery.min.js +4 -0
- data/assets/scripts/main.js +208 -0
- data/assets/scripts/svg4everybody.js +1 -0
- 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);
|