(function () { const $ = (s, r = document) => r.querySelector(s); const $$ = (s, r = document) => Array.from(r.querySelectorAll(s)); // Kopiuj: cały widok $('#btn-copy-overview')?.addEventListener('click', async () => { try { await navigator.clipboard.writeText(document.body.innerText); window.showToast?.({ text: 'Skopiowano podsumowanie.', variant: 'success' }); } catch { window.showToast?.({ text: 'Nie udało się skopiować.', variant: 'danger' }); } }); // Eksport CSV z DOM (GEO + REASONS) $('#btn-export-overview')?.addEventListener('click', () => { const lines = []; lines.push('section,key,count,percent'); // GEO: z tabeli $$('#geo-table tbody tr').forEach(tr => { const tds = tr.querySelectorAll('td'); if (tds.length !== 3) return; const country = tds[0]?.innerText.trim(); const percent = (tds[1]?.querySelector('.text-secondary')?.innerText.trim() || '').replace('%', ''); const count = tds[2]?.innerText.trim(); if (country) lines.push(`geo,"${country.replace(/"/g, '""')}",${count},${percent}`); }); // REASONS: z listy $$('.card:has(.card-header:contains("Przyczyny banów")) .list-group-item').forEach(li => { const label = li.querySelector('.text-truncate')?.getAttribute('title') || li.querySelector('.text-truncate')?.innerText || ''; const meta = li.querySelector('.small.text-secondary')?.innerText || ''; // "123 (45.6%)" const m = meta.match(/(\d+)\s*\(([\d.,]+)%\)/); const count = m ? m[1] : ''; const percent = m ? m[2].replace(',', '.') : ''; if (label) lines.push(`reason,"${label.replace(/"/g, '""')}",${count},${percent}`); }); const csv = lines.join('\n'); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'stats_overview.csv'; a.click(); URL.revokeObjectURL(url); }); // Polyfill :contains dla selektora użytego wyżej (prosty, lokalny) (function addContainsPseudo() { const _matches = Element.prototype.matches; if (!document.querySelector(':contains(dummy)')) { const oldQuerySelectorAll = Document.prototype.querySelectorAll; Document.prototype.querySelectorAll = function (sel) { if (!sel.includes(':contains(')) return oldQuerySelectorAll.call(this, sel); const m = sel.match(/^(.*):has\(\.card-header:contains\("([^"]+)"\)\)\s*(.*)$/); if (m) { const [, pre, text, post] = m; return $$(pre + ' .card').filter(card => { return card.querySelector('.card-header')?.textContent.includes(text); }).flatMap(card => card.querySelectorAll(post || '')); } return oldQuerySelectorAll.call(this, sel); }; Element.prototype.matches = function (sel) { if (!sel.includes(':contains(')) return _matches.call(this, sel); const m = sel.match(/^:contains\("([^"]+)"\)$/); if (m) return this.textContent.includes(m[1]); return _matches.call(this, sel); }; } })(); })();