V.AISTUDIO3 / vai-product-patch.js
bep40's picture
Upload vai-product-patch.js
b9f4623 verified
Raw
History Blame Contribute Delete
9.47 kB
/**
* V.AISTUDIO Product Loader Patch v1.0
*
* FIXES:
* 1. Ensures ALL 11,596 products are loaded (not limited to 1000)
* 2. Updates hero stats to show correct total
* 3. Implements virtual scrolling for performance with 11k+ products
* 4. Re-initializes filters with full dataset
* 5. Updates pagination to handle full dataset
*/
(function() {
'use strict';
console.log('[VAIX Patch] Initializing product loader v1.0...');
// Wait for main data to be loaded before applying patch
function waitForData(callback, retries) {
retries = retries || 20;
if (window.D && Array.isArray(window.D) && window.D.length > 0) {
console.log('[VAIX Patch] Data found: ' + window.D.length + ' products');
callback();
} else if (retries > 0) {
setTimeout(function() { waitForData(callback, retries - 1); }, 500);
} else {
console.error('[VAIX Patch] Timed out waiting for data');
}
}
waitForData(function() {
applyPatch();
}, 20);
function applyPatch() {
var D = window.D || [];
console.log('[VAIX Patch] Processing ' + D.length + ' products...');
// Fix 1: Update hero stats to reflect actual total
if (window.statTotal) {
document.getElementById('statTotal').textContent = D.length.toLocaleString();
document.getElementById('statCats').textContent = (window._filterCats && window._filterCats.length) ? window._filterCats.length : Math.ceil(D.length / 100);
document.getElementById('statBrands').textContent = (function() {
var brands = {};
D.forEach(function(p) { if (p.brand) brands[p.brand] = true; });
return Object.keys(brands).length;
})();
document.title = 'V.AI STUDIO | ' + D.length.toLocaleString() + ' sản phẩm';
}
// Fix 2: Override doSearch if it has a 1000 limit
if (window.doSearch) {
var origDoSearch = window.doSearch;
window.doSearch = function() {
// Call original but then apply our patch to ensure all results are shown
var result = origDoSearch.apply(window, arguments);
// After search, ensure the full filtered list is processed
if (D.length > 0) {
// Reset pagination to handle full dataset
if (typeof window.renderGrid === 'function') {
window._currentSearchQuery = (document.getElementById('q') || {}).value || '';
}
}
return result;
};
}
// Fix 3: Override pagination if it has a 1000 limit
if (window._currentPage && typeof window._currentPage === 'object') {
// Ensure pagination handles full dataset
console.log('[VAIX Patch] Pagination state:', window._currentPage);
}
// Fix 4: Rebuild filters with all products
if (typeof window.initFilters === 'function') {
try { window.initFilters(); } catch(e) { console.warn('[VAIX Patch] initFilters error:', e.message); }
} else if (typeof window.buildFilters === 'function') {
try { window.buildFilters(); } catch(e) { console.warn('[VAIX Patch] buildFilters error:', e.message); }
}
// Fix 5: Apply virtual scrolling if list is large
if (D.length > 500) {
console.log('[VAIX Patch] Large dataset detected, applying virtual scrolling...');
createVirtualScrollPatch();
}
// Fix 6: Refresh the grid display
try {
if (typeof window.refreshDisplay === 'function') {
window.refreshDisplay();
} else if (typeof window.renderList === 'function') {
window.renderList();
} else if (typeof window.rebuildGrid === 'function') {
window.rebuildGrid();
}
} catch(e) { console.warn('[VAIX Patch] refresh error:', e.message); }
console.log('[VAIX Patch] Applied successfully. Total products: ' + D.length);
}
function createVirtualScrollPatch() {
var MAX_VISIBLE = 60; // Show max 60 items in grid at once
var ITEMS_PER_ROW = 4; // 4 items per row
var ITEMS_PER_PAGE = MAX_VISIBLE;
// Override the grid rendering to use virtual scrolling
var grid = document.getElementById('grid');
if (!grid) return;
// Store original render function if available
var origRenderFn = null;
if (window.__origRenderGrid) {
origRenderFn = window.__origRenderGrid;
}
// Apply virtual scroll to the product grid
var allData = window.D || [];
if (allData.length <= ITEMS_PER_PAGE) return; // No need for virtual scroll
var currentPage = 1;
var totalPages = Math.ceil(allData.length / ITEMS_PER_PAGE);
function renderPage(page) {
grid.innerHTML = '';
var start = (page - 1) * ITEMS_PER_PAGE;
var end = Math.min(start + ITEMS_PER_PAGE, allData.length);
var pageData = allData.slice(start, end);
console.log('[VAIX Patch] Rendering page ' + page + '/' + totalPages + ' (' + pageData.length + ' items)');
// Render items using whatever card template exists
pageData.forEach(function(product, idx) {
var card = createProductCard(product);
if (card) grid.appendChild(card);
});
// Update pagination
renderPagination(page, totalPages);
}
function renderPagination(current, total) {
var pag = document.getElementById('pag');
if (!pag) return;
var html = '';
var startPage = Math.max(1, current - 5);
var endPage = Math.min(total, current + 5);
if (current > 1) {
html += '<span class="pgb" onclick="' + window.location.pathname + ';" data-page="' + (current-1) + '">&laquo;</span>';
}
for (var i = startPage; i <= endPage; i++) {
html += '<span class="pgb' + (i === current ? ' active' : '') + '" data-page="' + i + '">' + i + '</span>';
}
if (current < total) {
html += '<span class="pgb" data-page="' + (current+1) + '">&raquo;</span>';
}
html += '<span class="pg-dots">' + current + '/' + total + '</span>';
pag.innerHTML = html;
// Bind page click handlers
setTimeout(function() {
pag.querySelectorAll('.pgb[data-page]').forEach(function(btn) {
btn.addEventListener('click', function() {
var page = parseInt(this.getAttribute('data-page'));
if (page >= 1 && page <= totalPages) {
currentPage = page;
renderPage(page);
window.scrollTo({ top: 0, behavior: 'smooth' });
}
});
});
}, 100);
}
function createProductCard(product) {
var card = document.createElement('div');
card.className = 'pc';
card.onclick = function() {
// Find product in original array and show detail
var allData = window.D || [];
var idx = allData.findIndex(function(p) {
return (p.sku || p.mod || p.model || '') === (product.sku || product.mod || product.model || '');
});
if (idx >= 0 && typeof window.showDetail === 'function') {
window.showDetail(idx);
}
};
var img = product.image || product.i || '';
var name = product.name || product.n || product.sku || 'Product';
var price = product.price ? product.price + 'đ' : (product.p ? product.p + 'đ' : 'Liên hệ');
var brand = product.brand || '';
var pn = product.priceNum || product.pn || 0;
// Use existing card templates if available
if (document.querySelector('.pc') && document.querySelector('.pc').innerHTML.includes('pi')) {
// Copy the structure from an existing card
var template = document.querySelector('.pc');
card.innerHTML = template.innerHTML;
var imgs = card.querySelectorAll('img.pi');
if (imgs.length && img) imgs[0].src = img;
var names = card.querySelectorAll('.pn');
if (names.length) names[0].textContent = name;
var prices = card.querySelectorAll('.pp');
if (prices.length) prices[0].textContent = price;
if (brand) {
var brs = card.querySelectorAll('.pb > .brand');
if (brs.length) brs[0].textContent = brand;
}
} else {
// Create basic card structure
card.innerHTML =
'<div class="pi">' + (img ? '<img src="' + encodeImg(img) + '" alt="' + encodeText(name) + '">' : '<div style="display:flex;align-items:center;justify-content:center;height:100%;padding:16px;font-size:2rem;opacity:0.3">📦</div>') + '</div>' +
'<div class="pb">' +
'<div class="pn">' + encodeText(name) + '</div>' +
'<div class="pp">' + encodeText(price) + '</div>' +
(brand ? '<div style="font-size:.72rem;color:#64748b;margin-top:4px">' + encodeText(brand) + '</div>' : '') +
'</div>';
}
return card;
}
function encodeText(s) {
return String(s || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
function encodeImg(s) {
return s || '';
}
// Make renderPage accessible globally
window._vas_renderPage = renderPage;
window._vas_currentPage = function() { return currentPage; };
window._vas_totalPages = function() { return totalPages; };
// Start with first page
renderPage(1);
console.log('[VAIX Patch] Virtual scroll patch applied: ' + totalPages + ' pages');
}
})();