aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/js/plyr.js1017
1 files changed, 463 insertions, 554 deletions
diff --git a/src/js/plyr.js b/src/js/plyr.js
index 63c1aa9c..c41d564b 100644
--- a/src/js/plyr.js
+++ b/src/js/plyr.js
@@ -1,11 +1,9 @@
// ==========================================================================
// Plyr
-// plyr.js v2.0.10
+// plyr.js v3.0.0
// https://github.com/selz/plyr
// License: The MIT License (MIT)
// ==========================================================================
-// Credits: http://paypal.github.io/accessible-html5-video-player/
-// ==========================================================================
(function(root, factory) {
'use strict';
@@ -21,10 +19,11 @@
});
} else {
// Browser globals (root is window)
- root.plyr = factory(root, document);
+ root.Plyr = factory(root, document);
}
}(typeof window !== 'undefined' ? window : this, function(window, document) {
'use strict';
+ /* global jQuery */
// Globals
var scroll = {
@@ -88,8 +87,6 @@
// Selectors
// Change these to match your template if using custom HTML
selectors: {
- html5: 'video, audio',
- embed: '[data-type]',
editable: 'input, textarea, select, [contenteditable]',
container: '.plyr',
controls: {
@@ -271,8 +268,8 @@
},
// Events to watch on HTML5 media elements and bubble
+ // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events
events: [
- 'ready',
'ended',
'progress',
'stalled',
@@ -303,50 +300,51 @@
html5: ['video', 'audio']
};
- // Check variable types
- var is = {
- object: function(input) {
- return input !== null && typeof(input) === 'object' && input.constructor === Object;
- },
- array: function(input) {
- return input !== null && Array.isArray(input);
- },
- number: function(input) {
- return input !== null && (typeof(input) === 'number' && !isNaN(input - 0) || (typeof input === 'object' && input.constructor === Number));
- },
- string: function(input) {
- return input !== null && (typeof input === 'string' || (typeof input === 'object' && input.constructor === String));
- },
- boolean: function(input) {
- return input !== null && typeof input === 'boolean';
- },
- nodeList: function(input) {
- return input !== null && input instanceof NodeList;
- },
- htmlElement: function(input) {
- return input !== null && input instanceof HTMLElement;
- },
- function: function(input) {
- return input !== null && typeof input === 'function';
- },
- event: function(input) {
- return input !== null && input instanceof Event;
- },
- cue: function(input) {
- return input !== null && (input instanceof window.TextTrackCue || input instanceof window.VTTCue);
- },
- track: function(input) {
- return input !== null && input instanceof window.TextTrack;
- },
- undefined: function(input) {
- return input !== null && typeof input === 'undefined';
+ // Utilities outside of Plyr scope
+ var utils = {
+ // Check variable types
+ is: {
+ object: function(input) {
+ return input !== null && typeof(input) === 'object' && input.constructor === Object;
+ },
+ array: function(input) {
+ return input !== null && Array.isArray(input);
+ },
+ number: function(input) {
+ return input !== null && (typeof(input) === 'number' && !isNaN(input - 0) || (typeof input === 'object' && input.constructor === Number));
+ },
+ string: function(input) {
+ return input !== null && (typeof input === 'string' || (typeof input === 'object' && input.constructor === String));
+ },
+ boolean: function(input) {
+ return input !== null && typeof input === 'boolean';
+ },
+ nodeList: function(input) {
+ return input !== null && input instanceof NodeList;
+ },
+ htmlElement: function(input) {
+ return input !== null && input instanceof HTMLElement;
+ },
+ function: function(input) {
+ return input !== null && typeof input === 'function';
+ },
+ event: function(input) {
+ return input !== null && input instanceof Event;
+ },
+ cue: function(input) {
+ return input !== null && (input instanceof window.TextTrackCue || input instanceof window.VTTCue);
+ },
+ track: function(input) {
+ return input !== null && input instanceof window.TextTrack;
+ },
+ undefined: function(input) {
+ return input !== null && typeof input === 'undefined';
+ },
+ empty: function(input) {
+ return input === null || this.undefined(input) || ((this.string(input) || this.array(input) || this.nodeList(input)) && input.length === 0) || (this.object(input) && Object.keys(input).length === 0);
+ }
},
- empty: function(input) {
- return input === null || this.undefined(input) || ((this.string(input) || this.array(input) || this.nodeList(input)) && input.length === 0) || (this.object(input) && Object.keys(input).length === 0);
- }
- };
- var utils = {
// Credits: http://paypal.github.io/accessible-html5-video-player/
// Unfortunately, due to mixed support, UA sniffing is required
getBrowser: function() {
@@ -430,6 +428,47 @@
};
},
+ // Check for support
+ // Basic functionality vs full UI
+ checkSupport: function(type, inline) {
+ var basic = false;
+ var full = false;
+ var browser = utils.getBrowser();
+ var playsInline = (browser.isIPhone && inline && support.inline);
+
+ switch (type) {
+ case 'video':
+ basic = support.video;
+ full = basic && !browser.isOldIE && (!browser.isIPhone || playsInline);
+ break;
+
+ case 'audio':
+ basic = support.audio;
+ full = basic && !browser.isOldIE;
+ break;
+
+ case 'youtube':
+ basic = support.video;
+ full = basic && !browser.isOldIE && (!browser.isIPhone || playsInline);
+ break;
+
+ case 'vimeo':
+ case 'soundcloud':
+ basic = true;
+ full = (!browser.isOldIE && !browser.isIos);
+ break;
+
+ default:
+ basic = (support.audio && support.video);
+ full = (basic && !browser.isOldIE);
+ }
+
+ return {
+ basic: basic,
+ full: full
+ };
+ },
+
// Inject a script
injectScript: function(url) {
// Check script is not already referenced
@@ -455,7 +494,7 @@
// Element exists in an array
inArray: function(haystack, needle) {
- return is.array(haystack) && haystack.indexOf(needle) !== -1;
+ return utils.is.array(haystack) && haystack.indexOf(needle) !== -1;
},
// Replace all
@@ -499,8 +538,8 @@
// Remove an element
removeElement: function(element) {
- if (!is.htmlElement(element) ||
- !is.htmlElement(element.parentNode)) {
+ if (!utils.is.htmlElement(element) ||
+ !utils.is.htmlElement(element.parentNode)) {
return;
}
@@ -523,12 +562,12 @@
var element = document.createElement(type);
// Set all passed attributes
- if (is.object(attributes)) {
+ if (utils.is.object(attributes)) {
utils.setAttributes(element, attributes);
}
// Add text node
- if (is.string(text)) {
+ if (utils.is.string(text)) {
element.textContent = text;
}
@@ -567,7 +606,7 @@
// '#test' to { id: 'test' }
// '[data-test="test"]' to { 'data-test': 'test' }
- if (!is.string(selector) || is.empty(selector)) {
+ if (!utils.is.string(selector) || utils.is.empty(selector)) {
return {};
}
@@ -586,7 +625,7 @@
var className = selector.replace('.', '');
// Add to existing classname
- if (is.object(existingAttributes) && is.string(existingAttributes.class)) {
+ if (utils.is.object(existingAttributes) && utils.is.string(existingAttributes.class)) {
existingAttributes.class += ' ' + className;
}
@@ -651,8 +690,8 @@
prototype.webkitMatchesSelector ||
prototype.mozMatchesSelector ||
prototype.msMatchesSelector ||
- function(s) {
- return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
+ function(selector) {
+ return [].indexOf.call(document.querySelectorAll(selector), this) !== -1;
};
return matches.call(element, selector);
@@ -687,13 +726,13 @@
// Whether the listener is a capturing listener or not
// Default to false
- if (!is.boolean(capture)) {
+ if (!utils.is.boolean(capture)) {
capture = false;
}
// Whether the listener can be passive (i.e. default never prevented)
// Default to true
- if (!is.boolean(passive)) {
+ if (!utils.is.boolean(passive)) {
passive = true;
}
@@ -736,14 +775,14 @@
// Bind event handler
on: function(element, events, callback, passive, capture) {
- if (!is.undefined(element)) {
+ if (!utils.is.undefined(element)) {
utils.toggleListener(element, events, callback, true, passive, capture);
}
},
// Unbind event handler
off: function(element, events, callback, passive, capture) {
- if (!is.undefined(element)) {
+ if (!utils.is.undefined(element)) {
utils.toggleListener(element, events, callback, false, passive, capture);
}
},
@@ -756,10 +795,30 @@
}
// Default bubbles to false
- if (!is.boolean(bubbles)) {
+ if (!utils.is.boolean(bubbles)) {
bubbles = false;
}
+ // Create CustomEvent constructor
+ var CustomEvent;
+ if (utils.is.function(window.CustomEvent)) {
+ CustomEvent = window.CustomEvent;
+ } else {
+ // Polyfill CustomEvent
+ // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
+ CustomEvent = function(event, params) {
+ params = params || {
+ bubbles: false,
+ cancelable: false,
+ detail: undefined
+ };
+ var custom = document.createEvent('CustomEvent');
+ custom.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
+ return custom;
+ };
+ CustomEvent.prototype = window.Event.prototype;
+ }
+
// Create and dispatch the event
var event = new CustomEvent(type, {
bubbles: bubbles,
@@ -779,7 +838,7 @@
}
// Get state
- state = (is.boolean(state) ? state : !target.getAttribute('aria-pressed'));
+ state = (utils.is.boolean(state) ? state : !target.getAttribute('aria-pressed'));
// Set the attribute on target
target.setAttribute('aria-pressed', state);
@@ -814,7 +873,7 @@
// First object is the destination
var destination = Array.prototype.shift.call(objects);
- if (!is.object(destination)) {
+ if (!utils.is.object(destination)) {
destination = {};
}
@@ -824,7 +883,7 @@
for (var i = 0; i < length; i++) {
var source = objects[i];
- if (!is.object(source)) {
+ if (!utils.is.object(source)) {
source = {};
}
@@ -854,6 +913,70 @@
fragment.appendChild(element);
element.innerHTML = source;
return fragment.firstChild.innerText;
+ },
+
+ // Load an SVG sprite
+ loadSprite: function(url, id) {
+ if (typeof url !== 'string') {
+ return;
+ }
+
+ var prefix = 'cache-';
+ var hasId = typeof id === 'string';
+ var isCached = false;
+
+ function updateSprite(container, data) {
+ // Inject content
+ container.innerHTML = data;
+
+ // Inject the SVG to the body
+ document.body.insertBefore(container, document.body.childNodes[0]);
+ }
+
+ // Only load once
+ if (!hasId || !document.querySelectorAll('#' + id).length) {
+ // Create container
+ var container = document.createElement('div');
+ container.setAttribute('hidden', '');
+
+ if (hasId) {
+ container.setAttribute('id', id);
+ }
+
+ // Check in cache
+ if (support.storage) {
+ var cached = window.localStorage.getItem(prefix + id);
+ isCached = cached !== null;
+
+ if (isCached) {
+ var data = JSON.parse(cached);
+ updateSprite(container, data.content);
+ }
+ }
+
+ // ReSharper disable once InconsistentNaming
+ var xhr = new XMLHttpRequest();
+
+ // XHR for Chrome/Firefox/Opera/Safari
+ if ('withCredentials' in xhr) {
+ xhr.open('GET', url, true);
+ } else {
+ return;
+ }
+
+ // Once loaded, inject to container and body
+ xhr.onload = function() {
+ if (support.storage) {
+ window.localStorage.setItem(prefix + id, JSON.stringify({
+ content: xhr.responseText
+ }));
+ }
+
+ updateSprite(container, xhr.responseText);
+ };
+
+ xhr.send();
+ }
}
};
@@ -863,15 +986,15 @@
var prefix = (function() {
var value = false;
- if (is.function(document.cancelFullScreen)) {
+ if (utils.is.function(document.cancelFullScreen)) {
value = '';
} else {
// Check for fullscreen support by vendor prefix
['webkit', 'o', 'moz', 'ms', 'khtml'].some(function(prefix) {
- if (is.function(document[prefix + 'CancelFullScreen'])) {
+ if (utils.is.function(document[prefix + 'CancelFullScreen'])) {
value = prefix;
return true;
- } else if (is.function(document.msExitFullscreen) && document.msFullscreenEnabled) {
+ } else if (utils.is.function(document.msExitFullscreen) && document.msFullscreenEnabled) {
// Special case for MS (when isn't it?)
value = 'ms';
return true;
@@ -893,7 +1016,7 @@
if (!support.fullscreen) {
return false;
}
- if (is.undefined(element)) {
+ if (utils.is.undefined(element)) {
element = document.body;
}
switch (this.prefix) {
@@ -909,7 +1032,7 @@
if (!support.fullscreen) {
return false;
}
- if (!is.htmlElement(element)) {
+ if (!utils.is.htmlElement(element)) {
element = document.body;
}
return (prefix === '') ? element.requestFullScreen() : element[prefix + (prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')]();
@@ -929,7 +1052,7 @@
};
})();
- // Check for support
+ // Check for feature support
var support = {
// Basic support
audio: 'canPlayType' in document.createElement('audio'),
@@ -947,18 +1070,11 @@
// Try to use it (it might be disabled, e.g. user is in private/porn mode)
// see: https://github.com/Selz/plyr/issues/131
+ var test = '___test';
try {
- // Add test item
- window.localStorage.setItem('___test', 'OK');
-
- // Get the test item
- var result = window.localStorage.getItem('___test');
-
- // Clean up
- window.localStorage.removeItem('___test');
-
- // Check if value matches
- return (result === 'OK');
+ window.localStorage.setItem(test, test);
+ window.localStorage.removeItem(test);
+ return true;
} catch (e) {
return false;
}
@@ -970,12 +1086,12 @@
// Safari only currently
pip: (function() {
var browser = utils.getBrowser();
- return !browser.isIPhone && is.function(utils.createElement('video').webkitSetPresentationMode);
+ return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode);
})(),
// Airplay support
// Safari only currently
- airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),
+ airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent),
// Inline playback support
// https://webkit.org/blog/6784/new-video-policies-for-ios/
@@ -989,7 +1105,7 @@
try {
// Bail if no checking function
- if (!is.function(media.canPlayType)) {
+ if (!utils.is.function(media.canPlayType)) {
return false;
}
@@ -1048,14 +1164,27 @@
};
// Player instance
- function Plyr(media, config) {
+ function Player(element, options) {
var player = this;
var timers = {};
- var api;
+ var api = {};
- player.fullscreen = {
- active: false
- };
+ // String selector passed
+ if (utils.is.string(element)) {
+ element = document.querySelectorAll(element);
+ }
+
+ // jQuery, NodeList or Array passed, use first element
+ if ((window.jQuery && element instanceof jQuery) || utils.is.nodeList(element) || utils.is.array(element)) {
+ element = element[0];
+ }
+
+ // Config
+ var config = utils.extend({}, defaults, options, (function() {
+ try {
+ return JSON.parse(element.getAttribute('data-plyr'));
+ } catch (e) {}
+ })());
// Elements cache
player.elements = {
@@ -1069,7 +1198,7 @@
panes: {},
tabs: {}
},
- media: media,
+ media: element,
captions: null
};
@@ -1081,15 +1210,19 @@
currentTrack: null
};
- // Set media
- var original = media.cloneNode(true);
+ // Fullscreen
+ player.fullscreen = {
+ active: false
+ };
// Debugging
var log = function() {};
var warn = function() {};
+ var error = function() {};
if (config.debug && 'console' in window) {
log = window.console.log;
warn = window.console.warn;
+ error = window.console.error;
}
// Log config options and support
@@ -1115,9 +1248,10 @@
function removeElement(element) {
// Remove reference from player.elements cache
- if (is.string(element)) {
+ if (utils.is.string(element)) {
utils.removeElement(player.elements[element]);
player.elements[element] = null;
+
} else {
utils.removeElement(element);
}
@@ -1150,11 +1284,11 @@
// Add elements to HTML5 media (source, tracks, etc)
function insertElements(type, attributes) {
- if (is.string(attributes)) {
+ if (utils.is.string(attributes)) {
utils.insertElement(type, player.elements.media, {
src: attributes
});
- } else if (is.array(attributes)) {
+ } else if (utils.is.array(attributes)) {
attributes.forEach(function(attribute) {
utils.insertElement(type, player.elements.media, attribute);
});
@@ -1230,7 +1364,7 @@
var iconToggled;
var labelKey;
- if (!is.object(attributes)) {
+ if (!utils.is.object(attributes)) {
attributes = {};
}
@@ -1278,7 +1412,7 @@
utils.extend(attributes, utils.getAttributesFromSelector(config.selectors.buttons[type], attributes));
// Add toggle icon if needed
- if (is.string(iconToggled)) {
+ if (utils.is.string(iconToggled)) {
button.appendChild(createIcon(iconToggled, {
class: 'icon--' + iconToggled
}));
@@ -1665,7 +1799,7 @@
}
}
- if (is.array(options) && !is.empty(options)) {
+ if (utils.is.array(options) && !utils.is.empty(options)) {
options.filter(function(quality) {
// Remove any unwanted quality levels
return !utils.inArray(['tiny', 'small'], quality);
@@ -1692,7 +1826,7 @@
label.appendChild(document.createTextNode(getLabel(quality)));
var badge = getBadge(quality);
- if (is.htmlElement(badge)) {
+ if (utils.is.htmlElement(badge)) {
label.appendChild(badge);
}
@@ -1739,7 +1873,7 @@
utils.emptyElement(list);
// If there's no captions, bail
- if (is.empty(player.captions.tracks)) {
+ if (utils.is.empty(player.captions.tracks)) {
return;
}
@@ -1748,7 +1882,7 @@
return {
language: track.language,
badge: true,
- label: !is.empty(track.label) ? track.label : track.language.toUpperCase()
+ label: !utils.is.empty(track.label) ? track.label : track.language.toUpperCase()
}
});
@@ -1799,7 +1933,7 @@
utils.emptyElement(list);
// If there's no captions, bail
- if (!is.array(options)) {
+ if (!utils.is.array(options)) {
options = config.speed.options;
}
@@ -1868,19 +2002,19 @@
}
// Inject the container
- if (!is.htmlElement(player.elements.captions)) {
+ if (!utils.is.htmlElement(player.elements.captions)) {
player.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(config.selectors.captions));
utils.insertAfter(player.elements.captions, player.elements.wrapper);
}
// Get tracks
- player.captions.tracks = is.array(tracks) ? tracks : player.elements.media.textTracks;
+ player.captions.tracks = utils.is.array(tracks) ? tracks : player.elements.media.textTracks;
// Set the class hook
- utils.toggleClass(player.elements.container, config.classes.captions.enabled, !is.empty(player.captions.tracks));
+ utils.toggleClass(player.elements.container, config.classes.captions.enabled, !utils.is.empty(player.captions.tracks));
// If no caption file exists, hide container for caption text
- if (is.empty(player.captions.tracks)) {
+ if (utils.is.empty(player.captions.tracks)) {
return;
}
@@ -1905,14 +2039,14 @@
});
// If we couldn't get the requested language, we get the first
- if (!is.track(player.captions.currentTrack)) {
+ if (!utils.is.track(player.captions.currentTrack)) {
warn('No language found to match ' + language + ' in tracks');
player.captions.currentTrack = player.captions.tracks[0];
}
// If it's a caption or subtitle, render it
var track = player.captions.currentTrack;
- if (is.track(track) && utils.inArray(['captions', 'subtitles'], track.kind)) {
+ if (utils.is.track(track) && utils.inArray(['captions', 'subtitles'], track.kind)) {
utils.on(track, 'cuechange', setActiveCue);
// If we change the active track while a cue is already displayed we need to update it
@@ -1928,7 +2062,7 @@
// Get current selected caption language
function getLanguage() {
- if (!support.textTracks || is.empty(player.captions.tracks)) {
+ if (!support.textTracks || utils.is.empty(player.captions.tracks)) {
return 'No Subs';
}
@@ -1942,14 +2076,14 @@
// Display active caption if it contains text
function setActiveCue(track) {
// Get the track from the event if needed
- if (is.event(track)) {
+ if (utils.is.event(track)) {
track = track.target;
}
var active = track.activeCues[0];
// Display a cue, if there is one
- if (is.cue(active)) {
+ if (utils.is.cue(active)) {
setCaption(active.getCueAsHTML());
} else {
setCaption();
@@ -1959,9 +2093,9 @@
// Select active caption
function setLanguage(language) {
// Save config
- if (is.string(language)) {
+ if (utils.is.string(language)) {
config.captions.language = language.toLowerCase();
- } else if (is.event(language)) {
+ } else if (utils.is.event(language)) {
config.captions.language = language.target.value.toLowerCase();
}
@@ -1974,19 +2108,19 @@
// Set the current caption
function setCaption(caption) {
- if (is.htmlElement(player.elements.captions)) {
+ if (utils.is.htmlElement(player.elements.captions)) {
var content = utils.createElement('span');
// Empty the container
utils.emptyElement(player.elements.captions);
// Default to empty
- if (is.undefined(caption)) {
+ if (utils.is.undefined(caption)) {
caption = '';
}
// Set the span content
- if (is.string(caption)) {
+ if (utils.is.string(caption)) {
content.textContent = caption.trim();
} else {
content.appendChild(caption);
@@ -2013,7 +2147,7 @@
var active = player.storage.captions;
// Otherwise fall back to the default config
- if (!is.boolean(active)) {
+ if (!utils.is.boolean(active)) {
active = config.captions.active;
} else {
config.captions.active = active;
@@ -2033,7 +2167,7 @@
}
// If the method is called without parameter, toggle based on current value
- if (!is.boolean(show)) {
+ if (!utils.is.boolean(show)) {
show = (player.elements.container.className.indexOf(config.classes.captions.active) === -1);
}
@@ -2064,7 +2198,7 @@
// Only load external sprite using AJAX
if (iconUrl.absolute) {
log('AJAX loading absolute SVG sprite' + (player.browser.isIE ? ' (due to IE)' : ''));
- loadSprite(iconUrl.url, "sprite-plyr");
+ utils.loadSprite(iconUrl.url, "sprite-plyr");
} else {
log('Sprite will be used as external resource directly');
}
@@ -2083,12 +2217,12 @@
var controls = null;
// HTML passed as the option
- if (is.string(config.controls)) {
+ if (utils.is.string(config.controls)) {
controls = config.controls;
}
// A custom function to build controls
// The function can return a HTMLElement or String
- else if (is.function(config.controls)) {
+ else if (utils.is.function(config.controls)) {
controls = config.controls({
id: player.id,
seektime: config.seekTime
@@ -2112,24 +2246,24 @@
var target;
// Inject to custom location
- if (is.string(config.selectors.controls.container)) {
+ if (utils.is.string(config.selectors.controls.container)) {
target = document.querySelector(config.selectors.controls.container);
}
// Inject into the container by default
- if (!is.htmlElement(target)) {
+ if (!utils.is.htmlElement(target)) {
target = player.elements.container
}
// Inject controls HTML
- if (is.htmlElement(controls)) {
+ if (utils.is.htmlElement(controls)) {
target.appendChild(controls);
} else {
target.insertAdjacentHTML('beforeend', controls);
}
// Find the elements if need be
- if (is.htmlElement(player.elements.controls)) {
+ if (utils.is.htmlElement(player.elements.controls)) {
findElements();
}
@@ -2186,7 +2320,7 @@
};
// Seek tooltip
- if (is.htmlElement(player.elements.progress)) {
+ if (utils.is.htmlElement(player.elements.progress)) {
player.elements.display.seekTooltip = player.elements.progress.querySelector('.' + config.classes.tooltip);
}
@@ -2222,7 +2356,7 @@
var label = config.i18n.play;
// If there's a media title set, use that for the label
- if (is.string(config.title) && !is.empty(config.title)) {
+ if (utils.is.string(config.title) && !utils.is.empty(config.title)) {
label += ', ' + config.title;
// Set container label
@@ -2231,18 +2365,18 @@
// If there's a play button, set label
if (player.supported.full) {
- if (is.htmlElement(player.elements.buttons.play)) {
+ if (utils.is.htmlElement(player.elements.buttons.play)) {
player.elements.buttons.play.setAttribute('aria-label', label);
}
- if (is.htmlElement(player.elements.buttons.playLarge)) {
+ if (utils.is.htmlElement(player.elements.buttons.playLarge)) {
player.elements.buttons.playLarge.setAttribute('aria-label', label);
}
}
// Set iframe title
// https://github.com/Selz/plyr/issues/124
- if (is.htmlElement(iframe)) {
- var title = is.string(config.title) && !is.empty(config.title) ? config.title : 'video';
+ if (utils.is.htmlElement(iframe)) {
+ var title = utils.is.string(config.title) && !utils.is.empty(config.title) ? config.title : 'video';
iframe.setAttribute('title', config.i18n.frameTitle.replace('{title}', title));
}
}
@@ -2375,7 +2509,7 @@
player.elements.media.setAttribute('id', id);
// Setup API
- if (is.object(window.YT)) {
+ if (utils.is.object(window.YT)) {
youTubeReady(mediaId);
} else {
// Load the API
@@ -2401,12 +2535,12 @@
player.elements.media.setAttribute('id', id);
// Load the API if not already
- if (!is.object(window.Vimeo)) {
+ if (!utils.is.object(window.Vimeo)) {
utils.injectScript(config.urls.vimeo.api);
// Wait for fragaloop load
var vimeoTimer = window.setInterval(function() {
- if (is.object(window.Vimeo)) {
+ if (utils.is.object(window.Vimeo)) {
window.clearInterval(vimeoTimer);
vimeoReady(mediaId);
}
@@ -2714,7 +2848,7 @@
player.embed.on('loaded', function() {
// Fix keyboard focus issues
// https://github.com/Selz/plyr/issues/317
- if (is.htmlElement(player.embed.element) && player.supported.full) {
+ if (utils.is.htmlElement(player.embed.element) && player.supported.full) {
player.embed.element.setAttribute('tabindex', -1);
}
});
@@ -2848,7 +2982,7 @@
// Toggle playback
function togglePlay(toggle) {
// True toggle
- if (!is.boolean(toggle)) {
+ if (!utils.is.boolean(toggle)) {
toggle = player.elements.media.paused;
}
@@ -2912,11 +3046,11 @@
}
// Check if can loop
- config.loop.active = is.number(config.loop.start) && is.number(config.loop.end);
+ config.loop.active = utils.is.number(config.loop.start) && utils.is.number(config.loop.end);
var start = updateTimeDisplay(config.loop.start, getElement('[data-plyr-loop="start"]'));
var end = null;
- if (is.number(config.loop.end)) {
+ if (utils.is.number(config.loop.end)) {
// Find the <span> inside button
end = updateTimeDisplay(config.loop.end, document.querySelector('[data-loop__value="loopout"]'));
} else {
@@ -2943,9 +3077,9 @@
// Set playback speed
function setSpeed(speed) {
// Load speed from storage or default value
- if (is.event(speed)) {
+ if (utils.is.event(speed)) {
speed = parseFloat(speed.target.value);
- } else if (!is.number(speed)) {
+ } else if (!utils.is.number(speed)) {
speed = parseFloat(player.storage.speed || config.speed.selected);
}
@@ -2957,7 +3091,7 @@
speed = 2.0;
}
- if (!is.array(config.speed.options)) {
+ if (!utils.is.array(config.speed.options)) {
warn('Invalid speeds format');
return;
}
@@ -2983,7 +3117,7 @@
// Rewind
function rewind(seekTime) {
// Use default if needed
- if (!is.number(seekTime)) {
+ if (!utils.is.number(seekTime)) {
seekTime = config.seekTime;
}
seek(player.elements.media.currentTime - seekTime);
@@ -2992,7 +3126,7 @@
// Fast forward
function forward(seekTime) {
// Use default if needed
- if (!is.number(seekTime)) {
+ if (!utils.is.number(seekTime)) {
seekTime = config.seekTime;
}
seek(player.elements.media.currentTime + seekTime);
@@ -3005,9 +3139,9 @@
var paused = player.elements.media.paused;
var duration = getDuration();
- if (is.number(input)) {
+ if (utils.is.number(input)) {
targetTime = input;
- } else if (is.event(input) && utils.inArray(['input', 'change'], input.type)) {
+ } else if (utils.is.event(input) && utils.inArray(['input', 'change'], input.type)) {
// It's the seek slider
// Seek to the selected time
targetTime = ((input.target.value / input.target.max) * duration);
@@ -3166,7 +3300,7 @@
var show = (toggle.getAttribute('aria-expanded') === 'false');
// Nothing to show, bail
- if (!is.htmlElement(target)) {
+ if (!utils.is.htmlElement(target)) {
return;
}
@@ -3221,7 +3355,7 @@
// Mute
function toggleMute(muted) {
// If the method is called without parameter, toggle based on current value
- if (!is.boolean(muted)) {
+ if (!utils.is.boolean(muted)) {
muted = !player.elements.media.muted;
}
@@ -3261,12 +3395,12 @@
var min = 0;
// If volume is event, get from input
- if (is.event(volume)) {
+ if (utils.is.event(volume)) {
volume = volume.target.value;
}
// Load volume from storage if no value specified
- if (is.undefined(volume)) {
+ if (utils.is.undefined(volume)) {
volume = player.storage.volume;
}
@@ -3321,7 +3455,7 @@
function increaseVolume(step) {
var volume = player.elements.media.muted ? 0 : (player.elements.media.volume * 10);
- if (!is.number(step)) {
+ if (!utils.is.number(step)) {
step = 1;
}
@@ -3332,7 +3466,7 @@
function decreaseVolume(step) {
var volume = player.elements.media.muted ? 0 : (player.elements.media.volume * 10);
- if (!is.number(step)) {
+ if (!utils.is.number(step)) {
step = 1;
}
@@ -3423,7 +3557,7 @@
if (buffered && buffered.length) {
// HTML5
return utils.getPercentage(buffered.end(0), duration);
- } else if (is.number(buffered)) {
+ } else if (utils.is.number(buffered)) {
// YouTube returns between 0 and 1
return (buffered * 100);
}
@@ -3435,7 +3569,7 @@
}
}
- if (is.number(config.loop.start) && is.number(config.loop.end) && player.elements.media.currentTime >= config.loop.end) {
+ if (utils.is.number(config.loop.start) && utils.is.number(config.loop.end) && player.elements.media.currentTime >= config.loop.end) {
seek(config.loop.start);
}
@@ -3449,12 +3583,12 @@
}
// Default to 0
- if (is.undefined(value)) {
+ if (utils.is.undefined(value)) {
value = 0;
}
// Default to buffer or bail
- if (is.undefined(progress)) {
- if (is.htmlElement(player.elements.display.buffer)) {
+ if (utils.is.undefined(progress)) {
+ if (utils.is.htmlElement(player.elements.display.buffer)) {
progress = player.elements.display.buffer;
} else {
return;
@@ -3462,12 +3596,12 @@
}
// Update value and label
- if (is.htmlElement(progress)) {
+ if (utils.is.htmlElement(progress)) {
progress.value = value;
// Update text label inside
var label = progress.getElementsByTagName('span')[0];
- if (is.htmlElement(label)) {
+ if (utils.is.htmlElement(label)) {
label.childNodes[0].nodeValue = value;
}
}
@@ -3546,7 +3680,7 @@
// Update seek range and progress
function updateSeekDisplay(time) {
// Default to 0
- if (!is.number(time)) {
+ if (!utils.is.number(time)) {
time = 0;
}
@@ -3569,7 +3703,7 @@
var duration = getDuration();
// Bail if setting not true
- if (!config.tooltips.seek || !is.htmlElement(player.elements.inputs.seek) || !is.htmlElement(player.elements.display.seekTooltip) || duration === 0) {
+ if (!config.tooltips.seek || !utils.is.htmlElement(player.elements.inputs.seek) || !utils.is.htmlElement(player.elements.display.seekTooltip) || duration === 0) {
return;
}
@@ -3579,7 +3713,7 @@
var visible = config.classes.tooltip + '--visible';
// Determine percentage, if already visible
- if (is.event(event)) {
+ if (utils.is.event(event)) {
percent = ((100 / clientRect.width) * (event.pageX - clientRect.left));
} else {
if (utils.hasClass(player.elements.display.seekTooltip, visible)) {
@@ -3604,7 +3738,7 @@
// Show/hide the tooltip
// If the event is a moues in/out and percentage is inside bounds
- if (is.event(event) && utils.inArray(['mouseenter', 'mouseleave'], event.type)) {
+ if (utils.is.event(event) && utils.inArray(['mouseenter', 'mouseleave'], event.type)) {
utils.toggleClass(player.elements.display.seekTooltip, visible, (event.type === 'mouseenter'));
}
}
@@ -3622,7 +3756,7 @@
var loading = utils.hasClass(player.elements.container, config.classes.loading);
// Default to false if no boolean
- if (!is.boolean(toggle)) {
+ if (!utils.is.boolean(toggle)) {
if (toggle && toggle.type) {
// Is the enter fullscreen event
isEnterFullscreen = (toggle.type === 'enterfullscreen');
@@ -3679,7 +3813,7 @@
// Add common function to retrieve media source
function source(source) {
// If not null or undefined, parse it
- if (!is.undefined(source)) {
+ if (!utils.is.undefined(source)) {
updateSource(source);
return;
}
@@ -3714,7 +3848,7 @@
// Update source
// Sources are not checked for support so be careful
function updateSource(source) {
- if (!is.object(source) || !('sources' in source) || !source.sources.length) {
+ if (!utils.is.object(source) || !('sources' in source) || !source.sources.length) {
warn('Invalid source format');
return;
}
@@ -3768,7 +3902,7 @@
}
// Check for support
- player.supported = getSupport(player.type, config.inline);
+ player.supported = utils.checkSupport(player.type, config.inline);
// Create new markup
switch (player.type) {
@@ -3792,7 +3926,7 @@
utils.prependChild(player.elements.container, player.elements.media);
// Autoplay the new source?
- if (is.boolean(source.autoplay)) {
+ if (utils.is.boolean(source.autoplay)) {
config.autoplay = source.autoplay;
}
@@ -3883,7 +4017,7 @@
var hadTabFocus = utils.hasClass(trigger, config.classes.tabFocus);
setTimeout(function() {
- if (is.htmlElement(target)) {
+ if (utils.is.htmlElement(target)) {
target.focus();
}
@@ -3919,13 +4053,11 @@
var code = getKeyCode(event);
var focused = utils.getFocusElement();
var allowed = [48, 49, 50, 51, 52, 53, 54, 56, 57, 75, 77, 70, 67, 73, 76, 79];
- var count = get().length;
- // Only handle global key press if there's only one player
- // and the key is in the allowed keys
+ // Only handle global key press if key is in the allowed keys
// and if the focused element is not editable (e.g. text input)
// and any that accept key input http://webaim.org/techniques/keyboard/
- if (count === 1 && utils.inArray(allowed, code) && (!is.htmlElement(focused) || !utils.matches(focused, config.selectors.editable))) {
+ if (utils.inArray(allowed, code) && (!utils.is.htmlElement(focused) || !utils.matches(focused, config.selectors.editable))) {
handleKey(event);
}
}, false);
@@ -3942,7 +4074,7 @@
// If the event is bubbled from the media element
// Firefox doesn't get the keycode for whatever reason
- if (!is.number(code)) {
+ if (!utils.is.number(code)) {
return;
}
@@ -3952,7 +4084,7 @@
var duration = player.elements.media.duration;
// Bail if we have no duration set
- if (!is.number(duration)) {
+ if (!utils.is.number(duration)) {
return;
}
@@ -3970,7 +4102,7 @@
if (utils.inArray(checkFocus, code)) {
var focused = utils.getFocusElement();
- if (is.htmlElement(focused) && utils.getFocusElement().type === "radio") {
+ if (utils.is.htmlElement(focused) && utils.getFocusElement().type === "radio") {
return;
}
}
@@ -4093,10 +4225,10 @@
// Trigger custom and default handlers
var handlerProxy = function(event, customHandler, defaultHandler) {
- if (is.function(customHandler)) {
+ if (utils.is.function(customHandler)) {
customHandler.call(this, event);
}
- if (is.function(defaultHandler)) {
+ if (utils.is.function(defaultHandler)) {
defaultHandler.call(this, event);
}
}
@@ -4376,11 +4508,6 @@
// Event listeners are removed when elements are removed
// http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory
function destroy(callback, restore) {
- // Bail if the element is not initialized
- if (!player.init) {
- return null;
- }
-
// Type specific stuff
switch (player.type) {
case 'youtube':
@@ -4419,13 +4546,13 @@
function cleanUp() {
// Default to restore original element
- if (!is.boolean(restore)) {
+ if (!utils.is.boolean(restore)) {
restore = true;
}
// Callback
- if (is.function(callback)) {
- callback.call(original);
+ if (utils.is.function(callback)) {
+ callback.call(player.original);
}
// Bail if we don't need to restore the original element
@@ -4433,94 +4560,15 @@
return;
}
- // Remove init flag
- player.init = false;
-
// Replace the container with the original element provided
- player.elements.container.parentNode.replaceChild(original, player.elements.container);
+ player.elements.container.parentNode.replaceChild(player.original, player.elements.container);
- // unbind escape key
+ // Reset overflow (incase destroyed while fullscreen)
document.body.style.overflow = '';
// Event
- trigger(original, 'destroyed', true);
- }
- }
-
- // Setup a player
- function init() {
- // Bail if the element is initialized
- if (player.init) {
- return null;
- }
-
- // Sniff out the browser
- player.browser = utils.getBrowser();
-
- // Bail if nothing to setup
- if (!is.htmlElement(player.elements.media)) {
- return;
- }
-
- // Load saved settings from localStorage
- setupStorage();
-
- // Set media type based on tag or data attribute
- // Supported: video, audio, vimeo, youtube
- var tagName = media.tagName.toLowerCase();
- if (tagName === 'div') {
- player.type = media.getAttribute('data-type');
- player.embedId = media.getAttribute('data-video-id');
-
- // Clean up
- media.removeAttribute('data-type');
- media.removeAttribute('data-video-id');
- } else {
- player.type = tagName;
- config.crossorigin = media.getAttribute('crossorigin') !== null;
- config.autoplay = config.autoplay || (media.getAttribute('autoplay') !== null);
- config.inline = media.getAttribute('playsinline') !== null;
- config.loop.active = config.loop || (media.getAttribute('loop') !== null);
- }
-
- // Check for support
- player.supported = getSupport(player.type, config.inline);
-
- // If no native support, bail
- if (!player.supported.basic) {
- return;
- }
-
- // Wrap media
- player.elements.container = utils.wrap(media, utils.createElement('div'));
-
- // Allow focus to be captured
- player.elements.container.setAttribute('tabindex', 0);
-
- // Add style hook
- toggleStyleHook();
-
- // Debug info
- log('' + player.browser.name + ' ' + player.browser.version);
-
- // Setup media
- setupMedia();
-
- // Setup interface
- // If embed but not fully supported, setupInterface (to avoid flash of controls) and call ready now
- if (utils.inArray(types.html5, player.type) || (utils.inArray(types.embed, player.type) && !player.supported.full)) {
- // Setup UI
- setupInterface();
-
- // Call ready
- ready();
-
- // Set title on button and frame
- setTitle();
+ trigger(player.original, 'destroyed', true);
}
-
- // Successful setup
- player.init = true;
}
// Setup the UI
@@ -4543,7 +4591,7 @@
}
// Inject custom controls if not present
- if (!is.htmlElement(player.elements.controls)) {
+ if (!utils.is.htmlElement(player.elements.controls)) {
// Inject custom controls
injectControls();
@@ -4552,7 +4600,7 @@
}
// If there's no controls, bail
- if (!is.htmlElement(player.elements.controls)) {
+ if (!utils.is.htmlElement(player.elements.controls)) {
return;
}
@@ -4585,9 +4633,148 @@
checkPlaying();
}
+ // Everything done
+ function ready() {
+ // Set class hook on media element
+ // utils.toggleClass(player.elements.media, defaults.classes.setup, true);
+
+ // Set container class for ready
+ // utils.toggleClass(player.elements.container, config.classes.ready, true);
+
+ // Store a refernce to instance
+ // player.elements.media.plyr = api;
+
+ // Ready event at end of execution stack
+ trigger(player.elements.container, 'ready', true);
+
+ // Autoplay
+ if (config.autoplay) {
+ play();
+ }
+ }
+
+ // Setup a player
+ function setup(target) {
+ // We need an element to setup
+ if (!utils.is.htmlElement(target)) {
+ error('Setup failed. No suitable element passed.');
+ return false;
+ }
+
+ // Bail if not enabled
+ if (!config.enabled) {
+ return false;
+ }
+
+ // Bail if disabled or no basic support
+ // You may want to disable certain UAs etc
+ if (!utils.checkSupport().basic) {
+ return false;
+ }
+
+ // Bail if the element is initialized
+ if (target.plyr) {
+ return false;
+ }
+
+ // Set media type based on tag or data attribute
+ // Supported: video, audio, vimeo, youtube
+ var type = target.tagName.toLowerCase();
+
+ // Different setup based on type
+ switch (type) {
+ case 'div':
+ player.type = target.getAttribute('data-type');
+ player.embedId = target.getAttribute('data-video-id');
+
+ if (utils.is.empty(player.type) || utils.is.empty(player.embedId)) {
+ return false;
+ }
+
+ // Clean up
+ target.removeAttribute('data-type');
+ target.removeAttribute('data-video-id');
+ break;
+
+ case 'iframe':
+ // Do something with the iframe
+ break;
+
+ case 'video':
+ case 'audio':
+ player.type = type;
+ config.crossorigin = target.getAttribute('crossorigin') !== null;
+ config.autoplay = config.autoplay || (target.getAttribute('autoplay') !== null);
+ config.inline = target.getAttribute('playsinline') !== null;
+ config.loop.active = config.loop || (target.getAttribute('loop') !== null);
+ break;
+
+ default:
+ return false;
+ }
+
+ // Sniff out the browser
+ player.browser = utils.getBrowser();
+
+ // Load saved settings from localStorage
+ setupStorage();
+
+ // Check for support
+ player.supported = utils.checkSupport(player.type, config.inline);
+
+ // If no native support, bail
+ if (!player.supported.basic) {
+ return false;
+ }
+
+ // Wrap media
+ player.elements.container = utils.wrap(target, utils.createElement('div'));
+
+ // Cache original element state for .destroy()
+ player.original = target.cloneNode(true);
+
+ // Allow focus to be captured
+ player.elements.container.setAttribute('tabindex', 0);
+
+ // Add style hook
+ toggleStyleHook();
+
+ // Debug info
+ log(player.browser.name + ' ' + player.browser.version);
+
+ // Setup media
+ setupMedia();
+
+ // Listen for events if debugging
+ if (config.debug) {
+ var events = config.events.concat(['setup', 'statechange', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled']);
+
+ utils.on(player.elements.container, events.join(' '), function(event) {
+ log(['event:', event.type].join(' ').trim());
+ });
+ }
+
+ // Setup interface
+ // If embed but not fully supported, setupInterface (to avoid flash of controls) and call ready now
+ if (utils.inArray(types.html5, player.type) || (utils.inArray(types.embed, player.type) && !player.supported.full)) {
+ // Setup UI
+ setupInterface();
+
+ // Call ready
+ ready();
+
+ // Set title on button and frame
+ setTitle();
+ }
+
+ // Successful setup
+ return true;
+ }
+
+ // Expose prototypes
api = {
getOriginal: function() {
- return original;
+ return player.original;
},
getContainer: function() {
return player.elements.container
@@ -4648,299 +4835,21 @@
toggleFullscreen: toggleFullscreen,
toggleControls: toggleControls,
setLanguage: setLanguage,
- isFullscreen: function() {
- return player.fullscreen.active || false;
- },
+ isFullscreen: player.fullscreen.active,
support: function(mimeType) {
return support.mime(player, mimeType);
},
destroy: destroy
};
- // Everything done
- function ready() {
- // Set class hook on media element
- utils.toggleClass(player.elements.media, defaults.classes.setup, true);
-
- // Set container class for ready
- utils.toggleClass(player.elements.container, config.classes.ready, true);
-
- // Store a refernce to instance
- player.elements.media.plyr = api;
-
- // Ready event at end of execution stack
- window.setTimeout(function() {
- trigger(player.elements.media, 'ready');
- }, 0);
-
- // Autoplay
- if (config.autoplay) {
- play();
- }
- }
-
// Initialize instance
- init();
-
- // If init failed, return null
- if (!player.init) {
+ if (!setup(player.elements.media)) {
return null;
}
+ // Expose API
return api;
}
- // Load a sprite
- function loadSprite(url, id) {
- var x = new XMLHttpRequest();
-
- // If the id is set and sprite exists, bail
- if (is.string(id) && is.htmlElement(document.querySelector('#' + id))) {
- return;
- }
-
- // Create placeholder (to prevent loading twice)
- var container = utils.createElement('div');
- container.setAttribute('hidden', '');
- if (is.string(id)) {
- container.setAttribute('id', id);
- }
- document.body.insertBefore(container, document.body.childNodes[0]);
-
- // Check for CORS support
- if ('withCredentials' in x) {
- x.open('GET', url, true);
- } else {
- return;
- }
-
- // Inject hidden div with sprite on load
- x.onload = function() {
- container.innerHTML = x.responseText;
- }
-
- x.send();
- }
-
- // Check for support
- // Basic functionality vs full UI
- function getSupport(type, inline) {
- var basic = false;
- var full = false;
- var browser = utils.getBrowser();
- var playsInline = (browser.isIPhone && inline && support.inline);
-
- switch (type) {
- case 'video':
- basic = support.video;
- full = basic && !browser.isOldIE && (!browser.isIPhone || playsInline);
- break;
-
- case 'audio':
- basic = support.audio;
- full = basic && !browser.isOldIE;
- break;
-
- case 'youtube':
- basic = support.video;
- full = basic && !browser.isOldIE && (!browser.isIPhone || playsInline);
- break;
-
- case 'vimeo':
- case 'soundcloud':
- basic = true;
- full = (!browser.isOldIE && !browser.isIos);
- break;
-
- default:
- basic = (support.audio && support.video);
- full = (basic && !browser.isOldIE);
- }
-
- return {
- basic: basic,
- full: full
- };
- }
-
- // Setup function
- function setup(targets, options) {
- // Get the players
- var players = [];
- var instances = [];
- var selector = [defaults.selectors.html5, defaults.selectors.embed].join(',');
-
- // Select the elements
- if (is.string(targets)) {
- // String selector passed
- targets = document.querySelectorAll(targets);
- } else if (is.htmlElement(targets)) {
- // Single HTMLElement passed
- targets = [targets];
- } else if (!is.nodeList(targets) && !is.array(targets) && !is.string(targets)) {
- // No selector passed, possibly options as first argument
- // If options are the first argument
- if (is.undefined(options) && is.object(targets)) {
- options = targets;
- }
-
- // Use default selector
- targets = document.querySelectorAll(selector);
- }
-
- // Convert NodeList to array
- if (is.nodeList(targets)) {
- targets = Array.prototype.slice.call(targets);
- }
-
- // Bail if disabled or no basic support
- // You may want to disable certain UAs etc
- if (!getSupport().basic || !targets.length) {
- return false;
- }
-
- // Add to container list
- function add(target, media) {
- if (!utils.hasClass(media, defaults.classes.hook)) {
- players.push({
- // Always wrap in a <div> for styling
- // container: utils.wrap(media, document.createElement('div')),
- // Could be a container or the media itself
- target: target,
- // This should be the <video>, <audio> or <div> (YouTube/Vimeo)
- media: media
- });
- }
- }
-
- // Check if the targets have multiple media elements
- for (var i = 0; i < targets.length; i++) {
- var target = targets[i];
-
- // Get children
- var children = target.querySelectorAll(selector);
-
- // If there's more than one media element child, wrap them
- if (children.length) {
- for (var x = 0; x < children.length; x++) {
- add(target, children[x]);
- }
- } else if (utils.matches(target, selector)) {
- // Target is media element
- add(target, target);
- }
- }
-
- // Create a player instance for each element
- players.forEach(function(player) {
- var element = player.target;
- var media = player.media;
- var match = false;
-
- // The target element can also be the media element
- if (media === element) {
- match = true;
- }
-
- // Setup a player instance and add to the element
- // Create instance-specific config
- var data = {};
-
- // Try parsing data attribute config
- try {
- data = JSON.parse(element.getAttribute('data-plyr'));
- } catch (e) {}
-
- var config = utils.extend({}, defaults, options, data);
-
- // Bail if not enabled
- if (!config.enabled) {
- return null;
- }
-
- // Create new instance
- var instance = new Plyr(media, config);
-
- // Go to next if setup failed
- if (!is.object(instance)) {
- return;
- }
-
- // Listen for events if debugging
- if (config.debug) {
- var events = config.events.concat(['setup', 'statechange', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled']);
-
- utils.on(instance.getContainer(), events.join(' '), function(event) {
- window.console.log([config.logPrefix, 'event:', event.type].join(' ').trim());
- });
- }
-
- // Callback
- utils.event(instance.getContainer(), 'setup', true, {
- plyr: instance
- });
-
- // Add to return array even if it's already setup
- instances.push(instance);
- });
-
- return instances;
- }
-
- // Get all instances within a provided container
- function get(container) {
- if (is.string(container)) {
- // Get selector if string passed
- container = document.querySelector(container);
- } else if (is.undefined(container)) {
- // Use body by default to get all on page
- container = document.body;
- }
-
- // If we have a HTML element
- if (is.htmlElement(container)) {
- var elements = container.querySelectorAll('.' + defaults.classes.setup),
- instances = [];
-
- Array.prototype.slice.call(elements).forEach(function(element) {
- if (is.object(element.plyr)) {
- instances.push(element.plyr);
- }
- });
-
- return instances;
- }
-
- return [];
- }
-
- return {
- setup: setup,
- supported: getSupport,
- loadSprite: loadSprite,
- get: get
- };
+ return Player;
}));
-
-// Custom event polyfill
-// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
-(function() {
- if (typeof window.CustomEvent === 'function') {
- return;
- }
-
- function CustomEvent(event, params) {
- params = params || {
- bubbles: false,
- cancelable: false,
- detail: undefined
- };
- var evt = document.createEvent('CustomEvent');
- evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
- return evt;
- }
-
- CustomEvent.prototype = window.Event.prototype;
-
- window.CustomEvent = CustomEvent;
-})();