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,725 @@
|
|
|
1
|
+
(function ($) {
|
|
2
|
+
// Set default variable values.
|
|
3
|
+
AblePlayer.prototype.setDefaults = function () {
|
|
4
|
+
|
|
5
|
+
// this.playing will change to true after 'playing' event is triggered
|
|
6
|
+
this.playing = false;
|
|
7
|
+
|
|
8
|
+
this.getUserAgent();
|
|
9
|
+
this.setIconColor();
|
|
10
|
+
this.setButtonImages();
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
AblePlayer.prototype.getRootPath = function() {
|
|
14
|
+
|
|
15
|
+
// returns Able Player root path (assumes ableplayer.js is in /build, one directory removed from root)
|
|
16
|
+
var scripts, i, scriptSrc, scriptFile, fullPath, ablePath, parentFolderIndex, rootPath;
|
|
17
|
+
scripts= document.getElementsByTagName('script');
|
|
18
|
+
for (i=0; i < scripts.length; i++) {
|
|
19
|
+
scriptSrc = scripts[i].src;
|
|
20
|
+
scriptFile = scriptSrc.substr(scriptSrc.lastIndexOf('/'));
|
|
21
|
+
if (scriptFile.indexOf('ableplayer') !== -1) {
|
|
22
|
+
// this is the ableplayerscript
|
|
23
|
+
fullPath = scriptSrc.split('?')[0]; // remove any ? params
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
ablePath= fullPath.split('/').slice(0, -1).join('/'); // remove last filename part of path
|
|
28
|
+
parentFolderIndex = ablePath.lastIndexOf('/');
|
|
29
|
+
rootPath = ablePath.substring(0, parentFolderIndex) + '/';
|
|
30
|
+
return rootPath;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
AblePlayer.prototype.setIconColor = function() {
|
|
34
|
+
|
|
35
|
+
// determine the best color choice (white or black) for icons,
|
|
36
|
+
// given the background-color of their container elements
|
|
37
|
+
// Source for relative luminance formula:
|
|
38
|
+
// https://en.wikipedia.org/wiki/Relative_luminance
|
|
39
|
+
|
|
40
|
+
// We need to know the color *before* creating the element
|
|
41
|
+
// so the element doesn't exist yet when this function is called
|
|
42
|
+
// therefore, need to create a temporary element then remove it after color is determined
|
|
43
|
+
// Temp element must be added to the DOM or WebKit can't retrieve its CSS properties
|
|
44
|
+
|
|
45
|
+
var $elements, i, $el, bgColor, rgb, red, green, blue, luminance, iconColor;
|
|
46
|
+
|
|
47
|
+
$elements = ['controller', 'toolbar'];
|
|
48
|
+
for (i=0; i<$elements.length; i++) {
|
|
49
|
+
if ($elements[i] == 'controller') {
|
|
50
|
+
$el = $('<div>', {
|
|
51
|
+
'class': 'able-controller'
|
|
52
|
+
}).hide();
|
|
53
|
+
}
|
|
54
|
+
else if ($elements[i] === 'toolbar') {
|
|
55
|
+
$el = $('<div>', {
|
|
56
|
+
'class': 'able-window-toolbar'
|
|
57
|
+
}).hide();
|
|
58
|
+
}
|
|
59
|
+
$('body').append($el);
|
|
60
|
+
bgColor = $el.css('background-color');
|
|
61
|
+
// bgColor is a string in the form 'rgb(R, G, B)', perhaps with a 4th item for alpha;
|
|
62
|
+
// split the 3 or 4 channels into an array
|
|
63
|
+
rgb = bgColor.replace(/[^\d,]/g, '').split(',');
|
|
64
|
+
red = rgb[0];
|
|
65
|
+
green = rgb[1];
|
|
66
|
+
blue = rgb[2];
|
|
67
|
+
luminance = (0.2126 * red) + (0.7152 * green) + (0.0722 * blue);
|
|
68
|
+
// range is 1 - 255; therefore 125 is the tipping point
|
|
69
|
+
if (luminance < 125) { // background is dark
|
|
70
|
+
iconColor = 'white';
|
|
71
|
+
}
|
|
72
|
+
else { // background is light
|
|
73
|
+
iconColor = 'black';
|
|
74
|
+
}
|
|
75
|
+
if ($elements[i] === 'controller') {
|
|
76
|
+
this.iconColor = iconColor;
|
|
77
|
+
}
|
|
78
|
+
else if ($elements[i] === 'toolbar') {
|
|
79
|
+
this.toolbarIconColor = iconColor;
|
|
80
|
+
}
|
|
81
|
+
$el.remove();
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
AblePlayer.prototype.setButtonImages = function() {
|
|
86
|
+
|
|
87
|
+
// NOTE: volume button images are now set dynamically within volume.js
|
|
88
|
+
this.imgPath = this.rootPath + 'button-icons/' + this.iconColor + '/';
|
|
89
|
+
this.playButtonImg = this.imgPath + 'play.png';
|
|
90
|
+
this.pauseButtonImg = this.imgPath + 'pause.png';
|
|
91
|
+
|
|
92
|
+
this.restartButtonImg = this.imgPath + 'restart.png';
|
|
93
|
+
|
|
94
|
+
this.rewindButtonImg = this.imgPath + 'rewind.png';
|
|
95
|
+
this.forwardButtonImg = this.imgPath + 'forward.png';
|
|
96
|
+
|
|
97
|
+
this.previousButtonImg = this.imgPath + 'previous.png';
|
|
98
|
+
this.nextButtonImg = this.imgPath + 'next.png';
|
|
99
|
+
|
|
100
|
+
if (this.speedIcons === 'arrows') {
|
|
101
|
+
this.fasterButtonImg = this.imgPath + 'slower.png';
|
|
102
|
+
this.slowerButtonImg = this.imgPath + 'faster.png';
|
|
103
|
+
}
|
|
104
|
+
else if (this.speedIcons === 'animals') {
|
|
105
|
+
this.fasterButtonImg = this.imgPath + 'rabbit.png';
|
|
106
|
+
this.slowerButtonImg = this.imgPath + 'turtle.png';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this.captionsButtonImg = this.imgPath + 'captions.png';
|
|
110
|
+
this.chaptersButtonImg = this.imgPath + 'chapters.png';
|
|
111
|
+
this.signButtonImg = this.imgPath + 'sign.png';
|
|
112
|
+
this.transcriptButtonImg = this.imgPath + 'transcript.png';
|
|
113
|
+
this.descriptionsButtonImg = this.imgPath + 'descriptions.png';
|
|
114
|
+
|
|
115
|
+
this.fullscreenExpandButtonImg = this.imgPath + 'fullscreen-expand.png';
|
|
116
|
+
this.fullscreenCollapseButtonImg = this.imgPath + 'fullscreen-collapse.png';
|
|
117
|
+
|
|
118
|
+
this.prefsButtonImg = this.imgPath + 'preferences.png';
|
|
119
|
+
this.helpButtonImg = this.imgPath + 'help.png';
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Initialize player based on data on page.
|
|
123
|
+
// This sets some variables, but does not modify anything. Safe to call multiple times.
|
|
124
|
+
// Can call again after updating this.media so long as new media element has the same ID.
|
|
125
|
+
AblePlayer.prototype.reinitialize = function () {
|
|
126
|
+
|
|
127
|
+
var deferred, promise, thisObj, errorMsg, srcFile;
|
|
128
|
+
|
|
129
|
+
deferred = new $.Deferred();
|
|
130
|
+
promise = deferred.promise();
|
|
131
|
+
thisObj = this;
|
|
132
|
+
|
|
133
|
+
// if F12 Developer Tools aren't open in IE (through 9, no longer a problen in IE10)
|
|
134
|
+
// console.log causes an error - can't use debug without a console to log messages to
|
|
135
|
+
if (! window.console) {
|
|
136
|
+
this.debug = false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this.startedPlaying = false;
|
|
140
|
+
// TODO: Move this setting to cookie.
|
|
141
|
+
this.autoScrollTranscript = true;
|
|
142
|
+
//this.autoScrollTranscript = this.getCookie(autoScrollTranscript); // (doesn't work)
|
|
143
|
+
|
|
144
|
+
// Bootstrap from this.media possibly being an ID or other selector.
|
|
145
|
+
this.$media = $(this.media).first();
|
|
146
|
+
this.media = this.$media[0];
|
|
147
|
+
|
|
148
|
+
// Set media type to 'audio' or 'video'; this determines some of the behavior of player creation.
|
|
149
|
+
if (this.$media.is('audio')) {
|
|
150
|
+
this.mediaType = 'audio';
|
|
151
|
+
}
|
|
152
|
+
else if (this.$media.is('video')) {
|
|
153
|
+
this.mediaType = 'video';
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
this.mediaType = this.$media.get(0).tagName;
|
|
157
|
+
errorMsg = 'Media player initialized with ' + this.mediaType + '#' + this.mediaId + '. ';
|
|
158
|
+
errorMsg += 'Expecting an HTML5 audio or video element.';
|
|
159
|
+
this.provideFallback(errorMsg);
|
|
160
|
+
deferred.fail();
|
|
161
|
+
return promise;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
this.$sources = this.$media.find('source');
|
|
165
|
+
|
|
166
|
+
this.player = this.getPlayer();
|
|
167
|
+
if (!this.player) {
|
|
168
|
+
// an error was generated in getPlayer()
|
|
169
|
+
this.provideFallback(this.error);
|
|
170
|
+
}
|
|
171
|
+
this.setIconType();
|
|
172
|
+
this.setDimensions();
|
|
173
|
+
|
|
174
|
+
deferred.resolve();
|
|
175
|
+
return promise;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
AblePlayer.prototype.setDimensions = function() {
|
|
179
|
+
// if <video> element includes width and height attributes,
|
|
180
|
+
// use these to set the max-width and max-height of the player
|
|
181
|
+
if (this.$media.attr('width') && this.$media.attr('height')) {
|
|
182
|
+
this.playerMaxWidth = parseInt(this.$media.attr('width'), 10);
|
|
183
|
+
this.playerMaxHeight = parseInt(this.$media.attr('height'), 10);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
// set width to width of #player
|
|
187
|
+
// don't set height though; YouTube will automatically set that to match width
|
|
188
|
+
this.playerMaxWidth = this.$media.parent().width();
|
|
189
|
+
this.playerMaxHeight = this.getMatchingHeight(this.playerMaxWidth);
|
|
190
|
+
}
|
|
191
|
+
// override width and height attributes with in-line CSS to make video responsive
|
|
192
|
+
this.$media.css({
|
|
193
|
+
'width': '100%',
|
|
194
|
+
'height': 'auto'
|
|
195
|
+
});
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
AblePlayer.prototype.getMatchingHeight = function(width) {
|
|
199
|
+
|
|
200
|
+
// returns likely height for a video, given width
|
|
201
|
+
// These calculations assume 16:9 aspect ratio (the YouTube standard)
|
|
202
|
+
// Videos recorded in other resolutions will be sized to fit, with black bars on each side
|
|
203
|
+
// This function is only called if the <video> element does not have width and height attributes
|
|
204
|
+
|
|
205
|
+
var widths, heights, closestWidth, closestIndex, closestHeight, height;
|
|
206
|
+
|
|
207
|
+
widths = [ 3840, 2560, 1920, 1280, 854, 640, 426 ];
|
|
208
|
+
heights = [ 2160, 1440, 1080, 720, 480, 360, 240 ];
|
|
209
|
+
closestWidth = null;
|
|
210
|
+
closestIndex = null;
|
|
211
|
+
|
|
212
|
+
$.each(widths, function(index){
|
|
213
|
+
if (closestWidth == null || Math.abs(this - width) < Math.abs(closestWidth - width)) {
|
|
214
|
+
closestWidth = this;
|
|
215
|
+
closestIndex = index;
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
closestHeight = heights[closestIndex];
|
|
219
|
+
this.aspectRatio = closestWidth / closestHeight;
|
|
220
|
+
height = Math.round(width / this.aspectRatio);
|
|
221
|
+
return height;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
AblePlayer.prototype.setIconType = function() {
|
|
225
|
+
// returns either "font" or "image"
|
|
226
|
+
// create a temporary play span and check to see if button has font-family == "able" (the default)
|
|
227
|
+
// if it doesn't, user has a custom style sheet and icon fonts will not display properly
|
|
228
|
+
// use images as fallback
|
|
229
|
+
|
|
230
|
+
var $tempButton, $testButton, controllerFont;
|
|
231
|
+
|
|
232
|
+
if (this.forceIconType) {
|
|
233
|
+
// use value specified in data-icon-type
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (window.getComputedStyle) {
|
|
238
|
+
|
|
239
|
+
// webkit doesn't return calculated styles unless element has been added to the DOM
|
|
240
|
+
// and is visible (note: visibly clipped is considered "visible")
|
|
241
|
+
// use playpauseButton for font-family test if it exists; otherwise must create a new temp button
|
|
242
|
+
if ($('span.icon-play').length) {
|
|
243
|
+
$testButton = $('span.icon-play');
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
$tempButton = $('<span>',{
|
|
247
|
+
'class': 'icon-play able-clipped'
|
|
248
|
+
});
|
|
249
|
+
$('body').append($tempButton);
|
|
250
|
+
$testButton = $tempButton;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// the following retrieves the computed value of font-family
|
|
254
|
+
// tested in Firefox 45.x with "Allow pages to choose their own fonts" unchecked - works!
|
|
255
|
+
// tested in Chrome 49.x with Font Changer plugin - works!
|
|
256
|
+
// tested in IE with user-defined style sheet enables - works!
|
|
257
|
+
// It does NOT account for users who have "ignore font styles on web pages" checked in IE
|
|
258
|
+
// There is no known way to check for that ???
|
|
259
|
+
controllerFont = window.getComputedStyle($testButton.get(0), null).getPropertyValue('font-family');
|
|
260
|
+
if (typeof controllerFont !== 'undefined') {
|
|
261
|
+
if (controllerFont.indexOf('able') !== -1) {
|
|
262
|
+
this.iconType = 'font';
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
this.iconType = 'image';
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
// couldn't get computed font-family; use images to be safe
|
|
270
|
+
this.iconType = 'image';
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
else { // window.getComputedStyle is not supported (IE 8 and earlier)
|
|
274
|
+
// No known way to detect computed font
|
|
275
|
+
// The following retrieves the value from the style sheet, not the computed font
|
|
276
|
+
// controllerFont = $tempButton.get(0).currentStyle.fontFamily;
|
|
277
|
+
// It will therefore return "able", even if the user is overriding that with a custom style sheet
|
|
278
|
+
// To be safe, use images
|
|
279
|
+
this.iconType = 'image';
|
|
280
|
+
}
|
|
281
|
+
if (this.debug) {
|
|
282
|
+
console.log('Using ' + this.iconType + 's for player controls');
|
|
283
|
+
}
|
|
284
|
+
if (typeof $tempButton !== 'undefined') {
|
|
285
|
+
$tempButton.remove();
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
// Perform one-time setup for this instance of player; called after player is first initialized.
|
|
291
|
+
AblePlayer.prototype.setupInstance = function () {
|
|
292
|
+
var deferred = new $.Deferred();
|
|
293
|
+
var promise = deferred.promise();
|
|
294
|
+
|
|
295
|
+
if (this.$media.attr('id')) {
|
|
296
|
+
this.mediaId = this.$media.attr('id');
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
// Ensure the base media element always has an ID.
|
|
300
|
+
this.mediaId = "ableMediaId_" + this.ableIndex;
|
|
301
|
+
this.$media.attr('id', this.mediaId);
|
|
302
|
+
}
|
|
303
|
+
// get playlist for this media element
|
|
304
|
+
this.setupInstancePlaylist();
|
|
305
|
+
|
|
306
|
+
deferred.resolve();
|
|
307
|
+
return promise;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
AblePlayer.prototype.setupInstancePlaylist = function() {
|
|
311
|
+
// find a matching playlist and set this.hasPlaylist
|
|
312
|
+
// if there is one, also set this.$playlist, this.playlistIndex, & this.playlistEmbed
|
|
313
|
+
var thisObj = this;
|
|
314
|
+
|
|
315
|
+
this.hasPlaylist = false; // will change to true if a matching playlist is found
|
|
316
|
+
|
|
317
|
+
$('.able-playlist').each(function() {
|
|
318
|
+
if ($(this).data('player') === thisObj.mediaId) {
|
|
319
|
+
// this is the playlist for the current player
|
|
320
|
+
thisObj.hasPlaylist = true;
|
|
321
|
+
// If using an embedded player, we'll replace $playlist with the clone later.
|
|
322
|
+
thisObj.$playlist = $(this).find('li');
|
|
323
|
+
// add tabindex to each list item
|
|
324
|
+
$(this).find('li').attr('tabindex', '0');
|
|
325
|
+
thisObj.playlistIndex = 0;
|
|
326
|
+
var dataEmbedded = $(this).data('embedded');
|
|
327
|
+
if (typeof dataEmbedded !== 'undefined' && dataEmbedded !== false) {
|
|
328
|
+
// embed playlist within player
|
|
329
|
+
thisObj.playlistEmbed = true;
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
thisObj.playlistEmbed = false;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
if (this.hasPlaylist && this.playlistEmbed) {
|
|
338
|
+
// Copy the playlist out of the dom, so we can reinject when we build the player.
|
|
339
|
+
var parent = this.$playlist.parent();
|
|
340
|
+
this.$playlistDom = parent.clone();
|
|
341
|
+
parent.remove();
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
// Creates the appropriate player for the current source.
|
|
346
|
+
AblePlayer.prototype.recreatePlayer = function () {
|
|
347
|
+
|
|
348
|
+
var thisObj, prefsGroups, i;
|
|
349
|
+
thisObj = this;
|
|
350
|
+
|
|
351
|
+
// TODO: Ensure when recreating player that we carry over the mediaId
|
|
352
|
+
if (!this.player) {
|
|
353
|
+
console.log("Can't create player; no appropriate player type detected.");
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// moved this until after setupTracks() is complete
|
|
358
|
+
// used to work fine in this location but was broken in Safari 10
|
|
359
|
+
// this.setMediaAttributes();
|
|
360
|
+
|
|
361
|
+
this.loadCurrentPreferences();
|
|
362
|
+
|
|
363
|
+
this.injectPlayerCode();
|
|
364
|
+
this.initSignLanguage();
|
|
365
|
+
this.setupTracks().then(function() {
|
|
366
|
+
|
|
367
|
+
// moved this here; in its original location was not working in Safari 10
|
|
368
|
+
thisObj.setMediaAttributes();
|
|
369
|
+
|
|
370
|
+
thisObj.setupAltCaptions().then(function() {
|
|
371
|
+
|
|
372
|
+
if (thisObj.transcriptType === 'external' || thisObj.transcriptType === 'popup') {
|
|
373
|
+
if (thisObj.captions.length <= 1) {
|
|
374
|
+
// without captions/subtitles in multiple languages,
|
|
375
|
+
// there is no need for a transcript language selector
|
|
376
|
+
thisObj.$transcriptLanguageSelect.parent().remove();
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
thisObj.initDescription();
|
|
381
|
+
thisObj.initDefaultCaption();
|
|
382
|
+
|
|
383
|
+
thisObj.initPlayer().then(function() { // initPlayer success
|
|
384
|
+
thisObj.initializing = false;
|
|
385
|
+
|
|
386
|
+
// inject each of the hidden forms that will be accessed from the Preferences popup menu
|
|
387
|
+
prefsGroups = thisObj.getPreferencesGroups();
|
|
388
|
+
for (i = 0; i < prefsGroups.length; i++) {
|
|
389
|
+
thisObj.injectPrefsForm(prefsGroups[i]);
|
|
390
|
+
}
|
|
391
|
+
thisObj.setupPopups();
|
|
392
|
+
thisObj.updateCaption();
|
|
393
|
+
thisObj.updateTranscript();
|
|
394
|
+
if (thisObj.chaptersDivLocation) {
|
|
395
|
+
thisObj.populateChaptersDiv();
|
|
396
|
+
}
|
|
397
|
+
thisObj.showSearchResults();
|
|
398
|
+
},
|
|
399
|
+
function() { // initPlayer fail
|
|
400
|
+
thisObj.provideFallback(this.error);
|
|
401
|
+
}
|
|
402
|
+
);
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
AblePlayer.prototype.initPlayer = function () {
|
|
408
|
+
|
|
409
|
+
var thisObj = this;
|
|
410
|
+
var playerPromise;
|
|
411
|
+
|
|
412
|
+
// First run player specific initialization.
|
|
413
|
+
if (this.player === 'html5') {
|
|
414
|
+
playerPromise = this.initHtml5Player();
|
|
415
|
+
}
|
|
416
|
+
else if (this.player === 'jw') {
|
|
417
|
+
playerPromise = this.initJwPlayer();
|
|
418
|
+
}
|
|
419
|
+
else if (this.player === 'youtube') {
|
|
420
|
+
playerPromise = this.initYouTubePlayer();
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// After player specific initialization is done, run remaining general initialization.
|
|
424
|
+
var deferred = new $.Deferred();
|
|
425
|
+
var promise = deferred.promise();
|
|
426
|
+
playerPromise.done(
|
|
427
|
+
function () { // done/resolved
|
|
428
|
+
if (thisObj.useFixedSeekInterval === false) {
|
|
429
|
+
thisObj.setSeekInterval();
|
|
430
|
+
}
|
|
431
|
+
thisObj.addControls();
|
|
432
|
+
thisObj.addEventListeners();
|
|
433
|
+
// Calling these set functions also initializes some icons.
|
|
434
|
+
if (thisObj.Volume) {
|
|
435
|
+
thisObj.setMute(false);
|
|
436
|
+
}
|
|
437
|
+
thisObj.setFullscreen(false);
|
|
438
|
+
thisObj.setVolume(thisObj.defaultVolume);
|
|
439
|
+
thisObj.refreshControls();
|
|
440
|
+
|
|
441
|
+
// After done messing with the player, this is necessary to fix playback on iOS
|
|
442
|
+
if (thisObj.player === 'html5' && thisObj.isIOS()) {
|
|
443
|
+
thisObj.$media[0].load();
|
|
444
|
+
}
|
|
445
|
+
deferred.resolve();
|
|
446
|
+
}
|
|
447
|
+
).fail(function () { // failed
|
|
448
|
+
deferred.reject();
|
|
449
|
+
}
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
return promise;
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
AblePlayer.prototype.setSeekInterval = function () {
|
|
456
|
+
// this function is only called if this.useFixedSeekInterval is false
|
|
457
|
+
// if this.useChapterTimes, this is called as each new chapter is loaded
|
|
458
|
+
// otherwise, it's called once, as the player is initialized
|
|
459
|
+
var duration;
|
|
460
|
+
this.seekInterval = this.defaultSeekInterval;
|
|
461
|
+
if (this.useChapterTimes) {
|
|
462
|
+
duration = this.chapterDuration;
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
duration = this.getDuration();
|
|
466
|
+
}
|
|
467
|
+
if (typeof duration === 'undefined' || duration < 1) {
|
|
468
|
+
// no duration; just use default for now but keep trying until duration is available
|
|
469
|
+
this.seekIntervalCalculated = false;
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
if (duration <= 20) {
|
|
474
|
+
this.seekInterval = 5; // 4 steps max
|
|
475
|
+
}
|
|
476
|
+
else if (duration <= 30) {
|
|
477
|
+
this.seekInterval = 6; // 5 steps max
|
|
478
|
+
}
|
|
479
|
+
else if (duration <= 40) {
|
|
480
|
+
this.seekInterval = 8; // 5 steps max
|
|
481
|
+
}
|
|
482
|
+
else if (duration <= 100) {
|
|
483
|
+
this.seekInterval = 10; // 10 steps max
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
// never more than 10 steps from start to end
|
|
487
|
+
this.seekInterval = (duration / 10);
|
|
488
|
+
}
|
|
489
|
+
this.seekIntervalCalculated = true;
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
AblePlayer.prototype.initDefaultCaption = function () {
|
|
494
|
+
|
|
495
|
+
var captions, i;
|
|
496
|
+
|
|
497
|
+
if (this.usingYouTubeCaptions) {
|
|
498
|
+
captions = this.ytCaptions;
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
captions = this.captions;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (captions.length > 0) {
|
|
505
|
+
for (i=0; i<captions.length; i++) {
|
|
506
|
+
if (captions[i].def === true) {
|
|
507
|
+
this.captionLang = captions[i].language;
|
|
508
|
+
this.selectedCaptions = captions[i];
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (typeof this.captionLang === 'undefined') {
|
|
512
|
+
// No caption track was flagged as default
|
|
513
|
+
// find and use a caption language that matches the player language
|
|
514
|
+
for (i=0; i<captions.length; i++) {
|
|
515
|
+
if (captions[i].language === this.lang) {
|
|
516
|
+
this.captionLang = captions[i].language;
|
|
517
|
+
this.selectedCaptions = captions[i];
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
if (typeof this.captionLang === 'undefined') {
|
|
522
|
+
// Still no matching caption track
|
|
523
|
+
// just use the first track
|
|
524
|
+
this.captionLang = captions[0].language;
|
|
525
|
+
this.selectedCaptions = captions[0];
|
|
526
|
+
}
|
|
527
|
+
if (typeof this.captionLang !== 'undefined') {
|
|
528
|
+
// reset transcript selected <option> to this.captionLang
|
|
529
|
+
if (this.$transcriptLanguageSelect) {
|
|
530
|
+
this.$transcriptLanguageSelect.find('option[lang=' + this.captionLang + ']').prop('selected',true);
|
|
531
|
+
}
|
|
532
|
+
// sync all other tracks to this same languge
|
|
533
|
+
this.syncTrackLanguages('init',this.captionLang);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
AblePlayer.prototype.initHtml5Player = function () {
|
|
539
|
+
// Nothing special to do!
|
|
540
|
+
var deferred = new $.Deferred();
|
|
541
|
+
var promise = deferred.promise();
|
|
542
|
+
deferred.resolve();
|
|
543
|
+
return promise;
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
AblePlayer.prototype.initJwPlayer = function () {
|
|
547
|
+
|
|
548
|
+
var jwHeight;
|
|
549
|
+
var thisObj = this;
|
|
550
|
+
var deferred = new $.Deferred();
|
|
551
|
+
var promise = deferred.promise();
|
|
552
|
+
|
|
553
|
+
$.ajax({
|
|
554
|
+
async: false,
|
|
555
|
+
url: this.fallbackPath + 'jwplayer.js',
|
|
556
|
+
dataType: 'script',
|
|
557
|
+
success: function( data, textStatus, jqXHR) {
|
|
558
|
+
// Successfully loaded the JW Player
|
|
559
|
+
// add an id to div.able-media-container (JW Player needs this)
|
|
560
|
+
thisObj.jwId = thisObj.mediaId + '_fallback';
|
|
561
|
+
thisObj.$mediaContainer.attr('id', thisObj.jwId);
|
|
562
|
+
if (thisObj.mediaType === 'audio') {
|
|
563
|
+
// JW Player always shows its own controls if height <= 40
|
|
564
|
+
// Must set height to 0 to hide them
|
|
565
|
+
jwHeight = 0;
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
jwHeight = thisObj.playerHeight;
|
|
569
|
+
}
|
|
570
|
+
var sources = [];
|
|
571
|
+
$.each(thisObj.$sources, function (ii, source) {
|
|
572
|
+
sources.push({file: $(source).attr('src')});
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
var flashplayer = thisObj.fallbackPath + 'jwplayer.flash.swf';
|
|
576
|
+
var html5player = thisObj.fallbackPath + 'jwplayer.html5.js';
|
|
577
|
+
|
|
578
|
+
// Initializing JW Player with width:100% results in player that is either the size of the video
|
|
579
|
+
// or scaled down to fit the container if container is smaller
|
|
580
|
+
// After onReady event fires, actual dimensions will be collected for future use
|
|
581
|
+
// in preserving the video ratio
|
|
582
|
+
if (thisObj.mediaType === 'video') {
|
|
583
|
+
thisObj.jwPlayer = jwplayer(thisObj.jwId).setup({
|
|
584
|
+
playlist: [{
|
|
585
|
+
image: thisObj.$media.attr('poster'),
|
|
586
|
+
sources: sources
|
|
587
|
+
}],
|
|
588
|
+
flashplayer: flashplayer,
|
|
589
|
+
html5player: html5player,
|
|
590
|
+
controls: false,
|
|
591
|
+
volume: thisObj.defaultVolume * 100,
|
|
592
|
+
width: '100%',
|
|
593
|
+
fallback: false,
|
|
594
|
+
primary: 'flash',
|
|
595
|
+
wmode: 'transparent' // necessary to get HTML captions to appear as overlay
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
else { // if this is an audio player
|
|
599
|
+
thisObj.jwPlayer = jwplayer(thisObj.jwId).setup({
|
|
600
|
+
playlist: [{
|
|
601
|
+
sources: sources
|
|
602
|
+
}],
|
|
603
|
+
flashplayer: flashplayer,
|
|
604
|
+
html5player: html5player,
|
|
605
|
+
controls: false,
|
|
606
|
+
volume: this.defaultVolume * 100,
|
|
607
|
+
height: 0,
|
|
608
|
+
width: '100%',
|
|
609
|
+
fallback: false,
|
|
610
|
+
primary: 'flash'
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
// remove the media element - we're done with it
|
|
614
|
+
// keeping it would cause too many potential problems with HTML5 & JW event listeners both firing
|
|
615
|
+
thisObj.$media.remove();
|
|
616
|
+
|
|
617
|
+
deferred.resolve();
|
|
618
|
+
},
|
|
619
|
+
error: function(jqXHR, textStatus, errorThrown) {
|
|
620
|
+
// Loading the JW Player failed
|
|
621
|
+
this.error = 'Failed to load JW Player.';
|
|
622
|
+
deferred.reject();
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
// Done with JW Player initialization.
|
|
626
|
+
return promise;
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
// Sets media/track/source attributes; is called whenever player is recreated since $media may have changed.
|
|
630
|
+
AblePlayer.prototype.setMediaAttributes = function () {
|
|
631
|
+
// Firefox puts videos in tab order; remove.
|
|
632
|
+
this.$media.attr('tabindex', -1);
|
|
633
|
+
|
|
634
|
+
// Keep native player from displaying captions/subtitles by setting textTrack.mode='disabled'
|
|
635
|
+
// https://dev.w3.org/html5/spec-author-view/video.html#text-track-mode
|
|
636
|
+
// This *should* work but historically hasn't been supported in all browsers
|
|
637
|
+
// Workaround for non-supporting browsers is to remove default attribute
|
|
638
|
+
// We're doing that too in track.js > setupCaptions()
|
|
639
|
+
var textTracks = this.$media.get(0).textTracks;
|
|
640
|
+
if (textTracks) {
|
|
641
|
+
var i = 0;
|
|
642
|
+
while (i < textTracks.length) {
|
|
643
|
+
textTracks[i].mode = 'disabled';
|
|
644
|
+
i += 1;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
AblePlayer.prototype.getPlayer = function() {
|
|
650
|
+
|
|
651
|
+
// Determine which player to use, if any
|
|
652
|
+
// return 'html5', 'jw' or null
|
|
653
|
+
var i, sourceType, $newItem;
|
|
654
|
+
if (this.youTubeId) {
|
|
655
|
+
if (this.mediaType !== 'video') {
|
|
656
|
+
this.error = 'To play a YouTube video, use the <video> tag.';
|
|
657
|
+
return null;
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
return 'youtube';
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
else if (this.testFallback ||
|
|
664
|
+
((this.isUserAgent('msie 7') || this.isUserAgent('msie 8') || this.isUserAgent('msie 9')) && this.mediaType === 'video') ||
|
|
665
|
+
(this.isIOS() && (this.isIOS(4) || this.isIOS(5) || this.isIOS(6)))
|
|
666
|
+
) {
|
|
667
|
+
// the user wants to test the fallback player, or
|
|
668
|
+
// the user is using an older version of IE or IOS,
|
|
669
|
+
// both of which had buggy implementation of HTML5 video
|
|
670
|
+
if (this.fallback === 'jw' && this.jwCanPlay()) {
|
|
671
|
+
return 'jw';
|
|
672
|
+
}
|
|
673
|
+
else {
|
|
674
|
+
this.error = 'The fallback player (JW Player) is unable to play the available media file.';
|
|
675
|
+
return null;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
else if (this.media.canPlayType) {
|
|
679
|
+
return 'html5';
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
this.error = 'This browser does not support the available media file.';
|
|
683
|
+
return null;
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
|
|
687
|
+
AblePlayer.prototype.jwCanPlay = function() {
|
|
688
|
+
// Determine whether there are media files that JW supports
|
|
689
|
+
var i, sourceType, $firstItem;
|
|
690
|
+
|
|
691
|
+
if (this.$sources.length > 0) { // this media has one or more <source> elements
|
|
692
|
+
for (i = 0; i < this.$sources.length; i++) {
|
|
693
|
+
sourceType = this.$sources[i].getAttribute('type');
|
|
694
|
+
if ((this.mediaType === 'video' && sourceType === 'video/mp4') ||
|
|
695
|
+
(this.mediaType === 'audio' && sourceType === 'audio/mpeg')) {
|
|
696
|
+
// JW Player can play this
|
|
697
|
+
return true;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
// still here? That means there's no source that JW can play
|
|
702
|
+
// check for an mp3 or mp4 in a able-playlist
|
|
703
|
+
// TODO: Implement this more efficiently
|
|
704
|
+
// Playlist is initialized later in setupInstancePlaylist()
|
|
705
|
+
// but we can't wait for that...
|
|
706
|
+
if ($('.able-playlist')) {
|
|
707
|
+
// there's at least one playlist on this page
|
|
708
|
+
// get the first item from the first playlist
|
|
709
|
+
// if JW Player can play that one, assume it can play all items in all playlists
|
|
710
|
+
$firstItem = $('.able-playlist').eq(0).find('li').eq(0);
|
|
711
|
+
if (this.mediaType === 'audio') {
|
|
712
|
+
if ($firstItem.attr('data-mp3')) {
|
|
713
|
+
return true;
|
|
714
|
+
}
|
|
715
|
+
else if (this.mediaType === 'video') {
|
|
716
|
+
if ($firstItem.attr('data-mp4')) {
|
|
717
|
+
return true;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return false;
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
})(jQuery);
|