From b86174b303af56125df4704fb3e218b41a951229 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 23 Nov 2018 11:42:41 +0100 Subject: [PATCH] MOBILE-2751 format-text: Fix handling youtube videos --- src/directives/format-text.ts | 57 +++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/src/directives/format-text.ts b/src/directives/format-text.ts index 2c46e20f4..51a47820e 100644 --- a/src/directives/format-text.ts +++ b/src/directives/format-text.ts @@ -502,16 +502,16 @@ export class CoreFormatTextDirective implements OnChanges { } const data = this.textUtils.parseJSON(video.getAttribute('data-setup') || video.getAttribute('data-setup-lazy') || '{}'), - youtubeId = data.techOrder && data.techOrder[0] && data.techOrder[0] == 'youtube' && data.sources && data.sources[0] && - data.sources[0].src && this.youtubeGetId(data.sources[0].src); + youtubeData = data.techOrder && data.techOrder[0] && data.techOrder[0] == 'youtube' && + this.parseYoutubeUrl(data.sources && data.sources[0] && data.sources[0].src); - if (!youtubeId) { + if (!youtubeData || !youtubeData.videoId) { return; } const iframe = document.createElement('iframe'); iframe.id = video.id; - iframe.src = 'https://www.youtube.com/embed/' + youtubeId; + iframe.src = 'https://www.youtube.com/embed/' + youtubeData.videoId; // Don't apply other params to align with Moodle web. iframe.setAttribute('frameborder', '0'); iframe.setAttribute('allowfullscreen', '1'); iframe.width = '100%'; @@ -630,15 +630,52 @@ export class CoreFormatTextDirective implements OnChanges { } /** - * Convenience function to extract YouTube Id to translate to embedded video. - * Based on http://stackoverflow.com/questions/3452546/javascript-regex-how-to-get-youtube-video-id-from-url + * Parse a YouTube URL. + * Based on Youtube.parseUrl from Moodle media/player/videojs/amd/src/Youtube-lazy.js * * @param {string} url URL of the video. */ - protected youtubeGetId(url: string): string { - const regExp = /^.*(?:(?:youtu.be\/)|(?:v\/)|(?:\/u\/\w\/)|(?:embed\/)|(?:watch\?))\??v?=?([^#\&\?]*).*/, - match = url.match(regExp); + protected parseYoutubeUrl(url: string): {videoId: string, listId?: string, start?: number} { + const result = { + videoId: null, + listId: null, + start: null + }; - return (match && match[1].length == 11) ? match[1] : ''; + if (!url) { + return result; + } + + url = this.textUtils.decodeHTML(url); + + // Get the video ID. + let match = url.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/); + + if (match && match[2].length === 11) { + result.videoId = match[2]; + } + + // Now get the playlist (if any). + match = url.match(/[?&]list=([^#\&\?]+)/); + + if (match && match[1]) { + result.listId = match[1]; + } + + // Now get the start time (if any). + match = url.match(/[?&]start=(\d+)/); + + if (match && match[1]) { + result.start = parseInt(match[1], 10); + } else { + // No start param, but it could have a time param. + match = url.match(/[?&]t=(\d+h)?(\d+m)?(\d+s)?/); + if (match) { + result.start = (match[1] ? parseInt(match[1], 10) * 3600 : 0) + (match[2] ? parseInt(match[2], 10) * 60 : 0) + + (match[3] ? parseInt(match[3], 10) : 0); + } + } + + return result; } }