diff options
Diffstat (limited to 'src/js/plugins')
-rw-r--r-- | src/js/plugins/ads.js | 20 | ||||
-rw-r--r-- | src/js/plugins/preview-thumbnails.js | 24 | ||||
-rw-r--r-- | src/js/plugins/vimeo.js | 64 | ||||
-rw-r--r-- | src/js/plugins/youtube.js | 71 |
4 files changed, 96 insertions, 83 deletions
diff --git a/src/js/plugins/ads.js b/src/js/plugins/ads.js index 1a52ebce..12b5cc31 100644 --- a/src/js/plugins/ads.js +++ b/src/js/plugins/ads.js @@ -15,7 +15,7 @@ import { silencePromise } from '../utils/promise'; import { formatTime } from '../utils/time'; import { buildUrlParams } from '../utils/urls'; -const destroy = instance => { +const destroy = (instance) => { // Destroy our adsManager if (instance.manager) { instance.manager.destroy(); @@ -179,10 +179,10 @@ class Ads { // Listen and respond to ads loaded and error events this.loader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, - event => this.onAdsManagerLoaded(event), + (event) => this.onAdsManagerLoaded(event), false, ); - this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false); + this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, (error) => this.onAdError(error), false); // Request video ads to be pre-loaded this.requestAds(); @@ -264,11 +264,11 @@ class Ads { // Add listeners to the required events // Advertisement error events - this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error)); + this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, (error) => this.onAdError(error)); // Advertisement regular events - Object.keys(google.ima.AdEvent.Type).forEach(type => { - this.manager.addEventListener(google.ima.AdEvent.Type[type], e => this.onAdEvent(e)); + Object.keys(google.ima.AdEvent.Type).forEach((type) => { + this.manager.addEventListener(google.ima.AdEvent.Type[type], (e) => this.onAdEvent(e)); }); // Resolve our adsManager @@ -278,7 +278,7 @@ class Ads { addCuePoints() { // Add advertisement cue's within the time line if available if (!is.empty(this.cuePoints)) { - this.cuePoints.forEach(cuePoint => { + this.cuePoints.forEach((cuePoint) => { if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) { const seekElement = this.player.elements.progress; @@ -310,7 +310,7 @@ class Ads { const adData = event.getAdData(); // Proxy event - const dispatchEvent = type => { + const dispatchEvent = (type) => { triggerEvent.call(this.player, this.player.media, `ads${type.replace(/_/g, '').toLowerCase()}`); }; @@ -565,7 +565,7 @@ class Ads { } // Re-set our adsManager promises - this.managerPromise = new Promise(resolve => { + this.managerPromise = new Promise((resolve) => { this.on('loaded', resolve); this.player.debug.log(this.manager); }); @@ -586,7 +586,7 @@ class Ads { const handlers = this.events[event]; if (is.array(handlers)) { - handlers.forEach(handler => { + handlers.forEach((handler) => { if (is.function(handler)) { handler.apply(this, args); } diff --git a/src/js/plugins/preview-thumbnails.js b/src/js/plugins/preview-thumbnails.js index 6ce53f28..16167247 100644 --- a/src/js/plugins/preview-thumbnails.js +++ b/src/js/plugins/preview-thumbnails.js @@ -5,15 +5,15 @@ import is from '../utils/is'; import { formatTime } from '../utils/time'; // Arg: vttDataString example: "WEBVTT\n\n1\n00:00:05.000 --> 00:00:10.000\n1080p-00001.jpg" -const parseVtt = vttDataString => { +const parseVtt = (vttDataString) => { const processedList = []; const frames = vttDataString.split(/\r\n\r\n|\n\n|\r\r/); - frames.forEach(frame => { + frames.forEach((frame) => { const result = {}; const lines = frame.split(/\r\n|\n|\r/); - lines.forEach(line => { + lines.forEach((line) => { if (!is.number(result.startTime)) { // The line with start and end times on it is the first line of interest const matchTimes = line.match( @@ -130,7 +130,7 @@ class PreviewThumbnails { // Download VTT files and parse them getThumbnails() { - return new Promise(resolve => { + return new Promise((resolve) => { const { src } = this.player.config.previewThumbnails; if (is.empty(src)) { @@ -149,7 +149,7 @@ class PreviewThumbnails { // Via callback() if (is.function(src)) { - src(thumbnails => { + src((thumbnails) => { this.thumbnails = thumbnails; sortAndResolve(); }); @@ -159,7 +159,7 @@ class PreviewThumbnails { // If string, convert into single-element list const urls = is.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails - const promises = urls.map(u => this.getThumbnail(u)); + const promises = urls.map((u) => this.getThumbnail(u)); // Resolve Promise.all(promises).then(sortAndResolve); } @@ -168,8 +168,8 @@ class PreviewThumbnails { // Process individual VTT file getThumbnail(url) { - return new Promise(resolve => { - fetch(url).then(response => { + return new Promise((resolve) => { + fetch(url).then((response) => { const thumbnail = { frames: parseVtt(response), height: null, @@ -360,7 +360,7 @@ class PreviewThumbnails { // Find the desired thumbnail index // TODO: Handle a video longer than the thumbs where thumbNum is null const thumbNum = this.thumbnails[0].frames.findIndex( - frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime, + (frame) => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime, ); const hasThumb = thumbNum >= 0; let qualityIndex = 0; @@ -454,7 +454,7 @@ class PreviewThumbnails { // Remove all preview images that aren't the designated current image removeOldImages(currentImage) { // Get a list of all images, convert it from a DOM list to an array - Array.from(this.currentImageContainer.children).forEach(image => { + Array.from(this.currentImageContainer.children).forEach((image) => { if (image.tagName.toLowerCase() !== 'img') { return; } @@ -481,7 +481,7 @@ class PreviewThumbnails { // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame // This will only preload the lowest quality preloadNearby(thumbNum, forward = true) { - return new Promise(resolve => { + return new Promise((resolve) => { setTimeout(() => { const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text; @@ -496,7 +496,7 @@ class PreviewThumbnails { let foundOne = false; - thumbnailsClone.forEach(frame => { + thumbnailsClone.forEach((frame) => { const newThumbFilename = frame.text; if (newThumbFilename !== oldThumbFilename) { diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js index 33c327d7..b050cc53 100644 --- a/src/js/plugins/vimeo.js +++ b/src/js/plugins/vimeo.js @@ -58,7 +58,7 @@ const vimeo = { .then(() => { vimeo.ready.call(player); }) - .catch(error => { + .catch((error) => { player.debug.warn('Vimeo SDK (player.js) failed to load', error); }); } else { @@ -112,25 +112,29 @@ const vimeo = { } // Inject the package - const { poster } = player; - if (premium) { - iframe.setAttribute('data-poster', poster); + if (premium || !config.customControls) { + iframe.setAttribute('data-poster', player.poster); player.media = replaceElement(iframe, player.media); } else { - const wrapper = createElement('div', { class: player.config.classNames.embedContainer, 'data-poster': poster }); + const wrapper = createElement('div', { + class: player.config.classNames.embedContainer, + 'data-poster': player.poster, + }); wrapper.appendChild(iframe); player.media = replaceElement(wrapper, player.media); } - + // Get poster image - fetch(format(player.config.urls.vimeo.api, src)).then(response => { - if (is.empty(response) || !response.thumbnail_url) { - return; - } - - // Set and show poster - ui.setPoster.call(player, response.thumbnail_url).catch(() => { }); - }); + if (!config.customControls) { + fetch(format(player.config.urls.vimeo.api, src)).then((response) => { + if (is.empty(response) || !response.thumbnail_url) { + return; + } + + // Set and show poster + ui.setPoster.call(player, response.thumbnail_url).catch(() => {}); + }); + } // Setup instance // https://github.com/vimeo/player.js @@ -263,11 +267,11 @@ const vimeo = { let currentSrc; player.embed .getVideoUrl() - .then(value => { + .then((value) => { currentSrc = value; controls.setDownloadUrl.call(player); }) - .catch(error => { + .catch((error) => { this.debug.warn(error); }); @@ -285,49 +289,49 @@ const vimeo = { }); // Set aspect ratio based on video size - Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => { + Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then((dimensions) => { const [width, height] = dimensions; player.embed.ratio = [width, height]; setAspectRatio.call(this); }); // Set autopause - player.embed.setAutopause(player.config.autopause).then(state => { + player.embed.setAutopause(player.config.autopause).then((state) => { player.config.autopause = state; }); // Get title - player.embed.getVideoTitle().then(title => { + player.embed.getVideoTitle().then((title) => { player.config.title = title; ui.setTitle.call(this); }); // Get current time - player.embed.getCurrentTime().then(value => { + player.embed.getCurrentTime().then((value) => { currentTime = value; triggerEvent.call(player, player.media, 'timeupdate'); }); // Get duration - player.embed.getDuration().then(value => { + player.embed.getDuration().then((value) => { player.media.duration = value; triggerEvent.call(player, player.media, 'durationchange'); }); // Get captions - player.embed.getTextTracks().then(tracks => { + player.embed.getTextTracks().then((tracks) => { player.media.textTracks = tracks; captions.setup.call(player); }); player.embed.on('cuechange', ({ cues = [] }) => { - const strippedCues = cues.map(cue => stripHTML(cue.text)); + const strippedCues = cues.map((cue) => stripHTML(cue.text)); captions.updateCues.call(player, strippedCues); }); player.embed.on('loaded', () => { // Assure state and events are updated on autoplay - player.embed.getPaused().then(paused => { + player.embed.getPaused().then((paused) => { assurePlaybackState.call(player, !paused); if (!paused) { triggerEvent.call(player, player.media, 'playing'); @@ -360,13 +364,13 @@ const vimeo = { assurePlaybackState.call(player, false); }); - player.embed.on('timeupdate', data => { + player.embed.on('timeupdate', (data) => { player.media.seeking = false; currentTime = data.seconds; triggerEvent.call(player, player.media, 'timeupdate'); }); - player.embed.on('progress', data => { + player.embed.on('progress', (data) => { player.media.buffered = data.percent; triggerEvent.call(player, player.media, 'progress'); @@ -377,7 +381,7 @@ const vimeo = { // Get duration as if we do it before load, it gives an incorrect value // https://github.com/sampotts/plyr/issues/891 - player.embed.getDuration().then(value => { + player.embed.getDuration().then((value) => { if (value !== player.media.duration) { player.media.duration = value; triggerEvent.call(player, player.media, 'durationchange'); @@ -395,13 +399,15 @@ const vimeo = { triggerEvent.call(player, player.media, 'ended'); }); - player.embed.on('error', detail => { + player.embed.on('error', (detail) => { player.media.error = detail; triggerEvent.call(player, player.media, 'error'); }); // Rebuild UI - setTimeout(() => ui.build.call(player), 0); + if (config.customControls) { + setTimeout(() => ui.build.call(player), 0); + } }, }; diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js index 89a75d89..db5781e6 100644 --- a/src/js/plugins/youtube.js +++ b/src/js/plugins/youtube.js @@ -70,7 +70,7 @@ const youtube = { }; // Load the SDK - loadScript(this.config.urls.youtube.sdk).catch(error => { + loadScript(this.config.urls.youtube.sdk).catch((error) => { this.debug.warn('YouTube API failed to load', error); }); } @@ -81,7 +81,7 @@ const youtube = { const url = format(this.config.urls.youtube.api, videoId); fetch(url) - .then(data => { + .then((data) => { if (is.object(data)) { const { title, height, width } = data; @@ -104,6 +104,7 @@ const youtube = { // API ready ready() { const player = this; + const config = player.config.youtube; // Ignore already setup (race condition) const currentId = player.media && player.media.getAttribute('id'); if (!is.empty(currentId) && currentId.startsWith('youtube-')) { @@ -121,43 +122,46 @@ const youtube = { // Replace the <iframe> with a <div> due to YouTube API issues const videoId = parseId(source); const id = generateId(player.provider); - // Get poster, if already set - const { poster } = player; // Replace media element - const container = createElement('div', { id, 'data-poster': poster }); + const container = createElement('div', { id, 'data-poster': config.customControls ? player.poster : undefined }); player.media = replaceElement(container, player.media); - // Id to poster wrapper - const posterSrc = s => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`; - - // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) - loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded - .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3 - .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists - .then(image => ui.setPoster.call(player, image.src)) - .then(src => { - // If the image is padded, use background-size "cover" instead (like youtube does too with their posters) - if (!src.includes('maxres')) { - player.elements.poster.style.backgroundSize = 'cover'; - } - }) - .catch(() => {}); - - const config = player.config.youtube; + // Only load the poster when using custom controls + if (config.customControls) { + const posterSrc = (s) => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`; + + // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) + loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded + .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3 + .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists + .then((image) => ui.setPoster.call(player, image.src)) + .then((src) => { + // If the image is padded, use background-size "cover" instead (like youtube does too with their posters) + if (!src.includes('maxres')) { + player.elements.poster.style.backgroundSize = 'cover'; + } + }) + .catch(() => {}); + } // Setup instance // https://developers.google.com/youtube/iframe_api_reference - player.embed = new window.YT.Player(id, { + player.embed = new window.YT.Player(player.media, { videoId, host: getHost(config), playerVars: extend( {}, { - autoplay: player.config.autoplay ? 1 : 0, // Autoplay - hl: player.config.hl, // iframe interface language - controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported - disablekb: 1, // Disable keyboard as we handle it - playsinline: !player.config.fullscreen.iosNative ? 1 : 0, // Allow iOS inline playback + // Autoplay + autoplay: player.config.autoplay ? 1 : 0, + // iframe interface language + hl: player.config.hl, + // Only show controls if not fully supported or opted out + controls: player.supported.ui && config.customControls ? 0 : 1, + // Disable keyboard as we handle it + disablekb: 1, + // Allow iOS inline playback + playsinline: !player.config.fullscreen.iosNative ? 1 : 0, // Captions are flaky on YouTube cc_load_policy: player.captions.active ? 1 : 0, cc_lang_pref: player.config.captions.language, @@ -278,6 +282,7 @@ const youtube = { const toggle = is.boolean(input) ? input : muted; muted = toggle; instance[toggle ? 'mute' : 'unMute'](); + instance.setVolume(volume * 100); triggerEvent.call(player, player.media, 'volumechange'); }, }); @@ -299,10 +304,10 @@ const youtube = { // Get available speeds const speeds = instance.getAvailablePlaybackRates(); // Filter based on config - player.options.speed = speeds.filter(s => player.config.speed.options.includes(s)); + player.options.speed = speeds.filter((s) => player.config.speed.options.includes(s)); // Set the tabindex to avoid focus entering iframe - if (player.supported.ui) { + if (player.supported.ui && config.customControls) { player.media.setAttribute('tabindex', -1); } @@ -335,7 +340,9 @@ const youtube = { }, 200); // Rebuild UI - setTimeout(() => ui.build.call(player), 50); + if (config.customControls) { + setTimeout(() => ui.build.call(player), 50); + } }, onStateChange(event) { // Get the instance @@ -386,7 +393,7 @@ const youtube = { case 1: // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) - if (!player.config.autoplay && player.media.paused && !player.embed.hasPlayed) { + if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) { player.media.pause(); } else { assurePlaybackState.call(player, true); |