first version of infinite scrolling
This commit is contained in:
@@ -68,6 +68,18 @@ window.requestAnimFrame = (function () {
|
||||
}
|
||||
};
|
||||
|
||||
// Navbar scroll effect - make background black when scrolling
|
||||
const navbar = document.querySelector('.navbar');
|
||||
if (navbar) {
|
||||
window.addEventListener('scroll', () => {
|
||||
if (window.scrollY > 50) {
|
||||
navbar.classList.add('scrolled');
|
||||
} else {
|
||||
navbar.classList.remove('scrolled');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const loadItemAjax = async (url, inheritContext = true) => {
|
||||
console.log("loadItemAjax called with:", url, "inheritContext:", inheritContext);
|
||||
// Show loading indicator
|
||||
@@ -335,15 +347,109 @@ window.requestAnimFrame = (function () {
|
||||
}
|
||||
// </image-responsive>
|
||||
|
||||
// <scroller>
|
||||
let tts = 0;
|
||||
const scroll_treshold = 1;
|
||||
if ([...document.querySelectorAll("div.posts")].length === 1) {
|
||||
// <infinite-scroll>
|
||||
const postsContainer = document.querySelector("div.posts");
|
||||
if (postsContainer) {
|
||||
// Infinite scroll state
|
||||
let infiniteState = {
|
||||
loading: false,
|
||||
hasMore: true,
|
||||
currentPage: 1
|
||||
};
|
||||
|
||||
// Extract current page from URL
|
||||
const pageMatch = window.location.pathname.match(/\/p\/(\d+)/);
|
||||
if (pageMatch) infiniteState.currentPage = parseInt(pageMatch[1]);
|
||||
|
||||
// Extract context (tag/user/mime) from URL
|
||||
const getContext = () => {
|
||||
const ctx = {};
|
||||
const tagMatch = window.location.pathname.match(/\/tag\/([^/]+)/);
|
||||
if (tagMatch) ctx.tag = decodeURIComponent(tagMatch[1]);
|
||||
const userMatch = window.location.pathname.match(/\/user\/([^/]+)/);
|
||||
if (userMatch) ctx.user = decodeURIComponent(userMatch[1]);
|
||||
const mimeMatch = window.location.pathname.match(/\/(image|audio|video)(?:\/|$)/);
|
||||
if (mimeMatch) ctx.mime = mimeMatch[1];
|
||||
return ctx;
|
||||
};
|
||||
|
||||
// Build URL path for history
|
||||
const buildUrl = (page) => {
|
||||
const ctx = getContext();
|
||||
let path = '/';
|
||||
if (ctx.tag) path += `tag/${ctx.tag}/`;
|
||||
if (ctx.user) path += `user/${ctx.user}/`;
|
||||
if (ctx.mime) path += `${ctx.mime}/`;
|
||||
if (page > 1) path += `p/${page}`;
|
||||
return path.replace(/\/$/, '') || '/';
|
||||
};
|
||||
|
||||
// Fetch and append more items
|
||||
const loadMoreItems = async () => {
|
||||
if (infiniteState.loading || !infiniteState.hasMore) return;
|
||||
|
||||
infiniteState.loading = true;
|
||||
const foot = document.querySelector("div#footbar");
|
||||
if (foot) {
|
||||
foot.innerHTML = '<span class="loading-spinner">Loading...</span>';
|
||||
foot.style.color = 'var(--footbar-color)';
|
||||
}
|
||||
|
||||
const nextPage = infiniteState.currentPage + 1;
|
||||
const ctx = getContext();
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.append('page', nextPage);
|
||||
if (ctx.tag) params.append('tag', ctx.tag);
|
||||
if (ctx.user) params.append('user', ctx.user);
|
||||
if (ctx.mime) params.append('mime', ctx.mime);
|
||||
|
||||
try {
|
||||
const response = await fetch(`/ajax/items?${params.toString()}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.html) {
|
||||
// Append new thumbnails
|
||||
postsContainer.insertAdjacentHTML('beforeend', data.html);
|
||||
|
||||
// Update state
|
||||
infiniteState.currentPage = data.currentPage;
|
||||
infiniteState.hasMore = data.hasMore;
|
||||
|
||||
// Update URL
|
||||
history.replaceState({}, '', buildUrl(infiniteState.currentPage));
|
||||
|
||||
// Update pagination display if exists
|
||||
const paginationLinks = document.querySelectorAll('.pagination .pagination-int-item, .pagination .btn');
|
||||
paginationLinks.forEach(el => {
|
||||
if (el.textContent.trim() == infiniteState.currentPage) {
|
||||
el.classList.add('disabled');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
infiniteState.hasMore = false;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Infinite scroll fetch error:', err);
|
||||
} finally {
|
||||
infiniteState.loading = false;
|
||||
if (foot) {
|
||||
foot.innerHTML = infiniteState.hasMore ? '▼' : '—';
|
||||
foot.style.color = 'transparent';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Scroll detection
|
||||
let tts = 0;
|
||||
const scroll_treshold = 1;
|
||||
|
||||
document.addEventListener("wheel", e => {
|
||||
if (!document.querySelector('#main')) return;
|
||||
|
||||
if (Math.ceil(window.innerHeight + window.scrollY) >= document.querySelector('#main').offsetHeight && e.deltaY > 0) { // down
|
||||
if (elem = document.querySelector(".pagination > .next:not(.disabled)")) {
|
||||
if (Math.ceil(window.innerHeight + window.scrollY) >= document.querySelector('#main').offsetHeight && e.deltaY > 0) {
|
||||
// Scrolling down at bottom
|
||||
if (infiniteState.hasMore && !infiniteState.loading) {
|
||||
if (tts < scroll_treshold) {
|
||||
const foot = document.querySelector("div#footbar");
|
||||
if (foot) {
|
||||
@@ -351,43 +457,25 @@ window.requestAnimFrame = (function () {
|
||||
foot.style.color = "var(--footbar-color)";
|
||||
}
|
||||
tts++;
|
||||
} else {
|
||||
loadMoreItems();
|
||||
tts = 0;
|
||||
}
|
||||
else
|
||||
changePage(elem);
|
||||
}
|
||||
}
|
||||
else if (window.scrollY <= 0 && e.deltaY < 0) { // up
|
||||
if (elem = document.querySelector(".pagination > .prev:not(.disabled)")) {
|
||||
if (tts < scroll_treshold) {
|
||||
const nav = document.querySelector("nav.navbar");
|
||||
if (nav) {
|
||||
nav.style.boxShadow = "0px 2px 0px var(--loading-indicator-color)";
|
||||
nav.style.transition = ".2s ease-in-out";
|
||||
}
|
||||
tts++;
|
||||
}
|
||||
else
|
||||
changePage(elem);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else if (window.scrollY <= 0 && e.deltaY < 0) {
|
||||
// Scrolling up at top - could load previous page if needed (optional)
|
||||
tts = 0;
|
||||
} else {
|
||||
tts = 0;
|
||||
const foot = document.querySelector("div#footbar");
|
||||
if (foot) {
|
||||
foot.style.boxShadow = "unset";
|
||||
foot.style.color = "transparent";
|
||||
}
|
||||
const nav = document.querySelector("nav.navbar");
|
||||
if (nav) nav.style.boxShadow = "unset";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const rmatch = /\/p\/(\d+?)/;
|
||||
if (document.referrer.match(rmatch) && document.location.href.match(rmatch))
|
||||
if (document.location.href.match(rmatch) < document.referrer.match(rmatch))
|
||||
document.body.scrollTop = document.body.scrollHeight;
|
||||
// </scroller>
|
||||
// </infinite-scroll>
|
||||
|
||||
// <swipe>
|
||||
const swipeRT = {
|
||||
|
||||
Reference in New Issue
Block a user