您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Adds button for loading the previous video in a YT playlist
当前为
// ==UserScript== // @name Play Youtube playlist in reverse order // @namespace https://github.com/Dragosarus/ // @version 1.0 // @description Adds button for loading the previous video in a YT playlist // @author Dragosarus // @match www.youtube.com/watch?*list* // @grant none // @require http://code.jquery.com/jquery-latest.js // ==/UserScript== // Cookies (current session): // pytplir_playPrevious - saves the button state between loads (function() { 'use strict'; // Your code here... $(document).ready(function() { var activeColor = "rgb(64,166,255)"; var inactiveColor = "rgb(144,144,144)"; var player; var arrow_up; var arrow_down; var playPrevious; var btn_svg; var redirectFlag = false; // remove the need to refresh the page for the script to work properly $("html")[0].addEventListener("yt-navigate-finish",init); $("html")[0].addEventListener("yt-navigate-start",removeButton); init(); function init() { playPrevious = getCookie("pytplir_playPrevious"); if (playPrevious === "") { // cookie has not been set yet playPrevious = false; // inital state setCookie("pytplir_playPrevious",playPrevious); } // create button arrow_up = document.createElementNS("http://www.w3.org/2000/svg","polygon"); arrow_down = document.createElementNS("http://www.w3.org/2000/svg","polygon"); btn_svg = document.createElementNS("http://www.w3.org/2000/svg","svg"); arrow_up.setAttribute("points","26,19 26,17 22,17 29,11 36,17 32,17 32,19"); arrow_up.addEventListener("click",onButtonClick); arrow_down.setAttribute("points","26,20 26,22 22,22 29,28 36,22 32,22 32,20"); arrow_down.addEventListener("click",onButtonClick); btn_svg.setAttribute("viewbox","0 0 40 40"); btn_svg.setAttribute("xmlns","http://www.w3.org/2000/svg"); btn_svg.setAttribute("width","50"); btn_svg.setAttribute("height","40"); btn_svg.setAttribute("id","plst-rev-btn"); btn_svg.appendChild(arrow_up); btn_svg.appendChild(arrow_down); setTimeout(addButton, 500); setTimeout(start, 500); } function onButtonClick() { // toggle playPrevious = !playPrevious; setCookie("pytplir_playPrevious",playPrevious); updateButtonState(); } function addButton() { withQuery(".ytd-playlist-panel-renderer > #top-level-buttons", function(res) { if (!document.getElementById("plst-rev-btn")) { res[0].appendChild(btn_svg); updateButtonState(); } }); } function updateButtonState() { if (playPrevious) { // play previous video arrow_up.setAttribute("style","fill:"+activeColor); arrow_down.setAttribute("style","fill:"+inactiveColor); } else { // play next video arrow_up.setAttribute("style","fill:"+inactiveColor); arrow_down.setAttribute("style","fill:"+activeColor); } } function removeButton() { btn_svg.parentNode.removeChild(btn_svg); } function start() { withQuery(".html5-main-video", function(res) { player = res[0]; player.addEventListener("timeupdate",checkTime); }); } function withQuery(query, onSuccess) { var res = $(query); if (res) { onSuccess(res); return res; } else { // not loaded yet => retry setTimeout(function(){withQuery(query);}, 100); } } function checkTime() { var timeLeft = player.duration - player.currentTime; if (playPrevious && timeLeft < 1.3 && !redirectFlag && !player.hasAttribute("loop")) { redirectFlag = true; redirect(); setTimeout(function() {redirectFlag = false;}, 1000); } } function redirect() { var previousURL = getPreviousURL(); if (previousURL) { document.location.href = previousURL; } else { // probably at start of playlist player.pause(); // prevent next video from loading } } function getPreviousURL(){ var query = document.querySelectorAll("#playlist-items"); var index; var previousURL; for (const a of Array.from(query).entries()) { // a = {index, element} if (a[1].textContent.includes("▶")) { // Current video's position in playlist index = a[0]; // index in query if (index == 0) {break;} // start of list previousURL = query[index-1].children[0].href; return previousURL; } } } // adapted from https://www.w3schools.com/js/js_cookies.asp function setCookie(cname, cvalue) { document.cookie = cname + "=" + cvalue + ";sameSite=lax;path=www.youtube.com/watch"; } function getCookie(cname) { var name = cname + "="; var decodedCookie = decodeURIComponent(document.cookie); var ca = decodedCookie.split(';'); for(var i = 0; i <ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { var x = c.substring(name.length, c.length); return ((x.toLowerCase() == "true") ? true : false); } } return ""; } }); })();