aboutsummaryrefslogtreecommitdiffstats
path: root/dist/plyr.polyfilled.js
diff options
context:
space:
mode:
Diffstat (limited to 'dist/plyr.polyfilled.js')
-rw-r--r--dist/plyr.polyfilled.js555
1 files changed, 314 insertions, 241 deletions
diff --git a/dist/plyr.polyfilled.js b/dist/plyr.polyfilled.js
index b919a304..068e7bab 100644
--- a/dist/plyr.polyfilled.js
+++ b/dist/plyr.polyfilled.js
@@ -5876,61 +5876,63 @@ var utils = {
// Check variable types
is: {
object: function object(input) {
- return this.getConstructor(input) === Object;
+ return utils.getConstructor(input) === Object;
},
number: function number(input) {
- return this.getConstructor(input) === Number && !Number.isNaN(input);
+ return utils.getConstructor(input) === Number && !Number.isNaN(input);
},
string: function string(input) {
- return this.getConstructor(input) === String;
+ return utils.getConstructor(input) === String;
},
boolean: function boolean(input) {
- return this.getConstructor(input) === Boolean;
+ return utils.getConstructor(input) === Boolean;
},
function: function _function(input) {
- return this.getConstructor(input) === Function;
+ return utils.getConstructor(input) === Function;
},
array: function array(input) {
- return !this.nullOrUndefined(input) && Array.isArray(input);
+ return !utils.is.nullOrUndefined(input) && Array.isArray(input);
},
weakMap: function weakMap(input) {
- return this.instanceof(input, WeakMap);
+ return utils.is.instanceof(input, WeakMap);
},
nodeList: function nodeList(input) {
- return this.instanceof(input, NodeList);
+ return utils.is.instanceof(input, NodeList);
},
element: function element(input) {
- return this.instanceof(input, Element);
+ return utils.is.instanceof(input, Element);
},
textNode: function textNode(input) {
- return this.getConstructor(input) === Text;
+ return utils.getConstructor(input) === Text;
},
event: function event(input) {
- return this.instanceof(input, Event);
+ return utils.is.instanceof(input, Event);
},
cue: function cue(input) {
- return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue);
+ return utils.is.instanceof(input, window.TextTrackCue) || utils.is.instanceof(input, window.VTTCue);
},
track: function track(input) {
- return this.instanceof(input, TextTrack) || !this.nullOrUndefined(input) && this.string(input.kind);
+ return utils.is.instanceof(input, TextTrack) || !utils.is.nullOrUndefined(input) && utils.is.string(input.kind);
},
url: function url(input) {
- return !this.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input);
+ return !utils.is.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input);
},
nullOrUndefined: function nullOrUndefined(input) {
return input === null || typeof input === 'undefined';
},
empty: function empty(input) {
- return this.nullOrUndefined(input) || (this.string(input) || this.array(input) || this.nodeList(input)) && !input.length || this.object(input) && !Object.keys(input).length;
+ return utils.is.nullOrUndefined(input) || (utils.is.string(input) || utils.is.array(input) || utils.is.nodeList(input)) && !input.length || utils.is.object(input) && !Object.keys(input).length;
},
instanceof: function _instanceof$$1(input, constructor) {
return Boolean(input && constructor && input instanceof constructor);
- },
- getConstructor: function getConstructor(input) {
- return !this.nullOrUndefined(input) ? input.constructor : null;
}
},
+ getConstructor: function getConstructor(input) {
+ return !utils.is.nullOrUndefined(input) ? input.constructor : null;
+ },
+
+
// Unfortunately, due to mixed support, UA sniffing is required
getBrowser: function getBrowser() {
return {
@@ -6550,7 +6552,7 @@ var utils = {
// Bail if the value isn't a number
if (!utils.is.number(time)) {
- return this.formatTime(null, displayHours, inverted);
+ return utils.formatTime(null, displayHours, inverted);
}
// Format time component to add leading zero
@@ -6559,9 +6561,9 @@ var utils = {
};
// Breakdown to hours, mins, secs
- var hours = this.getHours(time);
- var mins = this.getMinutes(time);
- var secs = this.getSeconds(time);
+ var hours = utils.getHours(time);
+ var mins = utils.getMinutes(time);
+ var secs = utils.getSeconds(time);
// Do we need to display hours?
if (displayHours || hours > 0) {
@@ -6757,12 +6759,12 @@ var utils = {
// Parse URL if needed
if (input.startsWith('http://') || input.startsWith('https://')) {
- var _parseUrl = this.parseUrl(input);
+ var _utils$parseUrl = utils.parseUrl(input);
- search = _parseUrl.search;
+ search = _utils$parseUrl.search;
}
- if (this.is.empty(search)) {
+ if (utils.is.empty(search)) {
return null;
}
@@ -6801,6 +6803,14 @@ var utils = {
},
+ // Like outerHTML, but also works for DocumentFragment
+ getHTML: function getHTML(element) {
+ var wrapper = document.createElement('div');
+ wrapper.appendChild(element);
+ return wrapper.innerHTML;
+ },
+
+
// Get aspect ratio for dimensions
getAspectRatio: function getAspectRatio(width, height) {
var getRatio = function getRatio(w, h) {
@@ -7542,9 +7552,15 @@ var controls = {
// Create a settings menu item
- createMenuItem: function createMenuItem(value, list, type, title) {
- var badge = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
- var checked = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
+ createMenuItem: function createMenuItem(_ref) {
+ var value = _ref.value,
+ list = _ref.list,
+ type = _ref.type,
+ title = _ref.title,
+ _ref$badge = _ref.badge,
+ badge = _ref$badge === undefined ? null : _ref$badge,
+ _ref$checked = _ref.checked,
+ checked = _ref$checked === undefined ? false : _ref$checked;
var item = utils.createElement('li');
@@ -7860,8 +7876,13 @@ var controls = {
var sorting = _this3.config.quality.options;
return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;
}).forEach(function (quality) {
- var label = controls.getLabel.call(_this3, 'quality', quality);
- controls.createMenuItem.call(_this3, quality, list, type, label, getBadge(quality));
+ controls.createMenuItem.call(_this3, {
+ value: quality,
+ list: list,
+ type: type,
+ title: controls.getLabel.call(_this3, 'quality', quality),
+ badge: getBadge(quality)
+ });
});
controls.updateSetting.call(this, type, list);
@@ -7904,18 +7925,7 @@ var controls = {
switch (setting) {
case 'captions':
- if (this.captions.active) {
- if (this.options.captions.length > 2 || !this.options.captions.some(function (lang) {
- return lang === 'enabled';
- })) {
- value = this.captions.language;
- } else {
- value = 'enabled';
- }
- } else {
- value = '';
- }
-
+ value = this.currentTrack;
break;
default:
@@ -8010,10 +8020,10 @@ var controls = {
// TODO: Captions or language? Currently it's mixed
var type = 'captions';
var list = this.elements.settings.panes.captions.querySelector('ul');
+ var tracks = captions.getTracks.call(this);
// Toggle the pane and tab
- var toggle = captions.getTracks.call(this).length;
- controls.toggleTab.call(this, type, toggle);
+ controls.toggleTab.call(this, type, tracks.length);
// Empty the menu
utils.emptyElement(list);
@@ -8022,28 +8032,33 @@ var controls = {
controls.checkMenu.call(this);
// If there's no captions, bail
- if (!toggle) {
+ if (!tracks.length) {
return;
}
- // Re-map the tracks into just the data we need
- var tracks = captions.getTracks.call(this).map(function (track) {
+ // Generate options data
+ var options = tracks.map(function (track, value) {
return {
- language: !utils.is.empty(track.language) ? track.language : 'enabled',
- label: captions.getLabel.call(_this4, track)
+ value: value,
+ checked: _this4.captions.active && _this4.currentTrack === value,
+ title: captions.getLabel.call(_this4, track),
+ badge: track.language && controls.createBadge.call(_this4, track.language.toUpperCase()),
+ list: list,
+ type: 'language'
};
});
// Add the "Disabled" option to turn off captions
- tracks.unshift({
- language: '',
- label: i18n.get('disabled', this.config)
+ options.unshift({
+ value: -1,
+ checked: !this.captions.active,
+ title: i18n.get('disabled', this.config),
+ list: list,
+ type: 'language'
});
// Generate options
- tracks.forEach(function (track) {
- controls.createMenuItem.call(_this4, track.language, list, 'language', track.label, track.language !== 'enabled' ? controls.createBadge.call(_this4, track.language.toUpperCase()) : null, track.language.toLowerCase() === _this4.language);
- });
+ options.forEach(controls.createMenuItem.bind(this));
controls.updateSetting.call(this, type, list);
},
@@ -8097,8 +8112,12 @@ var controls = {
// Create items
this.options.speed.forEach(function (speed) {
- var label = controls.getLabel.call(_this5, 'speed', speed);
- controls.createMenuItem.call(_this5, speed, list, type, label);
+ controls.createMenuItem.call(_this5, {
+ value: speed,
+ list: list,
+ type: type,
+ title: controls.getLabel.call(_this5, 'speed', speed)
+ });
});
controls.updateSetting.call(this, type, list);
@@ -8572,10 +8591,10 @@ var controls = {
var replace = function replace(input) {
var result = input;
- Object.entries(props).forEach(function (_ref) {
- var _ref2 = slicedToArray(_ref, 2),
- key = _ref2[0],
- value = _ref2[1];
+ Object.entries(props).forEach(function (_ref2) {
+ var _ref3 = slicedToArray(_ref2, 2),
+ key = _ref3[0],
+ value = _ref3[1];
result = utils.replaceAll(result, '{' + key + '}', value);
});
@@ -8692,124 +8711,189 @@ var captions = {
active = this.config.captions.active;
}
- // Set toggled state
- this.toggleCaptions(active);
+ // Get language from storage, fallback to config
+ var language = this.storage.get('language') || this.config.captions.language;
+ if (language === 'auto') {
+ var _split = (navigator.language || navigator.userLanguage).split('-');
+
+ var _split2 = slicedToArray(_split, 1);
+
+ language = _split2[0];
+ }
+ // Set language and show if active
+ captions.setLanguage.call(this, language, active);
// Watch changes to textTracks and update captions menu
- if (this.config.captions.update) {
- utils.on(this.media.textTracks, 'addtrack removetrack', captions.update.bind(this));
+ if (this.isHTML5) {
+ var trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';
+ utils.on(this.media.textTracks, trackEvents, captions.update.bind(this));
}
// Update available languages in list next tick (the event must not be triggered before the listeners)
setTimeout(captions.update.bind(this), 0);
},
update: function update() {
- // Update tracks
- var tracks = captions.getTracks.call(this);
- this.options.captions = tracks.map(function (_ref) {
- var language = _ref.language;
- return language;
- });
+ var _this = this;
- // Set language if it hasn't been set already
- if (!this.language) {
- var language = this.config.captions.language;
+ var tracks = captions.getTracks.call(this, true);
+ // Get the wanted language
+ var _captions = this.captions,
+ language = _captions.language,
+ meta = _captions.meta;
- if (language === 'auto') {
- var _split = (navigator.language || navigator.userLanguage).split('-');
+ // Handle tracks (add event listener and "pseudo"-default)
- var _split2 = slicedToArray(_split, 1);
+ if (this.isHTML5 && this.isVideo) {
+ tracks.filter(function (track) {
+ return !meta.get(track);
+ }).forEach(function (track) {
+ _this.debug.log('Track added', track);
+ // Attempt to store if the original dom element was "default"
+ meta.set(track, {
+ default: track.mode === 'showing'
+ });
- language = _split2[0];
- }
- this.language = this.storage.get('language') || (language || '').toLowerCase();
+ // Turn off native caption rendering to avoid double captions
+ track.mode = 'hidden';
+
+ // Add event listener for cue changes
+ utils.on(track, 'cuechange', function () {
+ return captions.updateCues.call(_this);
+ });
+ });
+ }
+
+ var trackRemoved = !tracks.find(function (track) {
+ return track === _this.captions.currentTrackNode;
+ });
+ var firstMatch = this.language !== language && tracks.find(function (track) {
+ return track.language === language;
+ });
+
+ // Update language if removed or first matching track added
+ if (trackRemoved || firstMatch) {
+ captions.setLanguage.call(this, language, this.config.captions.active);
}
- // Toggle the class hooks
- utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this)));
+ // Enable or disable captions based on track length
+ utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(tracks));
// Update available languages in list
if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) {
controls.setCaptionsMenu.call(this);
}
},
+ set: function set(index) {
+ var setLanguage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
+ var show = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
+ var tracks = captions.getTracks.call(this);
- // Set the captions language
- setLanguage: function setLanguage() {
- var _this = this;
+ // Disable captions if setting to -1
+ if (index === -1) {
+ this.toggleCaptions(false);
+ return;
+ }
- // Setup HTML5 track rendering
- if (this.isHTML5 && this.isVideo) {
- captions.getTracks.call(this).forEach(function (track) {
- // Show track
- utils.on(track, 'cuechange', function (event) {
- return captions.setCue.call(_this, event);
- });
+ if (!utils.is.number(index)) {
+ this.debug.warn('Invalid caption argument', index);
+ return;
+ }
- // Turn off native caption rendering to avoid double captions
- // eslint-disable-next-line
- track.mode = 'hidden';
- });
+ if (!(index in tracks)) {
+ this.debug.warn('Track not found', index);
+ return;
+ }
- // Get current track
- var currentTrack = captions.getCurrentTrack.call(this);
+ if (this.captions.currentTrack !== index) {
+ this.captions.currentTrack = index;
+ var track = captions.getCurrentTrack.call(this);
- // Check if suported kind
- if (utils.is.track(currentTrack)) {
- // If we change the active track while a cue is already displayed we need to update it
- if (Array.from(currentTrack.activeCues || []).length) {
- captions.setCue.call(this, currentTrack);
- }
+ var _ref = track || {},
+ language = _ref.language;
+
+ // Store reference to node for invalidation on remove
+
+
+ this.captions.currentTrackNode = track;
+
+ // Prevent setting language in some cases, since it can violate user's intentions
+ if (setLanguage) {
+ this.captions.language = language;
}
- } else if (this.isVimeo && this.captions.active) {
- this.embed.enableTextTrack(this.language);
+
+ // Handle Vimeo captions
+ if (this.isVimeo) {
+ this.embed.enableTextTrack(language);
+ }
+
+ // Trigger event
+ utils.dispatchEvent.call(this, this.media, 'languagechange');
}
- },
+ if (this.isHTML5 && this.isVideo) {
+ // If we change the active track while a cue is already displayed we need to update it
+ captions.updateCues.call(this);
+ }
- // Get the tracks
- getTracks: function getTracks() {
- // Return empty array at least
- if (utils.is.nullOrUndefined(this.media)) {
- return [];
+ // Show captions
+ if (show) {
+ this.toggleCaptions(true);
}
+ },
+ setLanguage: function setLanguage(language) {
+ var show = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
- // Only get accepted kinds
- return Array.from(this.media.textTracks || []).filter(function (track) {
- return ['captions', 'subtitles'].includes(track.kind);
- });
+ if (!utils.is.string(language)) {
+ this.debug.warn('Invalid language argument', language);
+ return;
+ }
+ // Normalize
+ this.captions.language = language.toLowerCase();
+
+ // Set currentTrack
+ var tracks = captions.getTracks.call(this);
+ var track = captions.getCurrentTrack.call(this, true);
+ captions.set.call(this, tracks.indexOf(track), false, show);
},
- // Get the current track for the current language
- getCurrentTrack: function getCurrentTrack() {
+ // Get current valid caption tracks
+ // If update is false it will also ignore tracks without metadata
+ // This is used to "freeze" the language options when captions.update is false
+ getTracks: function getTracks() {
var _this2 = this;
- var tracks = captions.getTracks.call(this);
+ var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
- if (!tracks.length) {
- return null;
- }
-
- // Get track based on current language
- var track = tracks.find(function (track) {
- return track.language.toLowerCase() === _this2.language;
+ // Handle media or textTracks missing or null
+ var tracks = Array.from((this.media || {}).textTracks || []);
+ // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)
+ // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)
+ return tracks.filter(function (track) {
+ return !_this2.isHTML5 || update || _this2.captions.meta.has(track);
+ }).filter(function (track) {
+ return ['captions', 'subtitles'].includes(track.kind);
});
+ },
- // Get the <track> with default attribute
- if (!track) {
- track = utils.getElement.call(this, 'track[default]');
- }
- // Get the first track
- if (!track) {
- var _tracks = slicedToArray(tracks, 1);
+ // Get the current track for the current language
+ getCurrentTrack: function getCurrentTrack() {
+ var _this3 = this;
- track = _tracks[0];
- }
+ var fromLanguage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
- return track;
+ var tracks = captions.getTracks.call(this);
+ var sortIsDefault = function sortIsDefault(track) {
+ return Number((_this3.captions.meta.get(track) || {}).default);
+ };
+ var sorted = Array.from(tracks).sort(function (a, b) {
+ return sortIsDefault(b) - sortIsDefault(a);
+ });
+ return !fromLanguage && tracks[this.currentTrack] || sorted.find(function (track) {
+ return track.language === _this3.captions.language;
+ }) || sorted[0];
},
@@ -8837,58 +8921,50 @@ var captions = {
},
- // Display active caption if it contains text
- setCue: function setCue(input) {
- // Get the track from the event if needed
- var track = utils.is.event(input) ? input.target : input;
- var activeCues = track.activeCues;
-
- var active = activeCues.length && activeCues[0];
- var currentTrack = captions.getCurrentTrack.call(this);
-
- // Only display current track
- if (track !== currentTrack) {
+ // Update captions using current track's active cues
+ // Also optional array argument in case there isn't any track (ex: vimeo)
+ updateCues: function updateCues(input) {
+ // Requires UI
+ if (!this.supported.ui) {
return;
}
- // Display a cue, if there is one
- if (utils.is.cue(active)) {
- captions.setText.call(this, active.getCueAsHTML());
- } else {
- captions.setText.call(this, null);
+ if (!utils.is.element(this.elements.captions)) {
+ this.debug.warn('No captions element to render to');
+ return;
}
- utils.dispatchEvent.call(this, this.media, 'cuechange');
- },
-
-
- // Set the current caption
- setText: function setText(input) {
- // Requires UI
- if (!this.supported.ui) {
+ // Only accept array or empty input
+ if (!utils.is.nullOrUndefined(input) && !Array.isArray(input)) {
+ this.debug.warn('updateCues: Invalid input', input);
return;
}
- if (utils.is.element(this.elements.captions)) {
- var content = utils.createElement('span');
+ var cues = input;
- // Empty the container
- utils.emptyElement(this.elements.captions);
+ // Get cues from track
+ if (!cues) {
+ var track = captions.getCurrentTrack.call(this);
+ cues = Array.from((track || {}).activeCues || []).map(function (cue) {
+ return cue.getCueAsHTML();
+ }).map(utils.getHTML);
+ }
- // Default to empty
- var caption = !utils.is.nullOrUndefined(input) ? input : '';
+ // Set new caption text
+ var content = cues.map(function (cueText) {
+ return cueText.trim();
+ }).join('\n');
+ var changed = content !== this.elements.captions.innerHTML;
- // Set the span content
- if (utils.is.string(caption)) {
- content.innerText = caption.trim();
- } else {
- content.appendChild(caption);
- }
+ if (changed) {
+ // Empty the container and create a new child element
+ utils.emptyElement(this.elements.captions);
+ var caption = utils.createElement('span', utils.getAttributesFromSelector(this.config.selectors.caption));
+ caption.innerHTML = content;
+ this.elements.captions.appendChild(caption);
- // Set new caption text
- this.elements.captions.appendChild(content);
- } else {
- this.debug.warn('No captions element to render to');
+ // Trigger event
+ utils.dispatchEvent.call(this, this.media, 'cuechange');
}
}
};
@@ -9192,6 +9268,7 @@ var defaults$1 = {
},
progress: '.plyr__progress',
captions: '.plyr__captions',
+ caption: '.plyr__caption',
menu: {
quality: '.js-plyr__menu__list--quality'
}
@@ -10170,9 +10247,11 @@ var Listeners = function () {
// Proxy events to container
// Bubble up key events for Edge
utils.on(this.player.media, this.player.config.events.concat(['keyup', 'keydown']).join(' '), function (event) {
- var detail = {};
+ var _event$detail = event.detail,
+ detail = _event$detail === undefined ? {} : _event$detail;
// Get error details from media
+
if (event.type === 'error') {
detail = _this3.player.media.error;
}
@@ -10271,7 +10350,7 @@ var Listeners = function () {
// Settings menu items - use event delegation as items are added/removed
if (utils.matches(event.target, _this4.player.config.selectors.inputs.language)) {
proxy(event, function () {
- _this4.player.language = event.target.value;
+ _this4.player.currentTrack = Number(event.target.value);
showHomeTab();
}, 'language');
} else if (utils.matches(event.target, _this4.player.config.selectors.inputs.quality)) {
@@ -10466,6 +10545,9 @@ var Listeners = function () {
// Set playback state and trigger change (only on actual change)
function assurePlaybackState(play) {
+ if (play && !this.embed.hasPlayed) {
+ this.embed.hasPlayed = true;
+ }
if (this.media.paused === play) {
this.media.paused = !play;
utils.dispatchEvent.call(this, this.media, play ? 'play' : 'pause');
@@ -10618,24 +10700,25 @@ var vimeo = {
paused = player.paused,
volume = player.volume;
- // Set seeking state and trigger event
+ var restorePause = paused && !embed.hasPlayed;
+ // Set seeking state and trigger event
media.seeking = true;
utils.dispatchEvent.call(player, media, 'seeking');
// If paused, mute until seek is complete
- Promise.resolve(paused && embed.setVolume(0))
+ Promise.resolve(restorePause && embed.setVolume(0))
// Seek
.then(function () {
return embed.setCurrentTime(time);
})
// Restore paused
.then(function () {
- return paused && embed.pause();
+ return restorePause && embed.pause();
})
// Restore volume
.then(function () {
- return paused && embed.setVolume(volume);
+ return restorePause && embed.setVolume(volume);
}).catch(function () {
// Do nothing
});
@@ -10765,17 +10848,25 @@ var vimeo = {
captions.setup.call(player);
});
- player.embed.on('cuechange', function (data) {
- var cue = null;
-
- if (data.cues.length) {
- cue = utils.stripHTML(data.cues[0].text);
- }
+ player.embed.on('cuechange', function (_ref) {
+ var _ref$cues = _ref.cues,
+ cues = _ref$cues === undefined ? [] : _ref$cues;
- captions.setText.call(player, cue);
+ var strippedCues = cues.map(function (cue) {
+ return utils.stripHTML(cue.text);
+ });
+ captions.updateCues.call(player, strippedCues);
});
player.embed.on('loaded', function () {
+ // Assure state and events are updated on autoplay
+ player.embed.getPaused().then(function (paused) {
+ assurePlaybackState.call(player, !paused);
+ if (!paused) {
+ utils.dispatchEvent.call(player, player.media, 'playing');
+ }
+ });
+
if (utils.is.element(player.embed.element) && player.supported.ui) {
var frame = player.embed.element;
@@ -10905,6 +10996,9 @@ function mapQualityUnits(levels) {
// Set playback state and trigger change (only on actual change)
function assurePlaybackState$1(play) {
+ if (play && !this.embed.hasPlayed) {
+ this.embed.hasPlayed = true;
+ }
if (this.media.paused === play) {
this.media.paused = !play;
utils.dispatchEvent.call(this, this.media, play ? 'play' : 'pause');
@@ -11318,7 +11412,7 @@ var youtube = {
case 1:
// Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)
- if (player.media.paused) {
+ if (player.media.paused && !player.embed.hasPlayed) {
player.media.pause();
} else {
assurePlaybackState$1.call(player, true);
@@ -12309,7 +12403,8 @@ var Plyr = function () {
// Captions
this.captions = {
active: null,
- currentTrack: null
+ currentTrack: -1,
+ meta: new WeakMap()
};
// Fullscreen
@@ -12320,8 +12415,7 @@ var Plyr = function () {
// Options
this.options = {
speed: [],
- quality: [],
- captions: []
+ quality: []
};
// Debugging
@@ -12697,8 +12791,8 @@ var Plyr = function () {
}
/**
- * Set the captions language
- * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)
+ * Set the caption track by index
+ * @param {number} - Caption index
*/
}, {
@@ -13389,60 +13483,41 @@ var Plyr = function () {
return Boolean(this.config.autoplay);
}
}, {
- key: 'language',
+ key: 'currentTrack',
set: function set(input) {
- // Nothing specified
- if (!utils.is.string(input)) {
- return;
- }
-
- // If empty string is passed, assume disable captions
- if (utils.is.empty(input)) {
- this.toggleCaptions(false);
- return;
- }
-
- // Normalize
- var language = input.toLowerCase();
-
- // Check for support
- if (!this.options.captions.includes(language)) {
- this.debug.warn('Unsupported language option: ' + language);
- return;
- }
-
- // Ensure captions are enabled
- this.toggleCaptions(true);
-
- // Enabled only
- if (language === 'enabled') {
- return;
- }
-
- // If nothing to change, bail
- if (this.language === language) {
- return;
- }
+ captions.set.call(this, input);
+ }
- // Update config
- this.captions.language = language;
+ /**
+ * Get the current caption track index (-1 if disabled)
+ */
+ ,
+ get: function get() {
+ var _captions = this.captions,
+ active = _captions.active,
+ currentTrack = _captions.currentTrack;
- // Clear caption
- captions.setText.call(this, null);
+ return active ? currentTrack : -1;
+ }
- // Update captions
- captions.setLanguage.call(this);
+ /**
+ * Set the wanted language for captions
+ * Since tracks can be added later it won't update the actual caption track until there is a matching track
+ * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)
+ */
- // Trigger an event
- utils.dispatchEvent.call(this, this.media, 'languagechange');
+ }, {
+ key: 'language',
+ set: function set(input) {
+ captions.setLanguage.call(this, input);
}
/**
- * Get the current captions language
+ * Get the current track's language
*/
,
get: function get() {
- return this.captions.language;
+ return (captions.getCurrentTrack.call(this) || {}).language;
}
/**
@@ -13518,9 +13593,7 @@ var Plyr = function () {
} else if (utils.is.nodeList(selector)) {
targets = Array.from(selector);
} else if (utils.is.array(selector)) {
- targets = selector.filter(function (i) {
- return utils.is.element(i);
- });
+ targets = selector.filter(utils.is.element);
}
if (utils.is.empty(targets)) {