class InfiniteScroll { constructor(options = {}) { this.container = document.getElementById('items-thumbs'); this.initialItemCount = this.container ? this.container.children.length : 0; if (!this.container || this.initialItemCount < 12) { // console.log('Not enough items for infinite scroll, skipping initialization'); if (window.location.href.includes('page=')) { const cleanUrl = window.location.href.replace(/[&?]page=\d+/, '').replace(/\?$/, ''); window.history.replaceState({}, '', cleanUrl); } return; } this.loadingElement = this.createLoadingElement(); this.page = 1; this.loading = false; this.isFullListingPage = this.isAllWatchesOrHome(); this.hasMore = true; this.lastCount = this.initialItemCount; this.loadedOnce = false; this.allItemsLoaded = !this.isFullListingPage && this.initialItemCount < 96; this.baseURI = window.location.href.replace(/[&?]page=\d+/, '').replace(/\?$/, ''); // Add a Set to track loaded item IDs this.loadedItems = new Set(); this.initializeLoadedItems(); this.init(); } // Initialize the loadedItems Set with current items' stock IDs initializeLoadedItems() { const currentItems = this.container.querySelectorAll('img[alt]'); currentItems.forEach(item => { this.loadedItems.add(item.getAttribute('alt')); }); } isAllWatchesOrHome() { const url = window.location.href; return url.includes('all-watches') || url.endsWith('/preowned/') || url.endsWith('/preowned'); } createLoadingElement() { const div = document.createElement('div'); div.className = 'loading-spinner'; div.innerHTML = `
Loading More Items
`; div.style.display = 'none'; document.body.appendChild(div); return div; } init() { // Hide the see-more button const seeMoreBtn = document.getElementById('see-more'); if (seeMoreBtn) { seeMoreBtn.style.display = 'none'; } window.addEventListener('scroll', () => { if (!this.loading && this.hasMore) { const scrollPosition = window.scrollY + window.innerHeight; const bottomPosition = this.container.offsetTop + this.container.offsetHeight - 500; if (scrollPosition > bottomPosition) { this.loadMore(); } } }); // Add loading spinner styles const style = document.createElement('style'); style.textContent = ` .loading-spinner { position: fixed; bottom: 300px; left: 50%; transform: translateX(-50%); z-index: 1050; background: rgba(255, 255, 255, 0.95); padding: 15px 30px; border-radius: 4px; box-shadow: 0 2px 10px rgba(0,0,0,0.2); min-width: 200px; } .loading-dots:after { content: ''; animation: dots 2s steps(4, end) infinite; } @keyframes dots { 0%, 20% { content: ''; } 40% { content: '.'; } 60% { content: '..'; } 80%, 100% { content: '...'; } } `; document.head.appendChild(style); } displayItems(obj) { var itemsObj = obj.watches; var out = ""; // Filter out duplicate items itemsObj = itemsObj.filter(item => !this.loadedItems.has(item.stock_id)); for (var i = 0; i < itemsObj.length; i++) { // Add stock_id to loadedItems Set this.loadedItems.add(itemsObj[i].stock_id); out = out + '
' + '' + '
' + (itemsObj[i].on_special == 1 ? '
' : '') + '' + itemsObj[i].stock_id + '' + '

' + itemsObj[i].brand + '

' + '
' + (itemsObj[i].accessory_type_id !== null ? itemsObj[i].accessory_type : itemsObj[i].series) + '
' + '
' + '
'+itemsObj[i].status+'
' + '
'; if (itemsObj[i].status_id == 1 || itemsObj[i].status_id == 3) { if (itemsObj[i].on_special == 1) out = out + '$' + this.numberFormat(itemsObj[i].selling_price, 0) + ''; else out = out + '$' + this.numberFormat(itemsObj[i].selling_price, 0); } out = out + '
'; if (itemsObj[i].on_special == 1 && (itemsObj[i].status_id == 1 || itemsObj[i].status_id == 3)) { out = out + '
Special Price: $' + this.numberFormat(itemsObj[i].special_price, 0) + '
'; } out = out + '
'; } return out; } numberFormat(number, decimals) { // Convert to number if it's a string const num = typeof number === 'string' ? parseFloat(number.replace(/,/g, '')) : number; return num.toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); } async loadMore() { if (this.initialItemCount < 12 || this.allItemsLoaded) { this.hasMore = false; return; } if (this.loading || !this.hasMore) return; this.loading = true; this.loadingElement.style.display = 'block'; try { const separator = this.baseURI.includes('?') ? '&' : '?'; const nextPage = this.page + 1; const url = `${this.baseURI}${separator}page=${nextPage}&ajax=1`; const response = await fetch(url); if (!response.ok) { this.hasMore = false; return; } const result = await response.json(); if (!result.watches || result.watches.length === 0) { this.hasMore = false; return; } // Append new items (duplicates are now filtered in displayItems) const newItems = this.displayItems(result); if (newItems.trim() === '') { // If no new unique items were found, stop loading this.hasMore = false; this.allItemsLoaded = true; return; } this.container.insertAdjacentHTML('beforeend', newItems); if (this.isFullListingPage) { this.loadedOnce = true; if (window.location.href.endsWith('/preowned/') || window.location.href.endsWith('/preowned')) { // For home page, stop after first load this.hasMore = false; this.allItemsLoaded = true; } } this.page = nextPage; // Update URL and metadata const newUrl = `${this.baseURI}${separator}page=${this.page}`; window.history.pushState({ page: this.page }, '', newUrl); document.title = document.title + " - Page " + this.page; const metaDesc = document.querySelector('meta[name=description]'); if (metaDesc) { metaDesc.setAttribute('content', metaDesc.getAttribute('content') + " Page " + this.page); } } catch (error) { console.error('Error loading items:', error); this.hasMore = false; } finally { this.loading = false; this.loadingElement.style.display = 'none'; } } } // Initialize when DOM is ready document.addEventListener('DOMContentLoaded', function() { new InfiniteScroll(); });