您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a button for watching YouTube videos in picture in picture mode while viewing comments and prevents the page from scrolling up if the user clicks a timestamp in the comments
当前为
// ==UserScript== // @name Video Popout and No scroll on Click timestamps // @namespace http://tampermonkey.net/ // @version 0.1 // @description Adds a button for watching YouTube videos in picture in picture mode while viewing comments and prevents the page from scrolling up if the user clicks a timestamp in the comments // @author unbeatablemeat. @ discord // @license GPLv3 // @match *://*.youtube.com/watch* // @icon https://cdn-icons-png.flaticon.com/512/1412/1412577.png // @grant none // ==/UserScript== (function() { 'use strict'; var seconds=0; function timestampToSeconds(t){ let parts = t.split(':').reverse(); if (parts.length<2){ return false; } seconds = 0; for(let i=0; i<parts.length; i++){ switch (i) { case 0: seconds += (+parts[i]); break; case 1: seconds += (+parts[i])*60; break; case 2: seconds += (+parts[i])*60*60; break; case 3: seconds += (+parts[i])*60*60*24; break; } } return Number.isInteger(seconds); } document.addEventListener("click", function(e){ if(e.target.tagName=="A"){ if(timestampToSeconds(e.target.innerText)){ e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); movie_player.seekTo(seconds); return; } } else if(e.target.closest("a#endpoint")){/*chapters*/ if(timestampToSeconds(e.target.closest("a#endpoint").querySelector("#details #time").innerText)){ e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); movie_player.seekTo(seconds); return; } } }, {capture: true} ); if ('pictureInPictureEnabled' in document) { const videoElement = document.getElementsByClassName("video-stream")[0]; const pipButtonElement = document.createElement("button"); pipButtonElement.innerHTML = "Pip Mode"; pipButtonElement.style.position = "fixed"; pipButtonElement.style.right = "2rem"; pipButtonElement.style.bottom = "2rem"; pipButtonElement.style.visibility = "hidden"; pipButtonElement.style.width = "10rem"; pipButtonElement.style.height = "3.5rem"; pipButtonElement.style.borderRadius = "10px"; pipButtonElement.style.backgroundColor = "#ff0000"; pipButtonElement.style.border = `1px solid ${pipButtonElement.style.backgroundColor}`; pipButtonElement.style.fontFamily = "Roboto,Arial,sans-serif"; pipButtonElement.style.color = "#f1f1f1"; pipButtonElement.style.cursor = "pointer"; document.body.appendChild(pipButtonElement); const isVideoVisible = (element) => { const rect = element.getBoundingClientRect(); if (rect.top + rect.height > 0 && rect.top < window.innerHeight) { return true; } return false; }; function urlIsYoutubeVideo(currentUrl) { const regex = /(youtu.*be.*)\/(watch\?v=|embed\/|v|shorts|)(.*?((?=[&#?])|$))/; return currentUrl.match(regex); } // Shows the "Pip" button if the main video is scrolled out of view but the user closed the PiP instance videoElement.addEventListener("leavepictureinpicture", (event) => { if (!urlIsYoutubeVideo(window.location.href) && pipButtonElement.style.visibility !== "hidden") { pipButtonElement.style.visibility = "hidden"; } if (!isVideoVisible(videoElement)) { pipButtonElement.style.visibility = "visible"; pipButtonElement.click = null; pipButtonElement.addEventListener("click", async () => { pipButtonElement.disabled = true; try { await videoElement.requestPictureInPicture(); pipButtonElement.style.visibility = "hidden"; } catch (err) { console.log(err) } finally { pipButtonElement.disabled = false; } }); } }); function shouldNotIntercept(navigationEvent) { return ( !navigationEvent.canIntercept || // If this is just a hashChange, // just let the browser handle scrolling to the content. navigationEvent.hashChange || // If this is a download, // let the browser perform the download. navigationEvent.downloadRequest || // If this is a form submission, // let that go to the server. navigationEvent.formData ); } navigation.addEventListener("navigate", async e => { // Needed only when .intercept in called on 'e' ?? if (shouldNotIntercept(e)) return; if (!urlIsYoutubeVideo(e.destination.url) && pipButtonElement.style.visibility !== "hidden") { pipButtonElement.style.visibility = "hidden"; } if (urlIsYoutubeVideo(e.destination.url) && isVideoVisible(videoElement) && pipButtonElement.style.visibility !== "hidden") { pipButtonElement.style.visibility = "hidden"; } if (videoElement === document.pictureInPictureElement && !urlIsYoutubeVideo(e.destination.url)) { await document.exitPictureInPicture(); } }); document.addEventListener("scroll", async () => { if (isVideoVisible(videoElement)) { pipButtonElement.style.visibility = "hidden"; try { if (videoElement === document.pictureInPictureElement) { await document.exitPictureInPicture(); } } catch (err) { console.log(err) } } else { if (videoElement !== document.pictureInPictureElement) { pipButtonElement.style.visibility = "visible"; pipButtonElement.addEventListener("click", async () => { pipButtonElement.disabled = true; try { await videoElement.requestPictureInPicture(); pipButtonElement.style.visibility = "hidden"; } catch (err) { console.log(err) } finally { pipButtonElement.disabled = false; } }); } } }); } else { alert('No support of PIP in Browser'); } })();