Something went wrong. Try again.
A lightweight, self-hosted personal archiver, reader, and gallery manager for nhentai nh.ufal.my.id
python archiver nhentai
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120/** * Manga Reader Controller * Handles image rendering, keyboard/touch navigation, RTL manga reading mode, and dynamic URL updates. */
// Normalize initial page index from URL parameter (1-based to 0-based)let currentIndex = (window.initialPage && window.initialPage >= 1 && window.initialPage <= window.pages.length) ? window.initialPage - 1 : 0;const img = document.getElementById('manga-page');const indicator = document.getElementById('page-indicator');
// Automatically keep the reader viewer centered on the screen upon image load or page changefunction centerViewer() { document.getElementById('viewer').scrollIntoView({ behavior: 'instant', block: 'center' });}
if (img) { img.onload = centerViewer;}
// Update the displayed image, counter, document title, and push history state without reloadingfunction update() { img.src = window.pages[currentIndex]; indicator.innerText = (currentIndex + 1) + ' of ' + window.pages.length; document.title = window.galleryTitle + ' - page ' + (currentIndex + 1) + ' - ' + window.siteName; history.replaceState(null, '', '/g/' + window.galleryId + '/' + (currentIndex + 1)); centerViewer();}
function next() { if (currentIndex < window.pages.length - 1) { currentIndex++; update(); }}
function prev() { if (currentIndex > 0) { currentIndex--; update(); }}
const nextBtn = document.getElementById('next');const prevBtn = document.getElementById('prev');
if (nextBtn) nextBtn.onclick = next;if (prevBtn) prevBtn.onclick = prev;
// Helper to read client-side cookie valuesfunction getCookie(name) { const value = '; ' + document.cookie; const parts = value.split('; ' + name + '='); if (parts.length === 2) return parts.pop().split(';').shift(); return null;}
// Check whether RTL (Right-to-Left manga order) mode is activefunction isRtlMode() { if (typeof window.pageOrder === 'string') { return window.pageOrder === 'rtl'; } return (getCookie('flip_page_order') === 'rtl');}
// Handle tap/click navigation: splits viewer into left and right interactive click zonesfunction handleTap(e) { const isRtl = isRtlMode(); const target = img || document.getElementById('viewer'); if (!target) return; const rect = target.getBoundingClientRect(); const isLeft = (e.clientX - rect.left < rect.width / 2);
if (isRtl) { // In RTL mode, clicking left advances forward, clicking right moves back if (isLeft) { next(); } else { prev(); } } else { // In LTR mode, clicking left moves back, clicking right advances forward if (isLeft) { prev(); } else { next(); } }}
if (img) { img.onclick = handleTap;}
const viewer = document.getElementById('viewer');if (viewer) { viewer.onclick = (e) => { if (e.target !== img) { handleTap(e); } };}
// Keyboard arrow navigation supporting both LTR and RTL reading directionwindow.addEventListener('keydown', (e) => { const isRtl = isRtlMode(); if (isRtl) { if (e.key === 'ArrowLeft') next(); if (e.key === 'ArrowRight') prev(); } else { if (e.key === 'ArrowRight') next(); if (e.key === 'ArrowLeft') prev(); }});
// Render the initial page on loadif (window.pages && window.pages.length > 0) { update();}