Enhanced user experience for toonkor
// ==UserScript==
// @name TKOR Enhanced
// @author Minjae Kim
// @version 1.12
// @description Enhanced user experience for toonkor
// @match https://tkor1*.com/*
// @grant none
// @include /^https?:\/\/(?:www\.)?tkor\d{3}\.com\/.*/
// @include /^https?:\/\/(?:www\.)?toonkor\d{3}\.com\/.*/
// @icon https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRjf9ah_nrpbeAvtWWj4SspQhTCY_-bikwFswNoO-ovMA&s=10
// @license MIT
// @run-at document-start
// @namespace https://greasyfork.org/en/users/1529082-minjae-kim
// ==/UserScript==
(function () {
'use strict';
//adblock css
function adblock(){
const css = `
#mobile_nav,
.navbar.navbar-default.navbar-static-top,
.col-md-12.mobile-banner,
#banner_21_img,
.bn.bnt,
#nad
{
display: none !important;
}
`;
if (typeof GM_addStyle !== 'undefined') {
GM_addStyle(css);
} else {
const style = document.createElement('style');
style.textContent = css;
document.head.append(style);
}
}
//add search box
function searchboxInsert() {
const targetElement = document.querySelector('#bo_list_total');
if (targetElement) {
const searchBoxHTML = `
<div class="custom-search-wrapper" style="display: inline-block; margin-left: 10px;">
<input type="search" id="custom-search" placeholder="Search..." style="padding: 5px 10px; border: 1px solid #ccc; border-radius: 4px;">
<button id="custom-search-btn" style="padding: 5px 10px; cursor: pointer;">Go</button>
</div>
`;
targetElement.insertAdjacentHTML('afterend', searchBoxHTML);
const performSearch = () => {
const query = document.getElementById('custom-search').value;
if (query) {
window.location.href = `/bbs/search.php?sfl=wr_subject%7C%7Cwr_content&stx=${encodeURIComponent(query)}`;
}
};
document.getElementById('custom-search-btn').addEventListener('click', performSearch);
document.getElementById('custom-search').addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
event.preventDefault();
performSearch();
}
});
}
}
function runIdleTasks() {
console.log("[Userscript] Browser is idle. Running background tasks...");
// Heavy operations (e.g., scraping, analytics, loading large external libraries)
performHeavyLifting();
adblock();
searchboxInsert();
}
// Schedule the idle tasks safely
if ('requestIdleCallback' in window) {
requestIdleCallback(runIdleTasks, { timeout: 2000 });
// Note: 'timeout' ensures it runs within 2 seconds even if the browser is busy
} else {
// Fallback for older browsers or Safari (which lacks full support)
window.addEventListener('load', () => {
setTimeout(runIdleTasks, 1);
});
}
//goto recent url number
function performHeavyLifting() {
const latestNumber = '149';
if (window.location.href.includes("toonkor")){
window.location.host = `tkor${latestNumber}.com`;
//window.location.href = `https://tkor${latestNumber}.com${window.location.pathname}`;
return;
}
if (window.location.href.includes("tkor")){
const numberPart = location.hostname.match(/\d+/)[0];
console.log(numberPart);
if(Number(numberPart)==137 || Number(numberPart)==136 || Number(numberPart)<Number(latestNumber)){
window.location.host = `tkor${latestNumber}.com`;
//window.location.href = `https://tkor${latestNumber}.com${window.location.pathname}`;
return;
}
//const number = Number(numberPart)+1;
// Redirect on Cloudflare or missing body error
const hasError = document.querySelector("#cf-error-details") || !document.querySelector("#body_sec");
if (hasError) {
const nextNumber = Number(numberPart) + 1;
window.location.host = `tkor${nextNumber}.com`;
//window.location.href = `https://tkor${nextNumber}.com${window.location.pathname}${window.location.search}`;
return;
}
}
}
/*--------SCROLL SAVER--------*/
const normalize = s => (s || '').toLowerCase().replace(/\s+/g, '').replace(/[^\w가-힣]/g, '');
function getSeriesId() {
const file = location.pathname.split('/').pop() || '';
return file.replace(/\.html.*$/, '').replace(/_[^_]+$/, '');
}
function getChapterId() {
const file = location.pathname.split('/').pop() || '';
return normalize(file + '|' + document.title);
}
const seriesId = getSeriesId();
if (!seriesId) return;
const chapterId = getChapterId();
const panelKey = `tkor_panel_${seriesId}`;
const scrollKey = `tkor_scroll_${seriesId}`;
const chapterKey = `tkor_chapter_${seriesId}`;
/* -------- Chapter Change Check ---------- */
const isNewChapter = localStorage.getItem(chapterKey) !== chapterId;
if (isNewChapter) {
localStorage.removeItem(panelKey);
localStorage.removeItem(scrollKey);
localStorage.setItem(chapterKey, chapterId);
window.scrollTo(0, 0);
}
/* ---------- Restore Position ---------- */
function restorePosition() {
if (isNewChapter) return;
const panelData = JSON.parse(localStorage.getItem(panelKey) || 'null');
const imgs = [...document.images];
// Try panel resume first
if (panelData && imgs.length) {
const target = imgs.find(img => img.currentSrc === panelData.src) || imgs[panelData.index];
if (target) {
target.scrollIntoView({ block: 'center' });
return;
}
}
// Fallback to scroll position
const savedScroll = localStorage.getItem(scrollKey);
if (savedScroll) {
window.scrollTo(0, parseInt(savedScroll, 10));
}
}
/* ---------- Image-Aware Restore ---------- */
let decided = false;
const safeIdle = window.requestIdleCallback || ((cb) => setTimeout(cb, 1));
function maybeRestore() {
if (decided) return;
decided = true;
safeIdle(restorePosition, { timeout: 800 });
}
const imgs = document.images;
if (imgs.length === 0) {
setTimeout(maybeRestore, 600);
} else {
let loaded = 0;
for (const img of imgs) {
if (img.complete) {
loaded++;
} else {
img.addEventListener('load', () => {
loaded++;
if (loaded >= 2) maybeRestore();
}, { once: true });
}
}
if (loaded >= 2) maybeRestore();
}
setTimeout(maybeRestore, 3000);
/* ----------Scroll Listener ---------- */
let scrollTick = false;
window.addEventListener('scroll', () => {
if (scrollTick) return;
scrollTick = true;
safeIdle(() => {
//Save scroll position
localStorage.setItem(scrollKey, window.scrollY);
//save closest panel image
const imgList = [...document.images];
if (imgList.length) {
const center = window.innerHeight / 2;
let closest = null;
let minDist = Infinity;
imgList.forEach((img, i) => {
const rect = img.getBoundingClientRect();
if (rect.height === 0) return;
const dist = Math.abs(rect.top + rect.height / 2 - center);
if (dist < minDist) {
minDist = dist;
closest = { index: i, src: img.currentSrc };
}
});
if (closest) {
localStorage.setItem(panelKey, JSON.stringify(closest));
}
}
scrollTick = false;
}, { timeout: 300 });
}, { passive: true });
})();