/**
* Pricify - Auto-Refresh & Data Loading Module
* Polls /api/proxy.php for live price updates, loads chart data,
* and provides debounced asset search with dropdown rendering.
* Vanilla JS, no frameworks, no module exports.
*/
/* ============================================================
Configuration
============================================================ */
const PROXY_URL = '/api/proxy.php';
const DEFAULT_REFRESH_INTERVAL = 30000; // 30 seconds
const SEARCH_DEBOUNCE_MS = 300;
/* ============================================================
startAutoRefresh — periodic price-data refresh
------------------------------------------------------------
section : 'crypto' | 'stocks' | 'indices' — maps to proxy action
intervalMs: polling interval in ms (default 30000)
============================================================ */
/**
* Start an interval-based auto-refresh that fetches price data
* from the API proxy and updates table rows identified by
* data-symbol attributes. Cells with .price-cell and
* .change-cell get updated. A brief flash animation is applied
* to indicate fresh data.
* Returns the interval id (for clearInterval later).
*/
function startAutoRefresh(section, intervalMs) {
try {
const ms = intervalMs || DEFAULT_REFRESH_INTERVAL;
// Map section to proxy action
const actionMap = {
crypto: 'crypto-top',
stocks: 'stocks-list',
indices: 'indices',
};
const action = actionMap[section] || 'crypto-top';
// Immediate first fetch
fetchAndUpdatePrices(action, section);
// Periodic refresh
const intervalId = setInterval(function () {
fetchAndUpdatePrices(action, section);
}, ms);
return intervalId;
} catch (err) {
console.error('[refresh] startAutoRefresh error:', err);
return null;
}
}
/* ============================================================
fetchAndUpdatePrices — internal: fetch + DOM update
============================================================ */
/**
* Fetch price data from proxy and update visible DOM elements
* (price cells, change indicators). Called both on init and
* on each refresh tick.
*/
async function fetchAndUpdatePrices(action, section) {
try {
const url = PROXY_URL + '?action=' + encodeURIComponent(action);
const response = await fetch(url);
if (!response.ok) {
console.warn('[refresh] HTTP error:', response.status);
return;
}
const result = await response.json();
if (!result.success || !Array.isArray(result.data)) {
console.warn('[refresh] API returned no data');
return;
}
// Update each asset row in the DOM
result.data.forEach(function (asset) {
updateAssetRow(asset, section);
});
} catch (err) {
console.error('[refresh] fetchAndUpdatePrices error:', err);
}
}
/* ============================================================
updateAssetRow — update a single table row
============================================================ */
/**
* Update
elements that have data-symbol matching the asset.
* Updates price cells (.price-cell), change cells (.change-cell),
* and appends a brief CSS animation class for user feedback.
*/
function updateAssetRow(asset, section) {
try {
const symbol = asset.symbol || asset.ticker || '';
if (!symbol) return;
const rows = document.querySelectorAll(
'tr[data-symbol="' + CSS.escape(symbol) + '"]'
);
if (!rows.length) return;
const price = parseFloat(asset.price || asset.nav || 0);
const change = parseFloat(asset.change || asset.change_pct || 0);
const changePct = parseFloat(asset.change_pct || asset.change || 0);
rows.forEach(function (row) {
// Update price cell
const priceCell = row.querySelector('.price-cell');
if (priceCell) {
priceCell.textContent = formatPrice(price);
priceCell.className = 'price-cell ' + changeClass(change);
}
// Update change cell
const changeCell = row.querySelector('.change-cell');
if (changeCell) {
const sign = change >= 0 ? '+' : '';
changeCell.textContent = sign + changePct.toFixed(2) + '%';
changeCell.className = 'change-cell ' + changeClass(change);
}
// Brief flash animation to signal update
row.classList.remove('flash-update');
// Force reflow so the animation re-triggers
void row.offsetWidth;
row.classList.add('flash-update');
setTimeout(function () {
row.classList.remove('flash-update');
}, 800);
});
} catch (err) {
console.error('[refresh] updateAssetRow error:', err);
}
}
/* ============================================================
loadChartData — fetch chart data and render via Chart.js
------------------------------------------------------------
symbol : Asset ticker / symbol (e.g. 'BTC', 'RELIANCE')
range : Time range string (e.g. '1d', '1w', '1m', '1y')
canvasId :