`;
for (const groupName in result.groups) {
html += `
`;
}
resultsContainer.innerHTML = html;
};
// --- CORE LOGIC ---
const handleGrouping = () => {
groupBtnSpinner.classList.remove('hidden');
groupBtnText.textContent = 'Grouping...';
groupBtn.disabled = true;
setTimeout(() => {
const keywords = keywordsInput.value.split('\n').map(k => k.trim()).filter(Boolean);
const grouped = {};
const uncategorized = [];
const preparedGroups = keywordGroups.map(g => ({
name: g.name,
concepts: g.concepts.split(',').map(c => c.trim().toLowerCase()).filter(Boolean)
}));
keywords.forEach(keyword => {
let found = false;
const lowerKeyword = keyword.toLowerCase();
for (const group of preparedGroups) {
if (group.concepts.some(concept => lowerKeyword.includes(concept))) {
if (!grouped[group.name]) grouped[group.name] = [];
grouped[group.name].push(keyword);
found = true;
break;
}
}
if (!found) uncategorized.push(keyword);
});
if(uncategorized.length > 0) {
grouped['Uncategorized'] = uncategorized;
}
const result = {
groups: grouped,
totalKeywords: keywords.length,
totalGroups: Object.keys(grouped).length
};
renderDashboard(result);
downloadPdfBtn.disabled = false;
groupBtnSpinner.classList.add('hidden');
groupBtnText.textContent = 'Group Keywords';
groupBtn.disabled = false;
}, 800);
};
// --- UI & EVENT HANDLERS ---
const switchTab = (tabId) => {
currentTab = tabId;
Object.values(tabPanes).forEach(pane => pane.classList.add('hidden'));
tabPanes[tabId].classList.remove('hidden');
Object.values(tabButtons).forEach(btn => btn.classList.replace('tab-active', 'tab-inactive'));
tabButtons[tabId].classList.replace('tab-inactive', 'tab-active');
updateNavButtons();
};
const navigateTabs = (direction) => {
const currentIndex = tabs.indexOf(currentTab);
const newIndex = direction === 'next' ? currentIndex + 1 : currentIndex - 1;
if (newIndex >= 0 && newIndex < tabs.length) switchTab(tabs[newIndex]);
};
const updateNavButtons = () => {
const currentIndex = tabs.indexOf(currentTab);
prevBtn.disabled = currentIndex === 0;
nextBtn.disabled = currentIndex === tabs.length - 1;
prevBtn.classList.toggle('opacity-50', prevBtn.disabled);
nextBtn.classList.toggle('opacity-50', nextBtn.disabled);
};
const handlePdfDownload = () => {
const pdfRenderContainer = document.getElementById('pdf-render-content');
const pdfContent = document.getElementById('pdf-content').innerHTML;
const header = `';
html2canvas(pdfRenderContainer, { scale: 2 }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth(), margin = 40;
const contentWidth = pdfWidth - margin * 2;
const pdfHeight = (canvas.height * contentWidth) / canvas.width;
pdf.addImage(imgData, 'PNG', margin, margin, contentWidth, pdfHeight);
pdf.save('Keyword-Grouping-Report.pdf');
});
};
// --- EVENT LISTENERS ---
window.switchTab = switchTab;
window.navigateTabs = navigateTabs;
groupBtn.addEventListener('click', handleGrouping);
downloadPdfBtn.addEventListener('click', handlePdfDownload);
addAssociationBtn.addEventListener('click', () => {
keywordGroups.push({ id: nextId++, name: '', concepts: '' });
renderConfig();
});
configContainer.addEventListener('input', e => {
const id = parseInt(e.target.closest('[data-id]').dataset.id);
const prop = e.target.dataset.prop;
const item = keywordGroups.find(a => a.id === id);
if (item) item[prop] = e.target.value;
});
configContainer.addEventListener('click', e => {
if (!e.target.classList.contains('rm-btn')) return;
const id = parseInt(e.target.closest('[data-id]').dataset.id);
keywordGroups = keywordGroups.filter(a => a.id !== id);
renderConfig();
});
// --- INITIALIZATION ---
initialize();
});
${groupName} (${result.groups[groupName].length} keywords)
-
${result.groups[groupName].map(kw => `
- ${kw} `).join('')}
