- 新增 isLeafletDescendant 輔助函式,統一所有清理流程的地圖元素豁免邏輯 - 加入 popup / pane 內容保護 CSS,避免被廣告清除規則誤殺 - 移除 popup 預設的白色三角 tip,wrapper 改用自訂 padding 控制上下留白 - MutationObserver 略過 Leaflet 後代節點變動,避免點 marker 時誤觸發清理 - 版本 1.1.7 → 1.1.15 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
721 lines
26 KiB
JavaScript
721 lines
26 KiB
JavaScript
// ==UserScript==
|
||
// @name TWPKInfo 廣告清除器
|
||
// @namespace http://tampermonkey.net/
|
||
// @version 1.1.15
|
||
// @description 移除頂部導覽列、底部功能列與空白列,保留地圖工具
|
||
// @author AdBlocker
|
||
// @match https://twpkinfo.com/*
|
||
// @match https://*.twpkinfo.com/*
|
||
// @grant none
|
||
// @run-at document-start
|
||
// @license MIT
|
||
// ==/UserScript==
|
||
|
||
(function() {
|
||
'use strict';
|
||
|
||
console.log('TWPKInfo 廣告清除器啟動');
|
||
|
||
let cleanupStarted = false;
|
||
let tooltipTimer = null;
|
||
|
||
// 判斷元素是否屬於 Leaflet 地圖/彈窗系統(清理時必須跳過)
|
||
function isLeafletDescendant(element) {
|
||
if (!element || !element.closest) {
|
||
return false;
|
||
}
|
||
return Boolean(
|
||
element.closest('#map') ||
|
||
element.closest('.leaflet-container') ||
|
||
element.closest('.leaflet-pane') ||
|
||
element.closest('.leaflet-popup') ||
|
||
element.closest('.leaflet-tooltip') ||
|
||
element.closest('.leaflet-control')
|
||
);
|
||
}
|
||
|
||
// 清理用 CSS
|
||
function addCleanupCSS() {
|
||
if (document.getElementById('twpk-ad-blocker-cleanup')) {
|
||
return;
|
||
}
|
||
|
||
const styleRoot = document.head || document.documentElement;
|
||
if (!styleRoot) {
|
||
setTimeout(addCleanupCSS, 0);
|
||
return;
|
||
}
|
||
|
||
const style = document.createElement('style');
|
||
style.id = 'twpk-ad-blocker-cleanup';
|
||
style.textContent = `
|
||
/* 移除 Google AdSense */
|
||
.adsbygoogle,
|
||
ins.adsbygoogle,
|
||
[data-ad-client],
|
||
[data-ad-slot] {
|
||
display: none !important;
|
||
}
|
||
|
||
html,
|
||
body {
|
||
margin: 0 !important;
|
||
padding: 0 !important;
|
||
width: 100% !important;
|
||
height: 100% !important;
|
||
min-height: 100vh !important;
|
||
overflow: hidden !important;
|
||
background: transparent !important;
|
||
}
|
||
|
||
/* 移除頂部標題列 */
|
||
body > div:first-child:not(#map):not([class*="leaflet"]) {
|
||
display: none !important;
|
||
visibility: hidden !important;
|
||
height: 0 !important;
|
||
min-height: 0 !important;
|
||
overflow: hidden !important;
|
||
}
|
||
|
||
body > div:has(> h1),
|
||
body > div:has(> h2),
|
||
body > div:has(> h3),
|
||
body > div:has(> ins.adsbygoogle) {
|
||
display: none !important;
|
||
visibility: hidden !important;
|
||
height: 0 !important;
|
||
min-height: 0 !important;
|
||
overflow: hidden !important;
|
||
}
|
||
|
||
/* 移除 igym.aspx 的頂部網站導覽列 */
|
||
#myheader,
|
||
#myheader > .navbar,
|
||
nav.navbar.main-menu,
|
||
nav.navbar-fixed-top,
|
||
body > nav.navbar,
|
||
body > .navbar,
|
||
body > [class*="navbar"] {
|
||
display: none !important;
|
||
visibility: hidden !important;
|
||
height: 0 !important;
|
||
min-height: 0 !important;
|
||
overflow: hidden !important;
|
||
}
|
||
|
||
/* 移除底部功能列 */
|
||
#div_close_cf,
|
||
body > div[style*="position"][style*="bottom"],
|
||
body > div[style*="z-index"][style*="bottom"]:not(.leaflet-control-attribution),
|
||
div[style*="position: fixed; bottom"],
|
||
div[style*="position: absolute; bottom"],
|
||
div[style*="bottom: 0"]:not(.leaflet-control-attribution):not([class*="leaflet"]) {
|
||
display: none !important;
|
||
}
|
||
|
||
/* 移除特定結構的底部列 */
|
||
body > div:last-child:not(#map):not([id*="map"]):not([class*="leaflet"]):not(.leaflet-control-attribution) {
|
||
display: none !important;
|
||
}
|
||
|
||
/* 強制隱藏常見的底部導航類名 */
|
||
.bottom-nav,
|
||
.bottom-bar,
|
||
.footer-nav,
|
||
.nav-bottom,
|
||
.bottom-menu,
|
||
.bottom-toolbar,
|
||
[class*="bottom"][class*="nav"],
|
||
[class*="bottom"][class*="bar"],
|
||
[class*="bottom"][class*="menu"]:not([class*="pokemon"]) {
|
||
display: none !important;
|
||
visibility: hidden !important;
|
||
height: 0 !important;
|
||
overflow: hidden !important;
|
||
}
|
||
|
||
/* 確保重要元素可見 */
|
||
#map,
|
||
.leaflet-container,
|
||
.leaflet-control-attribution,
|
||
[class*="pokemon"],
|
||
[class*="sidebar"]:not([class*="bottom"]),
|
||
[class*="panel"]:not([class*="bottom"]),
|
||
[class*="menu"]:not([class*="bottom"]) {
|
||
display: block !important;
|
||
visibility: visible !important;
|
||
}
|
||
|
||
/* 保護 Leaflet 彈出視窗(popup)所有內容,避免被廣告清除規則誤殺 */
|
||
html body .leaflet-pane,
|
||
html body .leaflet-pane *,
|
||
html body .leaflet-popup,
|
||
html body .leaflet-popup * {
|
||
visibility: visible !important;
|
||
opacity: 1 !important;
|
||
}
|
||
|
||
/* 只強制 popup 內文(rows)的顯示,避免被 display:none 規則蓋掉;
|
||
不再覆寫 .leaflet-popup / .leaflet-popup-content-wrapper / tip 容器尺寸,
|
||
讓 TWPKInfo 與 Leaflet 自身的排版(含底部 tip 三角)正常運作 */
|
||
html body .leaflet-popup-content > *,
|
||
html body .leaflet-popup-content > * > *,
|
||
html body .leaflet-popup-content > * > * > *,
|
||
html body .leaflet-popup-content > * > * > * > * {
|
||
display: revert !important;
|
||
height: auto !important;
|
||
min-height: 0 !important;
|
||
max-height: none !important;
|
||
overflow: visible !important;
|
||
}
|
||
|
||
/* 把 Leaflet popup 預設的白色三角 tip 拿掉,並把 wrapper 改成自己控制留白 */
|
||
html body .leaflet-popup-content-wrapper {
|
||
overflow: hidden !important;
|
||
border-radius: 12px !important;
|
||
padding: 14px 4px !important;
|
||
}
|
||
|
||
/* 內層 content margin 歸零,全部交給 wrapper 的 padding 負責 */
|
||
html body .leaflet-popup-content {
|
||
margin: 0 14px !important;
|
||
}
|
||
|
||
html body .leaflet-popup-tip-container,
|
||
html body .leaflet-popup-tip,
|
||
html body [class*="leaflet-popup-tip"] {
|
||
display: none !important;
|
||
}
|
||
|
||
#map,
|
||
.leaflet-container {
|
||
top: 0 !important;
|
||
width: 100vw !important;
|
||
height: 100vh !important;
|
||
min-height: 100vh !important;
|
||
}
|
||
|
||
[data-twpk-tooltip] {
|
||
position: relative !important;
|
||
}
|
||
|
||
[data-twpk-tooltip]::after {
|
||
content: attr(data-twpk-tooltip);
|
||
position: absolute;
|
||
top: 50%;
|
||
left: calc(100% + 10px);
|
||
transform: translateY(-50%);
|
||
z-index: 2147483647;
|
||
display: block;
|
||
max-width: 220px;
|
||
padding: 6px 9px;
|
||
border-radius: 4px;
|
||
background: rgba(20, 20, 20, 0.9);
|
||
color: #fff;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
line-height: 1.35;
|
||
letter-spacing: 0;
|
||
text-align: left;
|
||
white-space: nowrap;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.24);
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
pointer-events: none;
|
||
transition: opacity 120ms ease, visibility 120ms ease;
|
||
}
|
||
|
||
[data-twpk-tooltip]::before {
|
||
content: "";
|
||
position: absolute;
|
||
top: 50%;
|
||
left: calc(100% + 4px);
|
||
transform: translateY(-50%);
|
||
z-index: 2147483647;
|
||
border: 6px solid transparent;
|
||
border-right-color: rgba(20, 20, 20, 0.9);
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
pointer-events: none;
|
||
transition: opacity 120ms ease, visibility 120ms ease;
|
||
}
|
||
|
||
[data-twpk-tooltip]:hover::after,
|
||
[data-twpk-tooltip]:hover::before,
|
||
[data-twpk-tooltip]:focus::after,
|
||
[data-twpk-tooltip]:focus::before,
|
||
[data-twpk-tooltip]:focus-within::after,
|
||
[data-twpk-tooltip]:focus-within::before {
|
||
opacity: 1;
|
||
visibility: visible;
|
||
}
|
||
|
||
[data-twpk-tooltip-side="left"]::after {
|
||
right: calc(100% + 10px);
|
||
left: auto;
|
||
}
|
||
|
||
[data-twpk-tooltip-side="left"]::before {
|
||
right: calc(100% + 4px);
|
||
left: auto;
|
||
border-right-color: transparent;
|
||
border-left-color: rgba(20, 20, 20, 0.9);
|
||
}
|
||
`;
|
||
styleRoot.appendChild(style);
|
||
console.log('清理 CSS 規則已應用');
|
||
}
|
||
|
||
// 讓移除底部列後的 Leaflet 地圖重新吃滿視窗
|
||
function resizeMapToViewport() {
|
||
const mapElement = document.getElementById('map');
|
||
if (mapElement) {
|
||
mapElement.style.width = '100vw';
|
||
mapElement.style.height = '100vh';
|
||
mapElement.style.minHeight = '100vh';
|
||
}
|
||
|
||
window.requestAnimationFrame(() => {
|
||
window.dispatchEvent(new Event('resize'));
|
||
|
||
if (window.map && typeof window.map.invalidateSize === 'function') {
|
||
window.map.invalidateSize(false);
|
||
}
|
||
});
|
||
}
|
||
|
||
function setToolbarTooltip(element, label) {
|
||
if (!element || element.closest('#map .leaflet-pane')) {
|
||
return;
|
||
}
|
||
|
||
const labeledParent = element.parentElement && element.parentElement.closest('[data-twpk-tooltip]');
|
||
if (!labeledParent || labeledParent === element) {
|
||
element.setAttribute('data-twpk-tooltip', label);
|
||
}
|
||
|
||
element.setAttribute('title', label);
|
||
element.setAttribute('aria-label', label);
|
||
updateTooltipSide(element);
|
||
}
|
||
|
||
function updateTooltipSide(element) {
|
||
const rect = element.getBoundingClientRect();
|
||
const label = element.getAttribute('data-twpk-tooltip') || element.getAttribute('title') || '';
|
||
const estimatedWidth = Math.min(Math.max(label.length * 14 + 18, 90), 220);
|
||
|
||
if (rect.right + estimatedWidth + 18 > window.innerWidth) {
|
||
element.setAttribute('data-twpk-tooltip-side', 'left');
|
||
} else {
|
||
element.removeAttribute('data-twpk-tooltip-side');
|
||
}
|
||
}
|
||
|
||
function applyToolbarTooltips() {
|
||
const directTooltips = [
|
||
['#update', '重新整理地圖資料'],
|
||
['#filter_btn', '開啟/關閉篩選面板'],
|
||
['#filter_bGYM', '切換道館/補給站顯示'],
|
||
['#gym', '切換到道館地圖'],
|
||
['#ipoke', '切換到寶可夢地圖'],
|
||
['#iquest', '切換到任務地圖'],
|
||
['#generation', '切換寶可夢世代顯示'],
|
||
['#a_iquest', '切換到任務地圖'],
|
||
['#quest_img', '切換到任務地圖'],
|
||
['.leaflet-control a[href*="iquest"]', '切換到任務地圖'],
|
||
['.leaflet-control a[href*="igym"]', '切換到道館地圖'],
|
||
['.leaflet-control a[href*="ipoke"]', '切換到寶可夢地圖'],
|
||
['.leaflet-control-locate a', '定位到我的位置'],
|
||
['.leaflet-control a[title*="Location"]', '定位到我的位置'],
|
||
['.leaflet-control a[title*="位置"]', '定位到我的位置'],
|
||
['.leaflet-control-zoom-in', '放大地圖'],
|
||
['.leaflet-control-zoom-out', '縮小地圖']
|
||
];
|
||
|
||
directTooltips.forEach(([selector, label]) => {
|
||
document.querySelectorAll(selector).forEach(element => {
|
||
setToolbarTooltip(element, label);
|
||
});
|
||
});
|
||
|
||
const imageTooltips = [
|
||
['img[src*="GYMgo"]', '切換到道館地圖'],
|
||
['img[src*="ipoke"]', '切換到寶可夢地圖'],
|
||
['img[src*="quest"]', '切換到任務地圖'],
|
||
['img[src*="Quest"]', '切換到任務地圖'],
|
||
['img[src*="iquest"]', '切換到任務地圖'],
|
||
['img[src*="target"]', '定位/移到目前位置'],
|
||
['img[src*="radar"]', '定位/移到目前位置'],
|
||
['img[src*="locat"]', '定位/移到目前位置'],
|
||
['img[src*="gps"]', '定位/移到目前位置'],
|
||
['img[src*="blue"]', '定位/移到目前位置'],
|
||
['img[src*="eye_"]', '切換道館/補給站顯示']
|
||
];
|
||
|
||
imageTooltips.forEach(([selector, label]) => {
|
||
document.querySelectorAll(selector).forEach(image => {
|
||
const target = image.closest('a, button, div') || image;
|
||
setToolbarTooltip(target, label);
|
||
image.setAttribute('alt', label);
|
||
});
|
||
});
|
||
}
|
||
|
||
function scheduleToolbarTooltips(delay = 100) {
|
||
window.clearTimeout(tooltipTimer);
|
||
tooltipTimer = window.setTimeout(applyToolbarTooltips, delay);
|
||
}
|
||
|
||
// 移除底部功能列
|
||
function cleanupBottomBar() {
|
||
let count = 0;
|
||
|
||
// 移除廣告
|
||
document.querySelectorAll('.adsbygoogle, ins.adsbygoogle, [data-ad-client], [data-ad-slot]').forEach(ad => {
|
||
ad.remove();
|
||
count++;
|
||
});
|
||
|
||
// 移除頂部標題
|
||
document.querySelectorAll('h1, h2, h3').forEach(title => {
|
||
if (title.textContent.includes('台灣寶可夢資訊站') || title.textContent.includes('TWPKInfo')) {
|
||
const container = title.closest('div');
|
||
if (container && container !== document.getElementById('map') && !container.classList.contains('leaflet-container')) {
|
||
container.remove();
|
||
count++;
|
||
}
|
||
}
|
||
});
|
||
|
||
// 清理底部列
|
||
const potentialBottomBars = [];
|
||
|
||
// 策略1:通過位置識別
|
||
document.querySelectorAll('div').forEach(div => {
|
||
if (div.id === 'map' ||
|
||
div.classList.contains('leaflet-container') ||
|
||
div.classList.contains('leaflet-control-attribution') ||
|
||
isLeafletDescendant(div)) {
|
||
return;
|
||
}
|
||
|
||
const rect = div.getBoundingClientRect();
|
||
const style = window.getComputedStyle(div);
|
||
|
||
// 識別底部固定元素
|
||
if ((style.position === 'fixed' || style.position === 'absolute') &&
|
||
(style.bottom === '0px' || parseInt(style.bottom) <= 30) &&
|
||
rect.width > 200 && // 有一定寬度
|
||
rect.height > 10 && rect.height < 150) { // 適中高度
|
||
potentialBottomBars.push(div);
|
||
}
|
||
|
||
// 識別位於底部的大寬度元素
|
||
if (rect.bottom >= window.innerHeight - 80 &&
|
||
rect.width > window.innerWidth * 0.4 &&
|
||
rect.height < 100 &&
|
||
rect.left <= 100) { // 不是右側小元素
|
||
potentialBottomBars.push(div);
|
||
}
|
||
});
|
||
|
||
// 策略2:通過內容識別
|
||
document.querySelectorAll('div').forEach(div => {
|
||
if (isLeafletDescendant(div)) {
|
||
return;
|
||
}
|
||
const classList = (typeof div.className === 'string' ? div.className : '').toLowerCase();
|
||
if (classList.includes('bottom') &&
|
||
(classList.includes('nav') || classList.includes('bar') || classList.includes('menu') || classList.includes('toolbar')) &&
|
||
!classList.includes('pokemon') &&
|
||
!classList.includes('leaflet')) {
|
||
potentialBottomBars.push(div);
|
||
}
|
||
});
|
||
|
||
// 策略3:DOM 結構識別(最後一個子元素)
|
||
const bodyChildren = Array.from(document.body.children);
|
||
bodyChildren.reverse().slice(0, 3).forEach(child => { // 檢查最後3個子元素
|
||
if (child.id !== 'map' &&
|
||
!child.classList.contains('leaflet-container') &&
|
||
!child.classList.contains('leaflet-control-attribution')) {
|
||
|
||
const rect = child.getBoundingClientRect();
|
||
if (rect.width > 200 && rect.height < 120 && rect.height > 20) {
|
||
potentialBottomBars.push(child);
|
||
}
|
||
}
|
||
});
|
||
|
||
// 執行移除(去重)
|
||
const uniqueElements = [...new Set(potentialBottomBars)];
|
||
uniqueElements.forEach(element => {
|
||
// 最後確認:確保不是重要元素
|
||
if (!element.querySelector('[class*="pokemon"]') &&
|
||
!element.querySelector('img[src*="pokemon"]') &&
|
||
!element.textContent.includes('Leaflet') &&
|
||
!element.textContent.includes('MapTiler') &&
|
||
!element.textContent.includes('OpenStreetMap')) {
|
||
element.remove();
|
||
count++;
|
||
}
|
||
});
|
||
|
||
if (count > 0) {
|
||
console.log(`已清理 ${count} 個元素`);
|
||
}
|
||
|
||
resizeMapToViewport();
|
||
return count;
|
||
}
|
||
|
||
// 移除 igym.aspx 這類頁面的頂部網站導覽列
|
||
function cleanupTopNavigation() {
|
||
let count = 0;
|
||
const navTexts = ['首頁', '官方消息', '關於寶可夢', '寵物圖鑑', '寵物身高體重最大最小參考值', '對戰排行榜'];
|
||
const candidates = document.querySelectorAll('body > nav, body > header, body > div, body > ul');
|
||
|
||
candidates.forEach(element => {
|
||
if (element.id === 'map' ||
|
||
element.classList.contains('leaflet-container') ||
|
||
isLeafletDescendant(element)) {
|
||
return;
|
||
}
|
||
|
||
const rect = element.getBoundingClientRect();
|
||
const text = element.textContent.replace(/\s+/g, '');
|
||
const navTextMatches = navTexts.filter(item => text.includes(item)).length;
|
||
const className = element.className.toString().toLowerCase();
|
||
|
||
const looksLikeTopBar = rect.top <= 80 &&
|
||
rect.width > window.innerWidth * 0.5 &&
|
||
rect.height > 20 &&
|
||
rect.height < 120;
|
||
const looksLikeSiteNav = navTextMatches >= 2 ||
|
||
className.includes('navbar') ||
|
||
className.includes('nav-bar') ||
|
||
className.includes('navigation');
|
||
|
||
if (looksLikeTopBar && looksLikeSiteNav) {
|
||
element.remove();
|
||
count++;
|
||
}
|
||
});
|
||
|
||
if (count > 0) {
|
||
console.log(`已清理 ${count} 個頂部導覽列`);
|
||
}
|
||
|
||
resizeMapToViewport();
|
||
return count;
|
||
}
|
||
|
||
// 持續清理監控
|
||
function startCleanupMonitor() {
|
||
const observer = new MutationObserver((mutations) => {
|
||
let needsCleanup = false;
|
||
let hasElementChanges = false;
|
||
|
||
mutations.forEach((mutation) => {
|
||
// 略過 Leaflet popup / pane 內部的變動,避免誤判清理
|
||
if (mutation.target && mutation.target.nodeType === 1 &&
|
||
isLeafletDescendant(mutation.target)) {
|
||
return;
|
||
}
|
||
|
||
mutation.addedNodes.forEach((node) => {
|
||
if (node.nodeType === 1) { // 元素節點
|
||
if (isLeafletDescendant(node)) {
|
||
return;
|
||
}
|
||
|
||
hasElementChanges = true;
|
||
const rect = node.getBoundingClientRect();
|
||
const style = window.getComputedStyle(node);
|
||
|
||
// 檢測新增的底部元素
|
||
if ((style.position === 'fixed' || style.position === 'absolute') &&
|
||
(style.bottom === '0px' || parseInt(style.bottom) <= 50) &&
|
||
rect.width > 100) {
|
||
needsCleanup = true;
|
||
}
|
||
|
||
if (rect.top <= 80 &&
|
||
rect.width > window.innerWidth * 0.5 &&
|
||
rect.height > 20 &&
|
||
rect.height < 120) {
|
||
const text = node.textContent.replace(/\s+/g, '');
|
||
if (text.includes('首頁') && text.includes('官方消息')) {
|
||
needsCleanup = true;
|
||
}
|
||
}
|
||
|
||
if (node.matches('div') &&
|
||
(node.querySelector('h1, h2, h3, .adsbygoogle, ins.adsbygoogle') ||
|
||
node.textContent.includes('台灣寶可夢資訊站') ||
|
||
node.textContent.includes('TWPKInfo'))) {
|
||
needsCleanup = true;
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
if (hasElementChanges) {
|
||
scheduleToolbarTooltips();
|
||
}
|
||
|
||
if (needsCleanup) {
|
||
console.log('偵測到新列元素,準備清理...');
|
||
setTimeout(cleanupTopNavigation, 200);
|
||
setTimeout(cleanupBottomBar, 200);
|
||
}
|
||
});
|
||
|
||
observer.observe(document.body, {
|
||
childList: true,
|
||
subtree: true
|
||
});
|
||
|
||
console.log('清理監控已啟動');
|
||
}
|
||
|
||
// 阻止廣告腳本
|
||
function blockAdScripts() {
|
||
if (!window.adsbygoogle) {
|
||
window.adsbygoogle = [];
|
||
}
|
||
window.adsbygoogle.push = () => console.log('AdSense 已阻止');
|
||
}
|
||
|
||
// 檢查清理效果
|
||
function checkCleanupEffect() {
|
||
setTimeout(() => {
|
||
const map = document.querySelector('#map, .leaflet-container');
|
||
const pokemonElements = document.querySelectorAll('[src*="pokemon"], [class*="pokemon"]');
|
||
const leafletAttribution = document.querySelector('.leaflet-control-attribution');
|
||
|
||
// 檢查是否還有底部列存在
|
||
const remainingBottomElements = [];
|
||
document.querySelectorAll('div').forEach(div => {
|
||
if (div.id === 'map' ||
|
||
div.classList.contains('leaflet-container') ||
|
||
isLeafletDescendant(div)) {
|
||
return;
|
||
}
|
||
|
||
const rect = div.getBoundingClientRect();
|
||
const style = window.getComputedStyle(div);
|
||
|
||
if (((style.position === 'fixed' || style.position === 'absolute') &&
|
||
(style.bottom === '0px' || parseInt(style.bottom) <= 30)) ||
|
||
(rect.bottom >= window.innerHeight - 50 && rect.width > 200)) {
|
||
|
||
if (!div.classList.contains('leaflet-control-attribution') &&
|
||
!div.closest('.leaflet-control-attribution')) {
|
||
remainingBottomElements.push(div);
|
||
}
|
||
}
|
||
});
|
||
|
||
console.log('清理效果檢查:');
|
||
console.log('- 地圖:', map ? '正常' : '缺失');
|
||
console.log('- 寶可夢元素:', pokemonElements.length > 0 ? `${pokemonElements.length} 個` : '缺失');
|
||
console.log('- Leaflet 版權:', leafletAttribution ? '保留' : '缺失');
|
||
console.log('- 剩餘底部元素:', remainingBottomElements.length, remainingBottomElements.length > 0 ? '仍有底部列' : '底部乾淨');
|
||
|
||
if (remainingBottomElements.length > 0) {
|
||
console.log('發現剩餘底部元素,再次清理...');
|
||
setTimeout(cleanupBottomBar, 1000);
|
||
} else {
|
||
console.log('清理任務完成');
|
||
}
|
||
}, 3000);
|
||
}
|
||
|
||
// 主要初始化
|
||
function init() {
|
||
blockAdScripts();
|
||
addCleanupCSS();
|
||
startCleanupWhenReady();
|
||
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', startCleanupWhenReady, { once: true });
|
||
} else {
|
||
startCleanupWhenReady();
|
||
}
|
||
}
|
||
|
||
function startCleanupWhenReady() {
|
||
if (cleanupStarted) {
|
||
return;
|
||
}
|
||
|
||
if (!document.body) {
|
||
setTimeout(startCleanupWhenReady, 50);
|
||
return;
|
||
}
|
||
|
||
cleanupStarted = true;
|
||
performCleanup();
|
||
}
|
||
|
||
// 執行清理
|
||
function performCleanup() {
|
||
console.log('開始清理任務');
|
||
resizeMapToViewport();
|
||
applyToolbarTooltips();
|
||
cleanupTopNavigation();
|
||
cleanupBottomBar();
|
||
|
||
// 多次清理提高穩定性
|
||
setTimeout(() => applyToolbarTooltips(), 300);
|
||
setTimeout(() => cleanupTopNavigation(), 500);
|
||
setTimeout(() => cleanupBottomBar(), 1000);
|
||
setTimeout(() => applyToolbarTooltips(), 1500);
|
||
setTimeout(() => cleanupTopNavigation(), 2000);
|
||
setTimeout(() => cleanupBottomBar(), 2500);
|
||
setTimeout(() => cleanupBottomBar(), 4000);
|
||
setTimeout(() => applyToolbarTooltips(), 4500);
|
||
|
||
// 啟動持續監控
|
||
startCleanupMonitor();
|
||
|
||
// 檢查清理效果
|
||
checkCleanupEffect();
|
||
|
||
// 定期檢查
|
||
setInterval(() => {
|
||
let hasBottomBars = false;
|
||
|
||
document.querySelectorAll('div').forEach(div => {
|
||
if (div.id === 'map' ||
|
||
div.classList.contains('leaflet-container') ||
|
||
isLeafletDescendant(div)) {
|
||
return;
|
||
}
|
||
|
||
const rect = div.getBoundingClientRect();
|
||
const style = window.getComputedStyle(div);
|
||
|
||
if (((style.position === 'fixed' || style.position === 'absolute') &&
|
||
(style.bottom === '0px' || parseInt(style.bottom) <= 30)) ||
|
||
(rect.bottom >= window.innerHeight - 50 && rect.width > 200)) {
|
||
|
||
if (!div.classList.contains('leaflet-control-attribution')) {
|
||
hasBottomBars = true;
|
||
}
|
||
}
|
||
});
|
||
|
||
if (hasBottomBars) {
|
||
console.log('定期檢查:發現底部元素');
|
||
cleanupBottomBar();
|
||
}
|
||
}, 8000);
|
||
}
|
||
|
||
console.log('初始化 TWPKInfo 廣告清除器');
|
||
init();
|
||
|
||
})();
|