gfsd
This commit is contained in:
+232
-88
@@ -118,10 +118,11 @@ window.cancelAnimFrame = (function () {
|
||||
};
|
||||
|
||||
const ensureLayoutClass = () => {
|
||||
if (window.f0ckSession && window.f0ckSession.use_new_layout === false) {
|
||||
document.body.classList.remove('layout-modern');
|
||||
const isLegacy = window.f0ckSession ? !window.f0ckSession.use_new_layout : (window.f0ckDefaultLayout === 'legacy');
|
||||
document.body.classList.remove('legacy-view', 'layout-modern', 'layout-legacy');
|
||||
if (isLegacy) {
|
||||
document.body.classList.add('layout-legacy');
|
||||
} else if (!document.body.classList.contains('layout-legacy')) {
|
||||
} else {
|
||||
document.body.classList.add('layout-modern');
|
||||
}
|
||||
};
|
||||
@@ -1196,10 +1197,74 @@ window.cancelAnimFrame = (function () {
|
||||
window.closeOnaraModal = closeOnaraModal;
|
||||
window.isOnaraActive = isOnaraActive;
|
||||
|
||||
// Content selector for protected elements inside onara modal
|
||||
const _onaraContentSelector = [
|
||||
'.media-object',
|
||||
'.previous-post',
|
||||
'.next-post',
|
||||
'.arrow-prev',
|
||||
'.arrow-next',
|
||||
'#prev',
|
||||
'#next',
|
||||
'.nav-prev',
|
||||
'.nav-next',
|
||||
'#random',
|
||||
'.steuerung',
|
||||
'.location',
|
||||
'.item_title',
|
||||
'.blahlol',
|
||||
'#comments-container',
|
||||
'.tag-controls',
|
||||
'.sidebar-tags-container',
|
||||
'.xd-score-wrapper',
|
||||
'.user-infobox-block',
|
||||
'a',
|
||||
'button',
|
||||
'input',
|
||||
'textarea',
|
||||
'select',
|
||||
'label',
|
||||
'form',
|
||||
'video',
|
||||
'audio',
|
||||
'img',
|
||||
'canvas',
|
||||
'iframe',
|
||||
'.iconset',
|
||||
'.badge',
|
||||
'.btn',
|
||||
'time',
|
||||
'[role="button"]',
|
||||
'i[class*="fa-"]'
|
||||
].join(', ');
|
||||
|
||||
let _onaraMouseDownInside = false;
|
||||
|
||||
document.addEventListener('mousedown', (e) => {
|
||||
if (!document.body.classList.contains('onara-modal-open')) return;
|
||||
if (e.target.closest('.modal-overlay:not(#onara-modal), .modal-content, .swal2-container, .tippy-box, #comments-container .emoji-picker, .dropdown-menu, .custom-confirm-overlay') ||
|
||||
e.target.closest('.global-sidebar-right, nav.navbar, #sidebar-drag-zone') ||
|
||||
e.target.closest(_onaraContentSelector)) {
|
||||
_onaraMouseDownInside = true;
|
||||
} else {
|
||||
_onaraMouseDownInside = false;
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
// Onara modal close click delegation: clicking on empty/free space closes the modal
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!document.body.classList.contains('onara-modal-open')) return;
|
||||
|
||||
// If mouse press originated on a protected element or if text is currently selected, do not close
|
||||
if (_onaraMouseDownInside) {
|
||||
_onaraMouseDownInside = false;
|
||||
return;
|
||||
}
|
||||
const sel = window.getSelection();
|
||||
if (sel && sel.toString().trim().length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not close if clicking auxiliary modals, dropdowns, tooltips, or emoji pickers
|
||||
if (e.target.closest('.modal-overlay:not(#onara-modal), .modal-content, .swal2-container, .tippy-box, #comments-container .emoji-picker, .dropdown-menu, .custom-confirm-overlay')) return;
|
||||
|
||||
@@ -1207,47 +1272,7 @@ window.cancelAnimFrame = (function () {
|
||||
if (e.target.closest('.global-sidebar-right, nav.navbar, #sidebar-drag-zone')) return;
|
||||
|
||||
// Do not close if clicking interactive content elements or actual item components
|
||||
const contentElementSelector = [
|
||||
'.media-object',
|
||||
'.previous-post',
|
||||
'.next-post',
|
||||
'.arrow-prev',
|
||||
'.arrow-next',
|
||||
'#prev',
|
||||
'#next',
|
||||
'.nav-prev',
|
||||
'.nav-next',
|
||||
'#random',
|
||||
'.steuerung',
|
||||
'.location',
|
||||
'.item_title',
|
||||
'.blahlol',
|
||||
'#comments-container',
|
||||
'.tag-controls',
|
||||
'.sidebar-tags-container',
|
||||
'.xd-score-wrapper',
|
||||
'.user-infobox-block',
|
||||
'a',
|
||||
'button',
|
||||
'input',
|
||||
'textarea',
|
||||
'select',
|
||||
'label',
|
||||
'form',
|
||||
'video',
|
||||
'audio',
|
||||
'img',
|
||||
'canvas',
|
||||
'iframe',
|
||||
'.iconset',
|
||||
'.badge',
|
||||
'.btn',
|
||||
'time',
|
||||
'[role="button"]',
|
||||
'i[class*="fa-"]'
|
||||
].join(', ');
|
||||
|
||||
if (e.target.closest(contentElementSelector)) return;
|
||||
if (e.target.closest(_onaraContentSelector)) return;
|
||||
|
||||
// Any click on free space (backdrop, modal wrapper, container background, empty space in item-main-content) closes
|
||||
if (e.target.closest('#onara-modal') || e.target.id === 'onara-backdrop') {
|
||||
@@ -1728,6 +1753,61 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
|
||||
|
||||
const _preloadedMediaUrls = new Set();
|
||||
|
||||
const preloadMediaFromHtml = (html) => {
|
||||
if (!html) return;
|
||||
try {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, 'text/html');
|
||||
|
||||
// 1. Preload Image
|
||||
const img = doc.querySelector('#f0ck-image, .embed-responsive-image img, .media-object img');
|
||||
if (img) {
|
||||
const src = img.getAttribute('src');
|
||||
if (src && !_preloadedMediaUrls.has(src)) {
|
||||
_preloadedMediaUrls.add(src);
|
||||
const preloadImg = new Image();
|
||||
preloadImg.decoding = 'async';
|
||||
preloadImg.src = src;
|
||||
window.f0ckDebug('[prefetch] Preloaded image asset:', src);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Preload Audio Cover Art
|
||||
const cover = doc.querySelector('#f0ck-audio-cover');
|
||||
if (cover) {
|
||||
const coverSrc = cover.getAttribute('src');
|
||||
if (coverSrc && coverSrc !== '/s/img/200.gif' && !_preloadedMediaUrls.has(coverSrc)) {
|
||||
_preloadedMediaUrls.add(coverSrc);
|
||||
const preloadCover = new Image();
|
||||
preloadCover.src = coverSrc;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Preload Video / Audio Media (fetch initial bytes into browser cache)
|
||||
const mediaEl = doc.querySelector('video#my-video, audio#my-video, .media-object video, .media-object audio');
|
||||
if (mediaEl) {
|
||||
const mediaSrc = mediaEl.getAttribute('src');
|
||||
if (mediaSrc && !mediaSrc.startsWith('blob:') && !_preloadedMediaUrls.has(mediaSrc)) {
|
||||
_preloadedMediaUrls.add(mediaSrc);
|
||||
fetch(mediaSrc, {
|
||||
headers: { Range: 'bytes=0-2097151' }, // 2MB initial chunk preload
|
||||
credentials: 'include',
|
||||
priority: 'low'
|
||||
}).catch(() => {});
|
||||
window.f0ckDebug('[prefetch] Preloaded media buffer:', mediaSrc);
|
||||
}
|
||||
}
|
||||
|
||||
if (_preloadedMediaUrls.size > 150) {
|
||||
_preloadedMediaUrls.clear();
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[prefetch] Error preloading media from html:', e);
|
||||
}
|
||||
};
|
||||
|
||||
const prefetchNextPrevItems = () => {
|
||||
const nextBtn = document.getElementById('next');
|
||||
const prevBtn = document.getElementById('prev');
|
||||
@@ -1769,7 +1849,11 @@ window.cancelAnimFrame = (function () {
|
||||
ajaxUrl += (ajaxUrl.includes('?') ? '&' : '?') + params.toString();
|
||||
}
|
||||
|
||||
if (itemCacheMap.has(ajaxUrl)) return;
|
||||
if (itemCacheMap.has(ajaxUrl)) {
|
||||
const cached = itemCacheMap.get(ajaxUrl);
|
||||
if (cached && cached.html) preloadMediaFromHtml(cached.html);
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(ajaxUrl, { credentials: 'include', priority: 'low' })
|
||||
.then(r => r.ok ? r.text() : null)
|
||||
@@ -1787,6 +1871,7 @@ window.cancelAnimFrame = (function () {
|
||||
itemCacheMap.delete(itemCacheMap.keys().next().value);
|
||||
}
|
||||
window.f0ckDebug('[prefetch] Cached AJAX template for item', itemId);
|
||||
preloadMediaFromHtml(html);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
@@ -2745,7 +2830,8 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
window.dispatchEvent(new Event('pjax:start'));
|
||||
|
||||
const currentScroll = window.scrollY;
|
||||
const currentContainer = document.querySelector('.index-container');
|
||||
const currentScroll = currentContainer ? currentContainer.scrollTop : window.scrollY;
|
||||
|
||||
// Save scroll position for the current page before we leave it (only for new navigations)
|
||||
if (!options.skipPush) {
|
||||
@@ -2835,7 +2921,9 @@ window.cancelAnimFrame = (function () {
|
||||
if (paginationWrapper && cache.pagination) paginationWrapper.innerHTML = cache.pagination;
|
||||
const restoredPosts = cache.node.querySelector('.posts');
|
||||
if (restoredPosts && restoredPosts._scrollHandler) {
|
||||
window.addEventListener('scroll', restoredPosts._scrollHandler, { passive: true });
|
||||
const sc = restoredPosts.closest('.index-container') || window;
|
||||
restoredPosts._scrollContainer = sc;
|
||||
sc.addEventListener('scroll', restoredPosts._scrollHandler, { passive: true });
|
||||
if (restoredPosts._infiniteState) restoredPosts._infiniteState.loading = false;
|
||||
}
|
||||
}
|
||||
@@ -2844,7 +2932,14 @@ window.cancelAnimFrame = (function () {
|
||||
if (!options.skipPush && !document.body.classList.contains('onara-modal-open')) history.pushState({}, '', url);
|
||||
|
||||
// Restore scroll position
|
||||
requestAnimationFrame(() => window.scrollTo(0, cache.scroll));
|
||||
requestAnimationFrame(() => {
|
||||
const ic = document.querySelector('.index-container');
|
||||
if (ic && cache.scroll !== undefined) {
|
||||
ic.scrollTo(0, cache.scroll);
|
||||
} else {
|
||||
window.scrollTo(0, cache.scroll || 0);
|
||||
}
|
||||
});
|
||||
|
||||
// Update title
|
||||
const urlParamsC = new URLSearchParams(urlObj.search);
|
||||
@@ -3423,10 +3518,16 @@ window.cancelAnimFrame = (function () {
|
||||
// Handle Scroll Position (Restore or Reset)
|
||||
if (options.skipPush && history.state && history.state.scroll !== undefined) {
|
||||
// Back/Forward Navigation: Restore saved scroll position
|
||||
requestAnimationFrame(() => window.scrollTo(0, history.state.scroll));
|
||||
requestAnimationFrame(() => {
|
||||
const ic = document.querySelector('.index-container');
|
||||
if (ic) ic.scrollTo(0, history.state.scroll);
|
||||
else window.scrollTo(0, history.state.scroll);
|
||||
});
|
||||
} else if (replace) {
|
||||
// New Navigation: Reset to top
|
||||
window.scrollTo(0, 0);
|
||||
const ic = document.querySelector('.index-container');
|
||||
if (ic) ic.scrollTo(0, 0);
|
||||
else window.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
// Trigger fade-in
|
||||
@@ -3544,10 +3645,11 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
// Navbar scroll effect - make background black when scrolling
|
||||
if (navbar) {
|
||||
window.addEventListener('scroll', () => {
|
||||
const isScrolled = window.scrollY > 10;
|
||||
document.addEventListener('scroll', () => {
|
||||
const ic = document.querySelector('.index-container');
|
||||
const isScrolled = (ic ? ic.scrollTop : window.scrollY) > 10;
|
||||
navbar.classList.toggle('scrolled', isScrolled);
|
||||
});
|
||||
}, { passive: true, capture: true });
|
||||
}
|
||||
|
||||
// Helper to immediately abort media downloads
|
||||
@@ -3674,7 +3776,8 @@ window.cancelAnimFrame = (function () {
|
||||
window.dispatchEvent(new Event('pjax:start'));
|
||||
}
|
||||
|
||||
const currentScroll = window.scrollY;
|
||||
const currentContainer = document.querySelector('.index-container');
|
||||
const currentScroll = currentContainer ? currentContainer.scrollTop : window.scrollY;
|
||||
|
||||
// Save scroll position for current page (only for new navigations)
|
||||
if (!options.skipPush && !options.keepMedia && !useOnara) {
|
||||
@@ -3885,12 +3988,7 @@ window.cancelAnimFrame = (function () {
|
||||
_ntc.remove();
|
||||
}
|
||||
main.className = 'item-view';
|
||||
document.body.classList.remove('legacy-view', 'layout-modern', 'layout-legacy');
|
||||
if (window.f0ckSession && !window.f0ckSession.use_new_layout) {
|
||||
document.body.classList.add('layout-legacy');
|
||||
} else {
|
||||
document.body.classList.add('layout-modern');
|
||||
}
|
||||
ensureLayoutClass();
|
||||
if (window.syncNavbarHeight) window.syncNavbarHeight();
|
||||
main.innerHTML = '';
|
||||
_container = main;
|
||||
@@ -3981,6 +4079,12 @@ window.cancelAnimFrame = (function () {
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
if (typeof requestIdleCallback === 'function') {
|
||||
requestIdleCallback(() => prefetchNextPrevItems());
|
||||
} else {
|
||||
setTimeout(prefetchNextPrevItems, 100);
|
||||
}
|
||||
|
||||
return; // Done — served from cache
|
||||
}
|
||||
// ── END CACHE HIT ───────────────────────────────────────────────────────
|
||||
@@ -4078,12 +4182,7 @@ window.cancelAnimFrame = (function () {
|
||||
main.className = 'item-view';
|
||||
|
||||
// Correctly handle body classes for the current layout mode
|
||||
document.body.classList.remove('legacy-view', 'layout-modern', 'layout-legacy');
|
||||
if (window.f0ckSession && !window.f0ckSession.use_new_layout) {
|
||||
document.body.classList.add('layout-legacy');
|
||||
} else {
|
||||
document.body.classList.add('layout-modern');
|
||||
}
|
||||
ensureLayoutClass();
|
||||
if (window.syncNavbarHeight) window.syncNavbarHeight();
|
||||
|
||||
// Toggle button lives permanently in body via header.html — no creation needed
|
||||
@@ -5172,6 +5271,16 @@ window.cancelAnimFrame = (function () {
|
||||
// Don't fire global shortcuts on the scroller/abyss page — it has its own handler
|
||||
if (document.body && document.body.classList.contains('scroller-active')) return;
|
||||
|
||||
// Shift+F: shortcut for favorite when "F is for Fullscreen" is active
|
||||
if ((e.key === 'F' || (e.key === 'f' && e.shiftKey)) && e.shiftKey && !e.ctrlKey && !e.metaKey && !e.altKey && e.target.tagName !== "INPUT" && e.target.tagName !== "TEXTAREA" && !e.target.isContentEditable) {
|
||||
if (localStorage.getItem('fForFullscreen') === 'true') {
|
||||
if (e.repeat) return;
|
||||
e.preventDefault();
|
||||
clickOnElementBinding("#a_favo")();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.key in keybindings && e.target.tagName !== "INPUT" && e.target.tagName !== "TEXTAREA") {
|
||||
const isHelpKey = e.key === '?' || e.key === 'ß';
|
||||
if (e.repeat || (e.shiftKey && e.key !== '?') || e.ctrlKey || e.metaKey || e.altKey)
|
||||
@@ -5210,11 +5319,21 @@ window.cancelAnimFrame = (function () {
|
||||
const initInfiniteScroll = (postsContainer) => {
|
||||
if (!postsContainer || postsContainer.classList.contains('no-infinite-scroll')) return;
|
||||
|
||||
const scrollContainer = postsContainer.closest('.index-container') || window;
|
||||
const isElementScroll = scrollContainer !== window;
|
||||
|
||||
const getScrollTop = () => isElementScroll ? scrollContainer.scrollTop : window.scrollY;
|
||||
const getViewportHeight = () => isElementScroll ? scrollContainer.clientHeight : window.innerHeight;
|
||||
const getScrollHeight = () => isElementScroll ? scrollContainer.scrollHeight : (document.documentElement.scrollHeight || document.body.scrollHeight);
|
||||
const scrollToPos = (top) => isElementScroll ? scrollContainer.scrollTo(0, top) : window.scrollTo(0, top);
|
||||
|
||||
// If already initialized, clean up the old scroll listener first
|
||||
if (postsContainer._infiniteState) {
|
||||
if (postsContainer._scrollHandler) {
|
||||
window.removeEventListener('scroll', postsContainer._scrollHandler);
|
||||
const sc = postsContainer._scrollContainer || scrollContainer;
|
||||
sc.removeEventListener('scroll', postsContainer._scrollHandler);
|
||||
delete postsContainer._scrollHandler;
|
||||
delete postsContainer._scrollContainer;
|
||||
}
|
||||
delete postsContainer._infiniteState;
|
||||
}
|
||||
@@ -5227,7 +5346,7 @@ window.cancelAnimFrame = (function () {
|
||||
hasPrev: false,
|
||||
currentPage: 1,
|
||||
firstPage: 1,
|
||||
lastScrollY: window.scrollY,
|
||||
lastScrollY: getScrollTop(),
|
||||
navigationGracePeriod: Date.now() + 500, // No URL updates for 500ms after load
|
||||
loadedPages: new Set()
|
||||
};
|
||||
@@ -5331,13 +5450,15 @@ window.cancelAnimFrame = (function () {
|
||||
// Find the marker that is currently most visible/active
|
||||
let maxVisibleHeight = 0;
|
||||
|
||||
const viewportHeight = window.innerHeight;
|
||||
const scrollTop = window.scrollY;
|
||||
const viewportHeight = getViewportHeight();
|
||||
const scrollTop = getScrollTop();
|
||||
const scrollHeight = getScrollHeight();
|
||||
|
||||
// Special case: if we are close to the bottom of the entire document,
|
||||
// Special case: if we are close to the bottom of the entire document/container,
|
||||
// give priority to the last marker that is at least partially visible.
|
||||
// Increasing threshold to 150px for better resilience on high-res monitors.
|
||||
const isNearBottom = (viewportHeight + window.scrollY) >= (document.documentElement.scrollHeight - 150);
|
||||
const isNearBottom = (viewportHeight + scrollTop) >= (scrollHeight - 150);
|
||||
const containerTop = isElementScroll ? scrollContainer.getBoundingClientRect().top : 0;
|
||||
|
||||
// Heuristic: iterate markers and calculate how much vertical space each "page section" occupies in the viewport
|
||||
for (let i = 0; i < markers.length; i++) {
|
||||
@@ -5345,11 +5466,12 @@ window.cancelAnimFrame = (function () {
|
||||
const rect = marker.getBoundingClientRect();
|
||||
const nextMarker = markers[i + 1];
|
||||
|
||||
// Start of this section (relative to viewport top)
|
||||
const start = rect.top;
|
||||
// End of this section (relative to viewport top). If no next marker, assume bottom of document/container
|
||||
// Start of this section (relative to viewport/container top)
|
||||
const start = rect.top - containerTop;
|
||||
// End of this section (relative to viewport/container top). If no next marker, assume bottom of document/container
|
||||
// rect.top of next marker, or very large number
|
||||
const end = nextMarker ? nextMarker.getBoundingClientRect().top : 99999;
|
||||
const nextRect = nextMarker ? nextMarker.getBoundingClientRect() : null;
|
||||
const end = nextRect ? (nextRect.top - containerTop) : 99999;
|
||||
|
||||
// Intersection with viewport [0, viewportHeight]
|
||||
const visibleStart = Math.max(0, start);
|
||||
@@ -5564,7 +5686,7 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
// Capture height/scroll RIGHT BEFORE insertion to account for any user scrolling during fetch
|
||||
const oldHeight = postsContainer.scrollHeight;
|
||||
const oldScrollTop = window.scrollY;
|
||||
const oldScrollTop = getScrollTop();
|
||||
|
||||
if (data.success && data.html) {
|
||||
const temp = document.createElement('div');
|
||||
@@ -5595,7 +5717,7 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
// Restore scroll position
|
||||
const newHeight = postsContainer.scrollHeight;
|
||||
window.scrollTo(0, oldScrollTop + (newHeight - oldHeight));
|
||||
scrollToPos(oldScrollTop + (newHeight - oldHeight));
|
||||
|
||||
infiniteState.firstPage = prevPage;
|
||||
infiniteState.hasPrev = prevPage > 1;
|
||||
@@ -5629,7 +5751,7 @@ window.cancelAnimFrame = (function () {
|
||||
const currentContainer = postsContainer;
|
||||
// Only run if THIS container is the active one and still in DOM
|
||||
if (!currentContainer || !document.body.contains(currentContainer)) {
|
||||
window.removeEventListener('scroll', onScroll);
|
||||
scrollContainer.removeEventListener('scroll', onScroll);
|
||||
return;
|
||||
}
|
||||
if (currentContainer.classList.contains('no-infinite-scroll')) return;
|
||||
@@ -5637,9 +5759,10 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
updateUrlAndPagination();
|
||||
|
||||
const scrollPosition = window.innerHeight + window.scrollY;
|
||||
const pageHeight = main.offsetHeight; // use cached ref, not querySelector every scroll
|
||||
const distanceFromBottom = pageHeight - scrollPosition;
|
||||
const scrollTop = getScrollTop();
|
||||
const vHeight = getViewportHeight();
|
||||
const sHeight = getScrollHeight();
|
||||
const distanceFromBottom = sHeight - (vHeight + scrollTop);
|
||||
|
||||
// Load more when within PRELOAD_OFFSET pixels of bottom
|
||||
if (distanceFromBottom < PRELOAD_OFFSET && infiniteState.hasMore && !infiniteState.loading) {
|
||||
@@ -5647,17 +5770,18 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
|
||||
// Load previous when within PRELOAD_OFFSET pixels of top
|
||||
if (window.scrollY < PRELOAD_OFFSET && infiniteState.hasPrev && !infiniteState.loadingUp) {
|
||||
if (scrollTop < PRELOAD_OFFSET && infiniteState.hasPrev && !infiniteState.loadingUp) {
|
||||
loadPreviousItems();
|
||||
}
|
||||
|
||||
infiniteState.lastScrollY = window.scrollY;
|
||||
infiniteState.lastScrollY = scrollTop;
|
||||
});
|
||||
};
|
||||
|
||||
// Store scroll handler reference for cleanup
|
||||
// Store scroll handler and container reference for cleanup
|
||||
postsContainer._scrollHandler = onScroll;
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
postsContainer._scrollContainer = scrollContainer;
|
||||
scrollContainer.addEventListener('scroll', onScroll, { passive: true });
|
||||
|
||||
// Initial check (in case we loaded at top/bottom)
|
||||
setTimeout(onScroll, 100);
|
||||
@@ -11516,7 +11640,17 @@ document.addEventListener('click', (e) => {
|
||||
const link = e.target.closest('.steuerung-scroll-down');
|
||||
if (!link) return;
|
||||
e.preventDefault();
|
||||
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
|
||||
const onaraModal = e.target.closest('#onara-modal') || (document.body.classList.contains('onara-modal-open') && document.getElementById('onara-modal'));
|
||||
if (onaraModal) {
|
||||
onaraModal.scrollTo({ top: onaraModal.scrollHeight, behavior: 'smooth' });
|
||||
} else {
|
||||
const ic = document.querySelector('.index-container');
|
||||
if (ic) {
|
||||
ic.scrollTo({ top: ic.scrollHeight, behavior: 'smooth' });
|
||||
} else {
|
||||
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ── Mobile scroll-to-top button ───────────────────────────────────────────────
|
||||
@@ -11525,7 +11659,17 @@ document.addEventListener('click', (e) => {
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!e.target.closest('.mobile-scroll-to-top')) return;
|
||||
e.preventDefault();
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
const onaraModal = e.target.closest('#onara-modal') || (document.body.classList.contains('onara-modal-open') && document.getElementById('onara-modal'));
|
||||
if (onaraModal) {
|
||||
onaraModal.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
} else {
|
||||
const ic = document.querySelector('.index-container');
|
||||
if (ic) {
|
||||
ic.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
} else {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
if (navigator.vibrate) navigator.vibrate(20);
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -267,7 +267,7 @@ class v0ck {
|
||||
}
|
||||
function enterFullScreen() {
|
||||
if (document.fullscreenElement) return;
|
||||
const target = document.getElementById('main') || player;
|
||||
const target = player;
|
||||
if (/(iPad|iPhone|iPod)/gi.test(navigator.platform))
|
||||
video.webkitEnterFullscreen();
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user