From 15c04b22b914272f637cdf74b01e16d924f62dd1 Mon Sep 17 00:00:00 2001 From: Jean-Luc Delarbre Date: Mon, 23 Mar 2020 22:42:56 +0100 Subject: [PATCH 1/2] Multi media selection - Select among many existing media in page (ie many videos) - Select among many existing media type in page (audio, video, YouTube) - bump to 1.5.0 --- README.md | 8 ++++++ js/skiptotimestamp.js | 59 ++++++++++++++++++++++++++++++++++++------- readme.txt | 19 ++++++++++++-- skiptotimestamp.php | 22 ++++++++++++++-- 4 files changed, 95 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 88ebdd5..19f8ad6 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,14 @@ To create a link, either: Eg, "Just wait until...or...hold on, you can [skipto time=4:30]skip to[/skipto] this part of the video!" * Check the "Replace Timestamps Automatically" checkbox in the Settings > Skip to Timestamp, and watch as all your timestamps in the form "4:30" or "1:23:45" are automatically converted into links. +* If many media (audio, video, YouTube) exist in the same page, you can select among them: +[skipto time=4:30 media-id=2]skip to[/skipto] +For the 2nd media in the page. +* If the page contains a mix of media of different kind: audio, video or YouTube, you can select among them: +[skipto time=2:37 media-type="video"]2:37[/skipto] +[skipto time=5:56 media-id=2 media-type="audio"]5:56[/skipto] +[skipto time=13:05 media-id=4 media-type="video"]13:05[/skipto] +[skipto time=29:14 media-id=3 media-type="youtube"]29:14[/skipto] The links search for and skip to a time in: diff --git a/js/skiptotimestamp.js b/js/skiptotimestamp.js index d1749bf..3f5629f 100644 --- a/js/skiptotimestamp.js +++ b/js/skiptotimestamp.js @@ -18,7 +18,7 @@ var STT = { }; -STTSkipTo = function(time) { +STTSkipTo = function(time, mediaId, mediaType) { var audio = document.getElementsByTagName('audio'), video = document.getElementsByTagName('video'), iframe = document.getElementsByTagName('iframe'), @@ -33,16 +33,25 @@ STTSkipTo = function(time) { STT.doSkip(); return; } + + const doAudio = (mediaType !== 'video' && mediaType !== 'youtube') && (parseInt(STT.settings.link_audio) && audio.length); + const doVideo = (mediaType !== 'audio' && mediaType !== 'youtube') && (parseInt(STT.settings.link_video) && video.length); + const doYoutube = (mediaType !== 'audio' && mediaType !== 'video') && (parseInt(STT.settings.link_youtube && iframe.length)); - if ((parseInt(STT.settings.link_audio) && audio.length) || - (parseInt(STT.settings.link_video) && video.length)) + if (doAudio || doVideo) { STT.doSkip = STT.doHTML5Skip; - if (parseInt(STT.settings.link_audio) && audio.length) { - STT.media = audio[0]; + if (doAudio) { + if (mediaId > audio.length) { + mediaId = audio.length; + } + STT.media = audio[mediaId - 1]; } else { - STT.media = video[0]; + if (mediaId > video.length) { + mediaId = video.length; + } + STT.media = video[mediaId - 1]; } var playbackRate = STT.media.playbackRate; @@ -51,14 +60,29 @@ STTSkipTo = function(time) { STT.media.playbackRate = playbackRate; STT.media.play(); return; - } else if (parseInt(STT.settings.link_youtube && iframe.length)) { + } else if (doYoutube) { + // Search last youtube frame + var lastYoutubeFrameIndex = 1; + for (var j = 0; j < iframe.length; j++) { + if (iframe[j].src.search('youtube') !== -1) { + lastYoutubeFrameIndex = j + 1; + } + } + if (mediaId > lastYoutubeFrameIndex) { + mediaId = lastYoutubeFrameIndex; + } // Inspect the iframes, looking for a src with youtube in the URI for (var i = 0; i < iframe.length; i++) { if (iframe[i].src.search('youtube') !== -1) { + var foundYoutubeIndex = i + 1; + if (mediaId !== foundYoutubeIndex) { + continue; + } + // Set up the JS interface STT.doSkip = STT.doYoutubeSkip; - iframe[0].id = 'stt-youtube-player'; + iframe[i].id = 'stt-youtube-player'; STT.media = new YT.Player('stt-youtube-player', { events: { onReady: STT.doYoutubeSkip @@ -79,7 +103,24 @@ document.addEventListener('click', function (event) { // If the event target doesn't match bail if (!elem.hasAttribute('data-stt-time')) { return; + } + var media_id = 1; + if (elem.hasAttribute('media-id')) { + const media_id_attr = elem.getAttribute('media-id'); + var parsed = parseInt(media_id_attr, 10); + if (!isNaN(parsed)) { + if (parsed > 0) { + media_id = parsed; + } + } + } + var media_type = 'unset'; + if (elem.hasAttribute('media-type')) { + const media_type_attr = elem.getAttribute('media-type'); + if (media_type_attr === 'audio' || media_type_attr === 'video' || media_type_attr === 'youtube') { + media_type = media_type_attr; + } } var time = elem.getAttribute('data-stt-time'); - STTSkipTo(time); + STTSkipTo(time, media_id, media_type); }, false); diff --git a/readme.txt b/readme.txt index c1defcb..faee88c 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: doytch Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=mark%2edeutsch%40utoronto%2eca&lc=US&item_name=Coffee%20Donation%20%3d%29&amount=10%2e00¤cy_code=USD&button_subtype=services&bn=PP%2dBuyNowBF%3abtn_buynowCC_LG%2egif%3aNonHosted Tags: audio, embed, html5, media, plugin, shortcode, video, youtube Requires at least: 3.0.1 -Tested up to: 4.9.4 -Stable tag: 1.4.4 +Tested up to: 4.9.13 +Stable tag: 1.5.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -22,6 +22,16 @@ Eg, "Just wait until...or...hold on, you can [skipto time=4:30]skip to[/skipto] * Check the "Replace Timestamps Automatically" checkbox in the Settings > Skip to Timestamp, and watch as all your timestamps in the form "4:30" or "1:23:45" are automatically converted into links. +If many media (audio, video, YouTube) exist in the same page, you can select among them: +[skipto time=4:30 media-id=2]skip to[/skipto] +For the 2nd media in the page. + +If the page contains a mix of media of different kind: audio, video or YouTube, you can select among them: +[skipto time=2:37 media-type="video"]2:37[/skipto] +[skipto time=5:56 media-id=2 media-type="audio"]5:56[/skipto] +[skipto time=13:05 media-id=4 media-type="video"]13:05[/skipto] +[skipto time=29:14 media-id=3 media-type="youtube"]29:14[/skipto] + The links search for and skip to a time in: * Youtube videos embedded using Wordpress embeds. Make sure you're just pasting in the Youtube video link into your post editor and let WordPress embed things for you to ensure that the correct player is inserted into your post. @@ -59,6 +69,11 @@ browser and operating system you're running. If it's a bug, I'll get right to wo == Changelog == += 1.5.0 = +* Add possibility to select a media when many of them of a given type (audio, video or YouTube) exist on the same page +* Add possibility to select among every existing media type in page (audio, video or YouTube) +* Fix bug with YouTube frame + = 1.4.4 = * Fixed bug with autolinks on timestamps. diff --git a/skiptotimestamp.php b/skiptotimestamp.php index 3c5954e..43100a5 100644 --- a/skiptotimestamp.php +++ b/skiptotimestamp.php @@ -3,7 +3,7 @@ Plugin Name: Skip to Timestamp Plugin URI: http://github.com/doytch/SkipToTimestamp Description: Adds clickable timestamps via shortcode or search-and-replace that skip to a time in a media player. -Version: 1.4.4 +Version: 1.5.0 Author: Mark Deutsch Author URI: http://github.com/doytch License: GPLv2 @@ -67,11 +67,29 @@ function qed_stt_shortcode($attr, $content) { } else if (isset($attr['ts'])) { $time = $attr['ts']; } + + $mediaId = -1; + if (isset($attr['media-id'])) { + $mediaId = $attr['media-id']; + } + + $mediaType = -1; + if (isset($attr['media-type'])) { + $mediaType = $attr['media-type']; + } if ($time == -1) { return $content; } else { - return "{$content}"; + if ($mediaId == -1 && $mediaType == -1) { + return "{$content}"; + } else { + if ($mediaType == -1) { + return "{$content}"; + } else { + return "{$content}"; + } + } } } From a7e870705dbcfef791900b0f4bc6413ffbac95e3 Mon Sep 17 00:00:00 2001 From: Jean-Luc Delarbre Date: Mon, 6 Apr 2020 11:40:00 +0200 Subject: [PATCH 2/2] Multi media selection with URL --- README.md | 34 +++- js/skiptotimestamp.js | 252 ++++++++++++++--------- readme.txt | 25 ++- skiptotimestamp.php | 463 ++++++++++++++++++++++-------------------- 4 files changed, 440 insertions(+), 334 deletions(-) diff --git a/README.md b/README.md index 19f8ad6..73c91d2 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,33 @@ in an embedded media element. You've seen it in the Youtube descriptions, now ge To create a link, either: * Use our [skipto] shortcode which takes a "time" (or "timestamp" or "ts") argument and uses that to create a link. -Eg, "Just wait until...or...hold on, you can [skipto time=4:30]skip to[/skipto] this part of the video!" -* Check the "Replace Timestamps Automatically" checkbox in the Settings > Skip to Timestamp, and watch as all your -timestamps in the form "4:30" or "1:23:45" are automatically converted into links. +Eg, "Just wait until...or...hold on, you can ```[skipto time=4:30]skip to[/skipto]``` this part of the video!" +* Check the "Replace Timestamps Automatically" checkbox in the Settings > Skip to Timestamp, and watch as all your timestamps in the form "4:30" or "1:23:45" are automatically converted into links. * If many media (audio, video, YouTube) exist in the same page, you can select among them: -[skipto time=4:30 media-id=2]skip to[/skipto] -For the 2nd media in the page. +```[skipto time=4:30 media-id=2]skip to[/skipto]``` +For the 2nd media in the page (it is equivalent to the order in the page: 1st, 2nd...). * If the page contains a mix of media of different kind: audio, video or YouTube, you can select among them: -[skipto time=2:37 media-type="video"]2:37[/skipto] -[skipto time=5:56 media-id=2 media-type="audio"]5:56[/skipto] -[skipto time=13:05 media-id=4 media-type="video"]13:05[/skipto] -[skipto time=29:14 media-id=3 media-type="youtube"]29:14[/skipto] + ```[skipto time=2:37 media-type="video"]2:37[/skipto]``` + ```[skipto time=5:56 media-id=2 media-type="audio"]5:56[/skipto]``` + ```[skipto time=13:05 media-id=4 media-type="video"]13:05[/skipto]``` + ```[skipto time=29:14 media-id=3 media-type="youtube"]29:14[/skipto]``` + +* A more convenient way to select a media is to refer to it using its URL. Media order is not robust to changes (adding or moving a media). +```[skipto time=5:56 url-media-contains="https://www.domain.com/path/myAudioFile.mp3" media-type="audio"]5:56[/skipto]``` +```[skipto time=13:05 url-media-contains="https://www.domain.com/path/myVideoFile.mp3" media-type="video"]13:05[/skipto]``` + + "url-media-contains" and "media-id" are not usable together. It is not necessary to give the whole URL: +```[skipto time=5:56 url-media-contains="myAudioFile.mp3" media-type="audio"]5:56[/skipto]``` +```[skipto time=13:05 url-media-contains="myVideoFile.mp3" media-type="video"]13:05[/skipto]``` + + Only a part of the URL may be enough, give the minimum necessary: +```[skipto time=5:56 url-media-contains="path1/myAudioFile.mp3" media-type="audio"]5:56[/skipto]``` +```[skipto time=5:56 url-media-contains="path2/myAudioFile.mp3" media-type="audio"]5:56[/skipto]``` + + * For the YouTube case, you may have some trouble with the following: +```[skipto time=4:14 url-media-contains="https://www.youtube.com/watch?v=9ptyprXFPX0" media-type="youtube"]4:14[/skipto]``` +Instead prefer: +```[skipto time=4:14 url-media-contains="9ptyprXFPX0" media-type="youtube"]4:14[/skipto]``` The links search for and skip to a time in: diff --git a/js/skiptotimestamp.js b/js/skiptotimestamp.js index 3f5629f..5af9367 100644 --- a/js/skiptotimestamp.js +++ b/js/skiptotimestamp.js @@ -1,126 +1,180 @@ var STT = { - settings: STTSettings, - media: undefined, - skipTo: undefined, - isHTML5: false, - isYoutube: false, + settings: STTSettings, + media: undefined, + skipTo: undefined, + isHTML5: false, + isYoutube: false, + youtubeFrames: [], - doHTML5Skip: function() { - STT.media.removeEventListener('canplaythrough', STT.doHTML5Skip); - STT.media.currentTime = STT.skipTo; - STT.media.play(); - }, + doHTML5Skip: function() { + STT.doHTML5Clear(); + STT.media.currentTime = STT.skipTo; + STT.media.play(); + }, - doYoutubeSkip: function() { - STT.media.seekTo(STT.skipTo); - STT.media.playVideo(); - } + doYoutubeSkip: function() { + STT.doYoutubeClear(); + STT.media.seekTo(STT.skipTo); + STT.media.playVideo(); + }, + doHTML5Clear: function() { + STT.media.removeEventListener("canplaythrough", STT.doHTML5Skip); + }, + + doYoutubeClear: function() { + } }; -STTSkipTo = function(time, mediaId, mediaType) { - var audio = document.getElementsByTagName('audio'), - video = document.getElementsByTagName('video'), - iframe = document.getElementsByTagName('iframe'), - timeArray = time.split(':').reverse(), - seconds = parseInt(timeArray[0]), - minutes = timeArray.length > 1 ? parseInt(timeArray[1]) : 0, - hours = timeArray.length > 2 ? parseInt(timeArray[2]) : 0; +STTSkipTo = function(time, mediaId, mediaType, urlMediaUsed, urlMediaContains) { + var audio = document.getElementsByTagName("audio"), + video = document.getElementsByTagName("video"), + iframe = document.getElementsByTagName("iframe"), + timeArray = time.split(":").reverse(), + seconds = parseInt(timeArray[0]), + minutes = timeArray.length > 1 ? parseInt(timeArray[1]) : 0, + hours = timeArray.length > 2 ? parseInt(timeArray[2]) : 0; - STT.skipTo = seconds + (minutes * 60) + (hours * 3600); + STT.skipTo = seconds + (minutes * 60) + (hours * 3600); - if (STT.media) { - STT.doSkip(); - return; - } - - const doAudio = (mediaType !== 'video' && mediaType !== 'youtube') && (parseInt(STT.settings.link_audio) && audio.length); - const doVideo = (mediaType !== 'audio' && mediaType !== 'youtube') && (parseInt(STT.settings.link_video) && video.length); - const doYoutube = (mediaType !== 'audio' && mediaType !== 'video') && (parseInt(STT.settings.link_youtube && iframe.length)); + if (STT.media) { + STT.doClear(); + } + + const doAudio = (mediaType !== "video" && mediaType !== "youtube") && (parseInt(STT.settings.link_audio) && audio.length); + const doVideo = (mediaType !== "audio" && mediaType !== "youtube") && (parseInt(STT.settings.link_video) && video.length); + const doYoutube = (mediaType !== "audio" && mediaType !== "video") && (parseInt(STT.settings.link_youtube && iframe.length)); - if (doAudio || doVideo) - { - STT.doSkip = STT.doHTML5Skip; + if (doAudio || doVideo) + { + STT.doClear = STT.doHTML5Clear; - if (doAudio) { - if (mediaId > audio.length) { - mediaId = audio.length; - } - STT.media = audio[mediaId - 1]; - } else { - if (mediaId > video.length) { - mediaId = video.length; - } - STT.media = video[mediaId - 1]; - } + if (doAudio) { + if (mediaId > audio.length) { + mediaId = audio.length; + } + if (urlMediaUsed) { + for (var i_a = 0; i_a < audio.length; i_a++) { + var audioURL = audio[i_a].currentSrc; + if (audioURL.includes(urlMediaContains)) { + mediaId = i_a + 1; + break; + } + } + } + STT.media = audio[mediaId - 1]; + } else { + if (mediaId > video.length) { + mediaId = video.length; + } + if (urlMediaUsed) { + for (var i_v = 0; i_v < video.length; i_v++) { + var videoURL = video[i_v].currentSrc; + if (videoURL.includes(urlMediaContains)) { + mediaId = i_v + 1; + break; + } + } + } + STT.media = video[mediaId - 1]; + } - var playbackRate = STT.media.playbackRate; - STT.media.addEventListener('canplaythrough', STT.doHTML5Skip); - STT.media.load(); - STT.media.playbackRate = playbackRate; - STT.media.play(); - return; - } else if (doYoutube) { - // Search last youtube frame - var lastYoutubeFrameIndex = 1; - for (var j = 0; j < iframe.length; j++) { - if (iframe[j].src.search('youtube') !== -1) { - lastYoutubeFrameIndex = j + 1; - } - } - if (mediaId > lastYoutubeFrameIndex) { - mediaId = lastYoutubeFrameIndex; - } - // Inspect the iframes, looking for a src with youtube in the URI - for (var i = 0; i < iframe.length; i++) { - if (iframe[i].src.search('youtube') !== -1) { - var foundYoutubeIndex = i + 1; - if (mediaId !== foundYoutubeIndex) { - continue; - } - - // Set up the JS interface - STT.doSkip = STT.doYoutubeSkip; + var playbackRate = STT.media.playbackRate; + STT.media.addEventListener("canplaythrough", STT.doHTML5Skip); + STT.media.load(); + STT.media.playbackRate = playbackRate; + STT.media.play(); + return; + } else if (doYoutube) { + // Search last youtube frame + var lastYoutubeFrameIndex = 1; + for (var j = 0; j < iframe.length; j++) { + if (iframe[j].src.search("youtube") !== -1) { + lastYoutubeFrameIndex = j + 1; + } + } + if (mediaId > lastYoutubeFrameIndex) { + mediaId = lastYoutubeFrameIndex; + } + var foundYoutubeIndex = 0; + if (urlMediaUsed) { + for (var i_y = 0; i_y < iframe.length; i_y++) { + if (iframe[i_y].src.search("youtube") !== -1) { + foundYoutubeIndex++; + if (iframe[i_y].src.includes(urlMediaContains)) { + mediaId = foundYoutubeIndex; + break; + } + } + } + } + // Inspect the iframes, looking for a src with youtube in the URI + foundYoutubeIndex = 0; + for (var i = 0; i < iframe.length; i++) { + if (iframe[i].src.search("youtube") !== -1) { + foundYoutubeIndex++; + if (mediaId !== foundYoutubeIndex) { + continue; + } + + // Set up the JS interface + STT.doClear = STT.doYoutubeClear; - iframe[i].id = 'stt-youtube-player'; - STT.media = new YT.Player('stt-youtube-player', { - events: { - onReady: STT.doYoutubeSkip - } - }); - return; - } - } - } + var frameId = "stt-youtube-player_".concat(i.toString()); + if (iframe[i].id) { + STT.media = STT.youtubeFrames[i]; + STT.doYoutubeSkip(); + } else { + iframe[i].id = frameId; + STT.media = new YT.Player(frameId, { + events: { + onReady: STT.doYoutubeSkip + } + }); + STT.youtubeFrames[i] = STT.media; + } + return; + } + } + } - console.log('Skip to Timestamp: No media player found!'); - return; -} + console.log("Skip to Timestamp: No media player found!"); + return; +}; // Listen to all clicks on the document -document.addEventListener('click', function (event) { +document.addEventListener("click", function (event) { var elem = event.target; - // If the event target doesn't match bail - if (!elem.hasAttribute('data-stt-time')) { - return; + // If the event target doesn't match bail + if (!elem.hasAttribute("data-stt-time")) { + return; } + const mediaIdAttribute = "media-id"; var media_id = 1; - if (elem.hasAttribute('media-id')) { - const media_id_attr = elem.getAttribute('media-id'); - var parsed = parseInt(media_id_attr, 10); + if (elem.hasAttribute(mediaIdAttribute)) { + const mediaIdAttr = elem.getAttribute(mediaIdAttribute); + var parsed = parseInt(mediaIdAttr, 10); if (!isNaN(parsed)) { if (parsed > 0) { media_id = parsed; } } } - var media_type = 'unset'; - if (elem.hasAttribute('media-type')) { - const media_type_attr = elem.getAttribute('media-type'); - if (media_type_attr === 'audio' || media_type_attr === 'video' || media_type_attr === 'youtube') { - media_type = media_type_attr; + const urlMediaContainsAttribute = "url-media-contains"; + var urlMediaContains = ""; + var urlMediaUsed = false; + if (elem.hasAttribute(urlMediaContainsAttribute)) { + urlMediaContains = elem.getAttribute(urlMediaContainsAttribute); + urlMediaUsed = true; + } + const mediaTypeAttribute = "media-type"; + var mediaType = "unset"; + if (elem.hasAttribute(mediaTypeAttribute)) { + const mediaTypeAttr = elem.getAttribute(mediaTypeAttribute); + if (mediaTypeAttr === "audio" || mediaTypeAttr === "video" || mediaTypeAttr === "youtube") { + mediaType = mediaTypeAttr; } } - var time = elem.getAttribute('data-stt-time'); - STTSkipTo(time, media_id, media_type); + var time = elem.getAttribute("data-stt-time"); + STTSkipTo(time, media_id, mediaType, urlMediaUsed, urlMediaContains); }, false); diff --git a/readme.txt b/readme.txt index faee88c..870d7ba 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=mark%2ed Tags: audio, embed, html5, media, plugin, shortcode, video, youtube Requires at least: 3.0.1 Tested up to: 4.9.13 -Stable tag: 1.5.0 +Stable tag: 1.6.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -24,7 +24,7 @@ timestamps in the form "4:30" or "1:23:45" are automatically converted into link If many media (audio, video, YouTube) exist in the same page, you can select among them: [skipto time=4:30 media-id=2]skip to[/skipto] -For the 2nd media in the page. +For the 2nd media in the page (it is equivalent to the order in the page: 1st, 2nd...). If the page contains a mix of media of different kind: audio, video or YouTube, you can select among them: [skipto time=2:37 media-type="video"]2:37[/skipto] @@ -32,6 +32,23 @@ If the page contains a mix of media of different kind: audio, video or YouTube, [skipto time=13:05 media-id=4 media-type="video"]13:05[/skipto] [skipto time=29:14 media-id=3 media-type="youtube"]29:14[/skipto] +A more convenient way to select a media is to refer to it using its URL. Media order is not robust to +changes (adding or moving a media). +[skipto time=5:56 url-media-contains="https://www.domain.com/path/myAudioFile.mp3" media-type="audio"]5:56[/skipto] +[skipto time=13:05 url-media-contains="https://www.domain.com/path/myVideoFile.mp3" media-type="video"]13:05[/skipto] +"url-media-contains" and "media-id" are not usable together. +It is not necessary to give the whole URL: +[skipto time=5:56 url-media-contains="myAudioFile.mp3" media-type="audio"]5:56[/skipto] +[skipto time=13:05 url-media-contains="myVideoFile.mp3" media-type="video"]13:05[/skipto] +Only a part of the URL may be enough, give the minimum necessary: +[skipto time=5:56 url-media-contains="path1/myAudioFile.mp3" media-type="audio"]5:56[/skipto] +[skipto time=5:56 url-media-contains="path2/myAudioFile.mp3" media-type="audio"]5:56[/skipto] + +For the YouTube case, you may have some trouble with the following: +[skipto time=4:14 url-media-contains="https://www.youtube.com/watch?v=9ptyprXFPX0" media-type="youtube"]4:14[/skipto] +Instead prefer: +[skipto time=4:14 url-media-contains="9ptyprXFPX0" media-type="youtube"]4:14[/skipto] + The links search for and skip to a time in: * Youtube videos embedded using Wordpress embeds. Make sure you're just pasting in the Youtube video link into your post editor and let WordPress embed things for you to ensure that the correct player is inserted into your post. @@ -69,6 +86,10 @@ browser and operating system you're running. If it's a bug, I'll get right to wo == Changelog == += 1.6.0 = +* Add media selection using URL +* Bug fix: Unable to skip into another YouTube video once done in a given one. + = 1.5.0 = * Add possibility to select a media when many of them of a given type (audio, video or YouTube) exist on the same page * Add possibility to select among every existing media type in page (audio, video or YouTube) diff --git a/skiptotimestamp.php b/skiptotimestamp.php index 43100a5..be721e8 100644 --- a/skiptotimestamp.php +++ b/skiptotimestamp.php @@ -3,7 +3,7 @@ Plugin Name: Skip to Timestamp Plugin URI: http://github.com/doytch/SkipToTimestamp Description: Adds clickable timestamps via shortcode or search-and-replace that skip to a time in a media player. -Version: 1.5.0 +Version: 1.6.0 Author: Mark Deutsch Author URI: http://github.com/doytch License: GPLv2 @@ -25,14 +25,14 @@ /* --- Installation --- */ register_activation_hook(__FILE__, 'qed_stt_install'); function qed_stt_install() { - $default_settings = array( - 'only_link_singular' => 1, - 'link_audio' => 1, - 'link_video' => 1, - 'link_youtube' => 1, - 'auto_replace_ts' => 0 - ); - update_option('qed_stt_settings', $default_settings); + $default_settings = array( + 'only_link_singular' => 1, + 'link_audio' => 1, + 'link_video' => 1, + 'link_youtube' => 1, + 'auto_replace_ts' => 0 + ); + update_option('qed_stt_settings', $default_settings); } /* --- Uninstallation --- */ @@ -42,199 +42,214 @@ function qed_stt_install() { // Enable Youtube's Javascript API for videos embedded with Wordpress' builtin oembeds add_filter('oembed_result', 'qed_stt_enable_yt_jsapi'); function qed_stt_enable_yt_jsapi($html) { - if (strstr($html, 'youtube.com/embed/')) { - $html = str_replace('?feature=oembed', '?feature=oembed&enablejsapi=1', $html); - } - return $html; + if (strstr($html, 'youtube.com/embed/')) { + $html = str_replace('?feature=oembed', '?feature=oembed&enablejsapi=1', $html); + } + return $html; } /* --- Shortcode --- */ add_shortcode('skipto', 'qed_stt_shortcode'); function qed_stt_shortcode($attr, $content) { - $options = get_option('qed_stt_settings'); - // Only link singular posts if the option is set - if (!is_singular() && $options['only_link_singular']) { - return $content; - } - - // Cover a few attributes for ease of use - $time = -1; - if (isset($attr['time'])) { - $time = $attr['time']; - } else if (isset($attr['timestamp'])) { - $time = $attr['timestamp']; - } else if (isset($attr['ts'])) { - $time = $attr['ts']; - } - - $mediaId = -1; - if (isset($attr['media-id'])) { - $mediaId = $attr['media-id']; - } - - $mediaType = -1; - if (isset($attr['media-type'])) { - $mediaType = $attr['media-type']; - } - - if ($time == -1) { - return $content; - } else { - if ($mediaId == -1 && $mediaType == -1) { - return "{$content}"; - } else { - if ($mediaType == -1) { - return "{$content}"; - } else { - return "{$content}"; - } - } - } + $options = get_option('qed_stt_settings'); + // Only link singular posts if the option is set + if (!is_singular() && $options['only_link_singular']) { + return $content; + } + + // Cover a few attributes for ease of use + $time = -1; + if (isset($attr['time'])) { + $time = $attr['time']; + } else if (isset($attr['timestamp'])) { + $time = $attr['timestamp']; + } else if (isset($attr['ts'])) { + $time = $attr['ts']; + } + + $mediaIdAttribute = 'media-id'; + $mediaId = -1; + if (isset($attr[$mediaIdAttribute])) { + $mediaId = $attr[$mediaIdAttribute]; + } + + $mediaTypeAttribute = 'media-type'; + $mediaType = -1; + if (isset($attr[$mediaTypeAttribute])) { + $mediaType = $attr[$mediaTypeAttribute]; + } + + $urlMediaContainsAttribute = 'url-media-contains'; + $urlMediaContains = -1; + if (isset($attr[$urlMediaContainsAttribute])) { + $urlMediaContains = $attr[$urlMediaContainsAttribute]; + } + + if ($time == -1) { + return $content; + } else { + $tagStart = "post_content, '[skipto ') !== false) { - return true; - } else { - return false; - } + $the_post = get_post(get_the_ID()); + if (stripos($the_post->post_content, '[skipto ') !== false) { + return true; + } else { + return false; + } } /* --- Admin Page --- */ // Create the settings submenu add_action('admin_menu', 'qed_stt_create_menu'); function qed_stt_create_menu() { - add_options_page( - 'Skip to Timestamp', - 'Skip to Timestamp', - 'manage_options', - 'skiptotimestamp', - 'qed_stt_create_settings_page' - ); + add_options_page( + 'Skip to Timestamp', + 'Skip to Timestamp', + 'manage_options', + 'skiptotimestamp', + 'qed_stt_create_settings_page' + ); } // Draw the settings page function qed_stt_create_settings_page() { ?> -
- -

Skip to Timestamp

-
-
- - - - - + +

Skip to Timestamp

+
+ + + + +
+ Only generate links on singular posts/pages."; + $options = get_option('qed_stt_settings'); + $only_link_singular = $options['only_link_singular']; + echo "Only generate links on singular posts/pages."; } function qed_stt_link_audio_create() { - $options = get_option('qed_stt_settings'); - $link_audio = $options['link_audio']; - echo "Skip to timestamp in audio embedded with the [audio] shortcode or <audio> HTML5 tag."; + $options = get_option('qed_stt_settings'); + $link_audio = $options['link_audio']; + echo "Skip to timestamp in audio embedded with the [audio] shortcode or <audio> HTML5 tag."; } function qed_stt_link_video_create() { - $options = get_option('qed_stt_settings'); - $link_video = $options['link_video']; - echo "Skip to timestamp in video embedded with the [video] shortcode or <video> HTML5 tag."; + $options = get_option('qed_stt_settings'); + $link_video = $options['link_video']; + echo "Skip to timestamp in video embedded with the [video] shortcode or <video> HTML5 tag."; } function qed_stt_link_youtube_create() { - $options = get_option('qed_stt_settings'); - $link_youtube = $options['link_youtube']; - echo "Skip to timestamp in embedded Youtube videos."; + $options = get_option('qed_stt_settings'); + $link_youtube = $options['link_youtube']; + echo "Skip to timestamp in embedded Youtube videos."; } function qed_stt_auto_replace_ts_create() { - $options = get_option('qed_stt_settings'); - $auto_replace_ts = $options['auto_replace_ts']; - echo "
Normally you create hyperlinks using the [skipto] shortcode. Check this and text formatted like"; - echo " '3:45' in your posts will get automatically replaced with a hyperlink."; + $options = get_option('qed_stt_settings'); + $auto_replace_ts = $options['auto_replace_ts']; + echo "
Normally you create hyperlinks using the [skipto] shortcode. Check this and text formatted like"; + echo " '3:45' in your posts will get automatically replaced with a hyperlink."; } function qed_stt_validate_settings($input) { - $valid = array( - 'only_link_singular' => isset($input['only_link_singular']) && true == $input['only_link_singular'] ? true : false, - 'link_audio' => isset($input['link_audio']) && true == $input['link_audio'] ? true : false, - 'link_video' => isset($input['link_video']) && true == $input['link_video'] ? true : false, - 'link_youtube' => isset($input['link_youtube']) && true == $input['link_youtube'] ? true : false, - 'auto_replace_ts' => isset($input['auto_replace_ts']) && true == $input['auto_replace_ts'] ? true : false - ); - - return $valid; + $valid = array( + 'only_link_singular' => isset($input['only_link_singular']) && true == $input['only_link_singular'] ? true : false, + 'link_audio' => isset($input['link_audio']) && true == $input['link_audio'] ? true : false, + 'link_video' => isset($input['link_video']) && true == $input['link_video'] ? true : false, + 'link_youtube' => isset($input['link_youtube']) && true == $input['link_youtube'] ? true : false, + 'auto_replace_ts' => isset($input['auto_replace_ts']) && true == $input['auto_replace_ts'] ? true : false + ); + + return $valid; } /* --- Metaboxes --- */ @@ -247,92 +262,92 @@ function qed_stt_validate_settings($input) { * */ function qed_stt_add_metabox($post_type) { - $screens = array( 'post', 'page'); - - foreach ($screens as $screen) { - add_meta_box( - 'stt_post_mb', - __('Skip to Timestamp Configuration', 'stt'), - 'qed_stt_create_metabox', - $screen, - 'normal', - 'high' - ); - } + $screens = array( 'post', 'page'); + + foreach ($screens as $screen) { + add_meta_box( + 'stt_post_mb', + __('Skip to Timestamp Configuration', 'stt'), + 'qed_stt_create_metabox', + $screen, + 'normal', + 'high' + ); + } } function qed_stt_create_metabox($post) { - wp_nonce_field('qed_stt_post_mb', 'qed_stt_post_mb_nonce'); - - ?> - - - - - -
- - /> -
- + + + + + +
+ + /> +
+ \d{1,2})[:.])?(?\d{1,2})[:.])(?\d{1,2})/", - '
$0', - $content - ); - - return $content; + // Don't autolink if it's turned off. + $options = get_option('qed_stt_settings'); + if (!$options['auto_replace_ts']) { + return $content; + } + // Don't autolink if singular page and only linking on singular pages is turned on. + if (!is_singular() && $options['only_link_singular']) { + return $content; + } + // Don't autolink if they've turned off autolinking for this page. + if (get_post_meta(get_the_ID(), 'qed-stt-disable-auto-link', true)) { + return $content; + } + + // Don't allow shortcodes and autolinks in the same post + if (qed_stt_post_has_shortcode()) { + return $content; + } + + $content = preg_replace( + "/(?:(?:(?\d{1,2})[:.])?(?\d{1,2})[:.])(?\d{1,2})/", + '$0', + $content + ); + + return $content; } add_action('wp_footer', 'qed_stt_custom_css');