You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

86 lines
2.8 KiB

(function() {
const configElement = document.querySelector('script[data-cloudflare-page-counter-config]');
const config = configElement ? JSON.parse(configElement.textContent || '{}') : {};
const endpoint = (config.endpoint || '').replace(/\/$/, '');
const cacheEnabled = config.local_cache !== false;
const cachePrefix = `cloudflare-page-counter:${config.site || location.hostname}:`;
if (!endpoint) return;
const normalizePath = path => {
try {
const url = new URL(path, location.origin);
return decodeURI(url.pathname.replace(/\/index\.html$/, '/'));
} catch (error) {
return decodeURI(path || location.pathname);
}
};
const request = payload => {
const controller = new AbortController();
const timeout = Number(config.timeout) || 5000;
const timer = setTimeout(() => controller.abort(), timeout);
return fetch(endpoint, {
method : 'POST',
headers: {
'Content-Type': 'application/json'
},
body : JSON.stringify(payload),
credentials: 'omit',
signal : controller.signal
}).then(response => {
clearTimeout(timer);
if (!response.ok) throw new Error(`Counter request failed: ${response.status}`);
return response.json();
});
};
const render = counts => {
document.querySelectorAll('.cloudflare-page-counter').forEach(element => {
const path = normalizePath(element.dataset.path);
const count = counts[path];
const target = element.querySelector('.cloudflare-page-counter-count');
if (target && typeof count === 'number') target.innerText = count;
});
};
const loadCounters = () => {
const elements = [...document.querySelectorAll('.cloudflare-page-counter')];
if (!elements.length) return;
const entries = elements.map(element => ({
path : normalizePath(element.dataset.path),
title: element.dataset.title || document.title
}));
const hitIndex = elements.findIndex(element => element.dataset.increment === 'true');
let action = hitIndex === -1 ? 'get' : 'hit';
let selectedEntries = entries;
if (action === 'hit') {
const key = cachePrefix + entries[hitIndex].path;
selectedEntries = [entries[hitIndex]];
if (cacheEnabled && localStorage.getItem(key)) {
action = 'get';
selectedEntries = entries;
} else if (cacheEnabled) {
localStorage.setItem(key, String(Date.now()));
}
}
request({
action,
site : config.site || location.hostname,
entries: selectedEntries
}).then(data => {
render(data.counts || {});
}).catch(error => {
console.error('Cloudflare Page Counter Error', error);
});
};
document.addEventListener('DOMContentLoaded', loadCounters);
document.addEventListener('page:loaded', loadCounters);
})();