您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Prev, Next button for player on animego.org
// ==UserScript== // @name AnimeGo Prev Next player // @name:ru AnimeGo След. Пред. кнопки для проигрывателя // @namespace http://tampermonkey.net/ // @version 0.5.2 // @description Prev, Next button for player on animego.org // @description:ru След., Пред. кнопки для проигрывателя на animego.org. // @author You // @match https://animego.org/** // @icon https://www.google.com/s2/favicons?sz=64&domain=animego.org // @grant none // @license MIT // ==/UserScript== const VIDEO_SELECTOR = ".video-player-main"; const SERIES_SELECTOR = "select[name='series']"; const $ = selector => document.querySelector(selector); const seriesElem = $(SERIES_SELECTOR); const posterImg = $(".anime-poster img"); const fullScreenButton = { width: 150, height: 80, offset: 5 }; function inRange(x, min, max) { return (x - min) * (x - max) <= 0; } function waitForElm(selector) { return new Promise(resolve => { if ($(selector)) { return resolve($(selector)); } const observer = new MutationObserver(mutations => { if ($(selector)) { resolve($(selector)); observer.disconnect(); } }); observer.observe(document, { attributeFilter: ["aria-hidden", "data-focus-method"], childList: true, subtree: true }); }); } const appendFixStyle = player => { const tStyle = document.querySelector("style"); tStyle.innerHTML = ` #video-carousel { display: flex !important; } .tns-liveregion.tns-visually-hidden { display: none; } .video-player .owl-nav, .video-player .tns-controls { background: #383838; z-index: 9; } .video-player-online.position-relative iframe::backdrop { position: absolute; left: 0; top: 0; width: 0; height: 0; } `; player.appendChild(tStyle); }; const changeSeries = series => { $('.video-player-bar-series-list [data-id="' + series + '"]').click(); }; const getOptionInfo = option => { if (!option) return undefined; return { value: option.value, text: `<span>${option.textContent}</span>` }; }; const getPrevNextSeries = seriesElem => { const selected = seriesElem.value; const options = Array.from(seriesElem.querySelectorAll("option")); const values = options.map(option => option.value); const selectedIndex = values.indexOf(selected); const prev = getOptionInfo(options[selectedIndex - 1]) || undefined; const next = getOptionInfo(options[selectedIndex + 1]) || undefined; return { prev, next }; }; const elementExist = element => typeof element != "undefined" && element != null; const removeElement = element => { if (elementExist(element)) { element.parentNode.removeChild(element); } }; class Default { constructor({ seriesElem, player }) { this.seriesElem = seriesElem; this.player = player; this.updButtons = this.updButtons.bind(this); this.getPrevButton = this.getPrevButton.bind(this); this.getNextButton = this.getNextButton.bind(this); this.appendStyle = this.appendStyle.bind(this); this.switchToPrev = this.switchToPrev.bind(this); this.switchToNext = this.switchToNext.bind(this); this.createContainer = this.createContainer.bind(this); this.handleFullScreenButtons = this.handleOnMessages.bind(this); this.handleSelectChange = this.handleSelectChange.bind(this); this.addListeners = this.addListeners.bind(this); this.createContainer(); this.handleOnMessages(); this.handleSelectChange(); this.addListeners(); } addListeners() { document.addEventListener('keypress', (evt) => { const nextKeys = ['n', 'N', 'т', 'T'] if (nextKeys.includes(evt.key)) { this.switchToNext(); } const prevKeys = ['p', 'P', 'з', 'З'] if (prevKeys.includes(evt.key)) { this.switchToPrev(); } }) } switchToPrev() { const { prev } = getPrevNextSeries(this.seriesElem); changeSeries(prev.value); this.updButtons(); } switchToNext() { const { next } = getPrevNextSeries(this.seriesElem); changeSeries(next.value); this.updButtons(); } updButtons() { const { prev, next } = getPrevNextSeries(this.seriesElem); const container = $(".pn-container"); const prevElem = container.querySelector(".pn-prev"); const nextElem = container.querySelector(".pn-next"); if (prev) { if (!elementExist(prevElem)) { const prevElemNew = this.getPrevButton(); container.appendChild(prevElemNew); } else { prevElem.innerHTML = prev.text; } } else { removeElement(prevElem); } if (next) { if (!elementExist(nextElem)) { const nextElemNew = this.getNextButton(); container.appendChild(nextElemNew); } else { nextElem.innerHTML = next.text; } } else { removeElement(nextElem); } } getPrevButton() { const { prev } = getPrevNextSeries(this.seriesElem); if (prev) { const prevElem = document.createElement("button"); const posterImgSrc = posterImg.src; prevElem.style.backgroundImage = `url(${posterImgSrc})`; prevElem.innerHTML = prev.text; prevElem.classList.add("pn-button"); prevElem.classList.add("pn-prev"); prevElem.addEventListener("click", () => { this.switchToPrev(); }); return prevElem; } return undefined; } getNextButton() { const { next } = getPrevNextSeries(this.seriesElem); if (next) { const nextElem = document.createElement("button"); const posterImgSrc = posterImg.src; nextElem.style.backgroundImage = `url(${posterImgSrc})`; nextElem.innerHTML = next.text; nextElem.classList.add("pn-button"); nextElem.classList.add("pn-next"); nextElem.addEventListener("click", () => { this.switchToNext(); }); return nextElem; } return undefined; } appendStyle() { const tStyle = document.querySelector("style"); tStyle.innerHTML = ` .pn-button { position: absolute; top: calc(50%); outline: unset; border: 2px solid #fff; color: #fff; font-size: 16px; cursor: pointer; padding: 10px 20px; min-width: 150px; min-height: 60px; background: rgba(0, 0, 0, 0.2); border-radius: 3px; transition: all 0.3s; z-index: 10; box-shadow: rgb(255 255 255 / 0%) 0px 0px 10px; opacity: 0.1; background-position: center; background-size: cover; perspective: 1000px; perspective-origin: 50% 50%; transform: translate(0, -50%); display: flex; flex-direction: column; align-content: center; justify-content: center; align-items: center; & > span { margin-top: 4px; background: rgba(0, 0, 0, 0.8); padding: 2px 10px; border-radius: 3px; } &:after { display: flex; border: 1px solid white; border-radius: 3px; width: 32px; box-shadow: 0px 8px 12px #000; margin-top: 4px; text-shadow: 2px 2px rgba(0, 0, 0, 0.2); background: rgba(0, 0, 0, 0.8); align-content: center; justify-content: center; } } .pn-button:hover { opacity: 1; box-shadow: rgb(255 255 255 / 50%) 0px 0px 10px; &:after { animation: scale 1s linear infinite; } } .pn-button:hover,.pn-button:focus { outline: unset; } .pn-prev { left: 5px; &:after{ content: "P"; } } .pn-prev:hover { animation: scroll-to-bottom 100s linear infinite; } .pn-next { right: 5px; &:after{ content: "N"; } } .pn-next:hover { animation: scroll-to-top 100s linear infinite; } @keyframes scroll-to-top { 100%{ background-position: 0px -3000px; } } @keyframes scroll-to-bottom { 100%{ background-position: 0px 3000px; } } @keyframes scale { 0% { scale: 1 } 100%{ scale: 0.95 } } `; this.player.appendChild(tStyle); } createContainer() { const pnContainer = document.createElement("DIV"); pnContainer.classList.add("pn-container"); const prev = this.getPrevButton(); if (prev) pnContainer.appendChild(prev); const next = this.getNextButton(); if (next) pnContainer.appendChild(next); this.appendStyle(); this.player.insertBefore(pnContainer, this.player.firstChild); } handleOnMessages() { window.onmessage = event => { if (document.fullscreenElement) { if (event.data.title === "click") { const { height, width } = window.screen; const { clientX, clientY } = event.data.data; const targetCoords = { y: [ height / 2 - fullScreenButton.height / 2, height / 2 + fullScreenButton.height / 2 ], prevX: [0, fullScreenButton.width + fullScreenButton.offset], nextX: [ width - (fullScreenButton.width + fullScreenButton.offset), width ] }; const isPrevButton = inRange(clientX, targetCoords.prevX[0], targetCoords.prevX[1]) && inRange(clientY, targetCoords.y[0], targetCoords.y[1]); const isNextButton = inRange(clientX, targetCoords.nextX[0], targetCoords.nextX[1]) && inRange(clientY, targetCoords.y[0], targetCoords.y[1]); if (isPrevButton) { this.switchToPrev(); } if (isNextButton) { this.switchToNext(); } } } if (event.data.title === "keydown") { console.log(event); } }; } handleSelectChange() { // This code looks like a HACK // Default select change does'nt work correctly // This code now work correctly! var element = document.querySelector(".video-player-bar-series-watch"); var observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.attributeName === "data-watched-id") { setTimeout(() => { this.updButtons(); }, 100); } }); }); observer.observe(element, { attributes: true }); } } waitForElm(VIDEO_SELECTOR).then(player => { waitForElm(SERIES_SELECTOR).then(seriesElem => { waitForElm(".video-player-main iframe").then(() => { new Default({ seriesElem, player }); appendFixStyle(document.body); }); }); });