您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
隱藏廣告內容,提昇瀏覽體驗。自訂背景顏色,圖片大小調整。當圖片載入失敗時,自動重新載入圖片。提供熱鍵功能:[← 上一頁]、[下一頁 →]、[↑ 自動上滾動]、[↓ 自動下滾動]。當用戶滾動到頁面底部時,自動跳轉到下一頁。
// ==UserScript== // @name ColaManga 瀏覽增強 // @name:zh-TW ColaManga 瀏覽增強 // @name:zh-CN ColaManga 浏览增强 // @name:en ColaManga Browsing Enhance // @version 2025.09.21-Beta // @author Canaan HS // @description 隱藏廣告內容,提昇瀏覽體驗。自訂背景顏色,圖片大小調整。當圖片載入失敗時,自動重新載入圖片。提供熱鍵功能:[← 上一頁]、[下一頁 →]、[↑ 自動上滾動]、[↓ 自動下滾動]。當用戶滾動到頁面底部時,自動跳轉到下一頁。 // @description:zh-TW 隱藏廣告內容,提昇瀏覽體驗。自訂背景顏色,圖片大小調整。當圖片載入失敗時,自動重新載入圖片。提供熱鍵功能:[← 上一頁]、[下一頁 →]、[↑ 自動上滾動]、[↓ 自動下滾動]。當用戶滾動到頁面底部時,自動跳轉到下一頁。 // @description:zh-CN 隐藏广告内容,提昇浏览体验。自定义背景颜色,调整图片大小。当图片载入失败时,自动重新载入图片。提供快捷键功能:[← 上一页]、[下一页 →]、[↑ 自动上滚动]、[↓ 自动下滚动]。当用户滚动到页面底部时,自动跳转到下一页。 // @description:en Hide advertisement content, enhance browsing experience. Customize background color, adjust image size. Automatically reload images when they fail to load. Provide shortcut key functionalities: [← Previous Page], [Next Page →], [↑ Auto Scroll Up], [↓ Auto Scroll Down]. Automatically jump to the next page when users scroll to the bottom of the page. // @match *://www.colamanga.com/manga-*/ // @match *://www.colamanga.com/manga-*/*/*.html // @icon https://www.colamanga.com/favicon.png // @license MPL-2.0 // @namespace https://gf.qytechs.cn/users/989635 // @supportURL https://github.com/Canaan-HS/MonkeyScript/issues // @require https://update.gf.qytechs.cn/scripts/487608/1661432/SyntaxLite_min.js // @grant GM_setValue // @grant GM_getValue // @run-at document-start // ==/UserScript== (function () { /* 臨時的自定義 (當 Enable = false 時, 其餘的設置將無效) */ const Config = { BGColor: { Enable: true, Color: "#595959", }, AutoTurnPage: { // 自動翻頁 Enable: true, Mode: 3, // 1 = 快速 | 2 = 一般無盡 | 3 = 優化無盡 }, RegisterHotkey: { // 快捷功能 Enable: true, Function: { // 移動端不適用以下配置 TurnPage: true, // 翻頁 AutoScroll: true, // 自動滾動 KeepScroll: true, // 換頁繼續滾動 ManualScroll: false, // 手動滾動啟用時, 將會變成點擊一次, 根據視點翻一頁 且 自動滾動會無效 } } }; const Control = { ScrollPixels: 2, WaitPicture: 1e3, BlockListener: new Set(["auxclick", "mousedown", "pointerup", "pointerdown", "dState", "touchstart", "unhandledrejection"]), IdList: { Title: "CME_Title", Iframe: "CME_Iframe", Block: "CME_Block-Ads", Menu: "CME_Menu-Style", Image: "CME_Image-Style", Scroll: "CME_Scroll-Hidden", ChildS: "CME_Child-Scroll-Hidden" } }; const Param = { Body: null, ContentsPage: null, HomePage: null, PreviousLink: null, NextLink: null, MangaList: null, BottomStrip: null, Up_scroll: false, Down_scroll: false, IsFinalPage: false, IsMangaPage: Lib.$url.endsWith("html"), IsMainPage: window.self === window.parent }; (async () => { if (!Param.IsMangaPage) return; Lib.addStyle(` html {pointer-events: none !important;} div[style*='position'] {display: none !important;} .mh_wrap a, .mh_readend a, span.mh_btn:not(.contact), #${Control.IdList.Iframe} { pointer-events: auto !important; } `, Control.IdList.Block); const OriginListener = EventTarget.prototype.addEventListener; const Block = Control.BlockListener; EventTarget.prototype.addEventListener = new Proxy(OriginListener, { apply(target, thisArg, args) { const [type, listener, options] = args; if (Block.has(type)) return; return target.apply(thisArg, args); } }); const iframe = `iframe:not(#${Control.IdList.Iframe})`; const AdCleanup = () => { Lib.$qa(iframe).forEach(ad => ad.remove()); Lib.body?.$qa("script").forEach(ad => ad.remove()); requestIdleCallback(AdCleanup, { timeout: 300 }); }; AdCleanup(); })(); const Tools = (() => { const idWhiteList = new Set(Object.values(Control.IdList)); const storage = (key, value = null) => { return value != null ? Lib.session(key, { value: value }) : Lib.session(key); }; const topDetected = Lib.$throttle(() => { Param.Up_scroll = Lib.sY == 0 ? (storage("scroll", false), false) : true; }, 1e3); const isTheBottom = () => Lib.sY + Lib.iH >= document.documentElement.scrollHeight; const detectSkip = Config.RegisterHotkey.Function.KeepScroll && Config.AutoTurnPage.Mode === 1; const bottomDetected = Lib.$throttle(() => { if (detectSkip) return; Param.Down_scroll = isTheBottom() ? (storage("scroll", false), false) : true; }, 1e3); return { storage: storage, getSet: () => { return Lib.getV("Style", { BG_Color: "#595959", Img_Bw: "auto", Img_Mw: "100%" }); }, getNodes(root) { const nodes = []; function task(root2) { const tree = document.createTreeWalker(root2, NodeFilter.SHOW_ELEMENT, { acceptNode: node => { if (idWhiteList.has(node.id)) { return NodeFilter.FILTER_REJECT; } return NodeFilter.FILTER_ACCEPT; } }); while (tree.nextNode()) { nodes.push(tree.currentNode); } } task(root.head); task(root.body); return nodes; }, autoScroll(move) { requestAnimationFrame(() => { if (Param.Up_scroll && move < 0) { window.scrollBy(0, move); topDetected(); this.autoScroll(move); } else if (Param.Down_scroll && move > 0) { window.scrollBy(0, move); bottomDetected(); this.autoScroll(move); } }); }, manualScroll(move) { window.scrollBy({ left: 0, top: move, behavior: "smooth" }); }, isFinalPage(link) { Param.IsFinalPage = link.startsWith("javascript"); return Param.IsFinalPage; }, visibleObjects: object => object.filter(img => img.height > 0 || img.src), lastObject: object => { const len = object.length; if (len <= 5) return object[0]; if (len <= 10) return object.at(-2) ?? object[0]; return object.at(-3) ?? object[0]; }, detectionValue(object) { return this.visibleObjects(object).length >= Math.floor(object.length * .5); } }; })(); const Style = (() => { const $Set = Tools.getSet(); return { async backgroundStyle(Color = Config.BGColor.Color) { Param.Body.style.cssText = ` background: ${Color} !important; `; document.documentElement.style.cssText = ` overflow: visible !important; `; }, async pictureStyle() { if (Lib.platform === "Desktop") { Lib.addStyle(` .mh_comicpic img { margin: auto; display: block; cursor: pointer; vertical-align: top; width: ${$Set.Img_Bw}; max-width: ${$Set.Img_Mw}; } `, Control.IdList.Image); } setTimeout(() => { const click = new MouseEvent("click", { bubbles: true, cancelable: true }); const observer = new IntersectionObserver(observed => { observed.forEach(entry => { if (entry.isIntersecting) { entry.target.dispatchEvent(click); } }); }, { threshold: .3 }); Param.MangaList.$qa("span.mh_btn:not(.contact):not(.read_page_link)").forEach(reloadBtn => observer.observe(reloadBtn)); }, Control.WaitPicture); }, async menuStyle() { } }; })(); const Hotkey = async () => { let jumpState = false; if (Lib.platform === "Desktop") { const { TurnPage, AutoScroll, KeepScroll, ManualScroll } = Config.RegisterHotkey.Function; if (Param.IsMainPage && KeepScroll && AutoScroll && !ManualScroll) { Param.Down_scroll = Tools.storage("scroll"); Param.Down_scroll && Tools.autoScroll(Control.ScrollPixels); } const UP_ScrollSpeed = -Control.ScrollPixels; const CanScroll = AutoScroll || ManualScroll; Lib.onEvent(window, "keydown", event => { const key = event.key; if (key === "ArrowLeft" && TurnPage && !jumpState) { event.stopImmediatePropagation(); jumpState = !Tools.isFinalPage(Param.PreviousLink); location.assign(Param.PreviousLink); } else if (key === "ArrowRight" && TurnPage && !jumpState) { event.stopImmediatePropagation(); jumpState = !Tools.isFinalPage(Param.NextLink); location.assign(Param.NextLink); } else if (key === "ArrowUp" && CanScroll) { event.stopImmediatePropagation(); event.preventDefault(); if (ManualScroll) { Tools.manualScroll(-Lib.iH); } else { if (Param.Up_scroll) { Param.Up_scroll = false; } else if (!Param.Up_scroll || Param.Down_scroll) { Param.Down_scroll = false; Param.Up_scroll = true; Tools.autoScroll(UP_ScrollSpeed); } } } else if (key === "ArrowDown" && CanScroll) { event.stopImmediatePropagation(); event.preventDefault(); if (ManualScroll) { Tools.manualScroll(Lib.iH); } else { if (Param.Down_scroll) { Param.Down_scroll = false; Tools.storage("scroll", false); } else if (Param.Up_scroll || !Param.Down_scroll) { Param.Up_scroll = false; Param.Down_scroll = true; Tools.storage("scroll", true); Tools.autoScroll(Control.ScrollPixels); } } } }, { capture: true }); } else if (Lib.platform === "Mobile") { let startX, startY, moveX, moveY; const sidelineX = Lib.iW * .3; const sidelineY = Lib.iH / 4 * .3; Lib.onEvent(window, "touchstart", event => { startX = event.touches[0].clientX; startY = event.touches[0].clientY; }, { passive: true }); Lib.onEvent(window, "touchmove", Lib.$debounce(event => { moveY = event.touches[0].clientY - startY; if (Math.abs(moveY) < sidelineY) { moveX = event.touches[0].clientX - startX; if (moveX > sidelineX && !jumpState) { jumpState = !Tools.isFinalPage(Param.PreviousLink); location.assign(Param.PreviousLink); } else if (moveX < -sidelineX && !jumpState) { jumpState = !Tools.isFinalPage(Param.NextLink); location.assign(Param.NextLink); } } }, 60), { passive: true }); } }; const PageTurn = async () => { const turnMode = Config.AutoTurnPage.Mode; const optimized = turnMode === 3; async function unlimited() { Lib.addStyle(` .mh_wrap, .mh_readend, .mh_footpager, .fed-foot-info, #imgvalidation2022 {display: none;} body { margin: 0; padding: 0; } #${Control.IdList.Iframe} { margin: 0; padding: 0; width: 100%; height: 110vh; border: none; } `, Control.IdList.Scroll); const stylelRules = Lib.$q(`#${Control.IdList.Scroll}`).sheet.cssRules; if (Param.IsMainPage) { let size = 0; Lib.onEvent(window, "message", event => { const data = event.data; if (data && data.length > 0) { const { Title, PreviousUrl, CurrentUrl, NextUrl, Resize, SizeSet, SizeRecord } = data[0]; if (Resize) { if (size > SizeRecord) size -= SizeRecord; size += Resize; stylelRules[2].style.height = `${size}px`; } else if (SizeSet) stylelRules[2].style.height = `${SizeSet}px`; else if (Title && NextUrl && PreviousUrl && CurrentUrl) { document.title = Title; Param.NextLink = NextUrl; Param.PreviousLink = PreviousUrl; history.pushState(null, null, CurrentUrl); } } }); } else { Lib.addStyle(` html { overflow: hidden !important; overflow-x: hidden !important; scrollbar-width: none !important; -ms-overflow-style: none !important; } html::-webkit-scrollbar { display: none !important; } `, Control.IdList.ChildS); let mainWindow = window; Lib.onEvent(window, "message", event => { while (mainWindow.parent !== mainWindow) { mainWindow = mainWindow.parent; } mainWindow.postMessage(event.data, Lib.$origin); }); } const iframe = Lib.createElement("iframe", { id: Control.IdList.Iframe, src: Param.NextLink }); (async () => { let img, Observer, quantity = 0; const observerNext = new IntersectionObserver(observed => { observed.forEach(entry => { const rect = entry.boundingClientRect; const isPastTarget = rect.bottom < 0; const isIntersecting = entry.isIntersecting; if ((isIntersecting || isPastTarget) && Tools.detectionValue(img)) { observerNext.disconnect(); Observer.disconnect(); turnPage(); } }); }, { threshold: [0, .1, .5], rootMargin: "0px 0px 200px 0px" }); setTimeout(() => { img = Param.MangaList.$qa("img"); if (img.length <= 5) { turnPage(); return; } const lastImg = Tools.lastObject(Tools.visibleObjects(img)); lastImg instanceof Element && observerNext.observe(lastImg); Lib.$observer(Param.MangaList, () => { const visible = Tools.visibleObjects(img); const vlen = visible.length; if (vlen > quantity) { quantity = vlen; const lastImg2 = Tools.lastObject(visible); if (lastImg2 instanceof Element) { observerNext.disconnect(); observerNext.observe(lastImg2); } } }, { debounce: 100, attributeFilter: ["src"] }, observer => { Observer = observer.ob; }); }, Control.WaitPicture); })(); let turned = false; function turnPage() { if (turned) return; turned = true; let currentHeight = 0; const resizeObserver = new ResizeObserver(() => { if (!Param.MangaList.isConnected) { resizeObserver.disconnect(); return; } const newHeight = Param.MangaList.offsetHeight; if (newHeight > currentHeight) { window.parent.postMessage([{ Resize: newHeight, SizeRecord: currentHeight }], Lib.$origin); currentHeight = newHeight; } }); if (Tools.isFinalPage(Param.NextLink)) { if (optimized) { window.parent.postMessage([{ SizeSet: Param.MangaList.offsetHeight + 245 }], Lib.$origin); } stylelRules[0].style.display = "block"; return; } waitLoad(); Param.Body.appendChild(iframe); resizeObserver.observe(Param.MangaList); function waitLoad() { let iframeWindow, currentUrl, content, allImg; const failed = () => { iframe.offAll(); iframe.src = ""; setTimeout(() => { iframe.src = Param.NextLink; waitLoad(); }); }; const success = () => { iframe.offAll(); iframeWindow = iframe.contentWindow; currentUrl = iframeWindow.location.href; if (currentUrl !== Param.NextLink) { failed(); return; } content = iframeWindow.document; content.body.style.overflow = "hidden"; Lib.log(currentUrl, { group: "無盡翻頁" }); allImg = content.$qa("#mangalist img"); const urlUpdate = new IntersectionObserver(observed => { observed.forEach(entry => { if (entry.isIntersecting) { urlUpdate.disconnect(); const PageLink = content.body.$qa("div.mh_readend ul a"); window.parent.postMessage([{ Title: content.title, CurrentUrl: currentUrl, PreviousUrl: PageLink[0]?.href, NextUrl: PageLink[2]?.href }], Lib.$origin); } }); }, { threshold: 0 }); allImg.forEach(img => urlUpdate.observe(img)); if (optimized) { Lib.$q("title").id = Control.IdList.Title; const adapt = Lib.platform === "Desktop" ? .5 : .7; const releaseMemory = new IntersectionObserver(observed => { observed.forEach(entry => { if (entry.isIntersecting) { const targetImg = entry.target; const ratio = Math.min(adapt, Lib.iH * adapt / targetImg.clientHeight); if (entry.intersectionRatio >= ratio) { releaseMemory.disconnect(); Tools.getNodes(document).forEach(node => { node.remove(); }); targetImg.scrollIntoView(); } } }); }, { threshold: [0, .5, 1] }); allImg.forEach(img => releaseMemory.observe(img)); } }; iframe.on("load", success); iframe.on("error", failed); } } } switch (turnMode) { case 2: case 3: unlimited(); break; default: setTimeout(() => { const img = Param.MangaList.$qa("img"); if (!Tools.isFinalPage(Param.NextLink)) { const observerNext = new IntersectionObserver(observed => { observed.forEach(entry => { if (entry.isIntersecting && Tools.detectionValue(img)) { observerNext.disconnect(); location.assign(Param.NextLink); } }); }, { threshold: 1 }); observerNext.observe(Param.BottomStrip); } }, Control.WaitPicture); } }; function Main(raf = void 0) { async function mangaPageInit(callback) { Lib.waitEl(["body", "div.mh_readtitle", "div.mh_headpager", "div.mh_readend", "#mangalist"], null, { raf: raf, throttle: 30, timeout: 10, visibility: Param.IsMainPage, timeoutResult: true }).then(([Body, Title, HeadPager, Readend, Manga]) => { Param.Body = Body; const HomeLink = Title.$qa("a"); Param.ContentsPage = HomeLink[0].href; Param.HomePage = HomeLink[1].href; try { const PageLink = Readend.$qa("ul a"); Param.PreviousLink = PageLink[0].href; Param.NextLink = PageLink[2].href; } catch { const PageLink = HeadPager.$qa("a.mh_btn:not(.mh_bgcolor)"); Param.PreviousLink = PageLink[0].href; Param.NextLink = PageLink[1].href; } Param.MangaList = Manga; Param.BottomStrip = Readend.$q(".endtip2"); if ([Param.Body, Param.ContentsPage, Param.HomePage, Param.PreviousLink, Param.NextLink, Param.MangaList, Param.BottomStrip].every(Check => Check)) callback(true); else callback(false); }); } async function contentsPageInit() { Lib.waitEl([".all_data_list", ".website-display-all"], ([list, display]) => { if (list.style.height === "auto") return; display.click(); }, { raf: raf }); } try { if (Param.IsMangaPage) { mangaPageInit(state => { if (state) { Style.pictureStyle(); Config.BGColor.Enable && Style.backgroundStyle(); Config.AutoTurnPage.Enable && PageTurn(); Config.RegisterHotkey.Enable && Hotkey(); } else { Lib.log("Manga Page Init Error").error; setTimeout(() => Main(true), 1e3); } }); } else contentsPageInit(); } catch (error) { Lib.log(error).error; } } Main(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址