class TabSwitcherController { constructor({ tabSelector, contentPrefix, textareaSelector, previewUrl }) { this.tabSelector = tabSelector; this.contentPrefix = contentPrefix; this.textareaSelector = textareaSelector; this.previewUrl = previewUrl; this.tabParent = document.querySelector(tabSelector); this.tabLinks = this.tabParent.querySelectorAll('a'); this.init(); } init() { this.tabLinks.forEach(link => { link.addEventListener('click', (e) => this.handleTabClick(e, link)); }); } async handleTabClick(e, link) { e.preventDefault(); const selectedTab = link.getAttribute('data-tab'); // Update active tab this.tabParent.querySelectorAll('li').forEach(li => li.classList.remove('is-active')); link.parentElement.classList.add('is-active'); // Show active content document.querySelectorAll('.tab-content').forEach(el => el.style.display = 'none'); const activeContent = document.getElementById(`${this.contentPrefix}-${selectedTab}`); if (activeContent) activeContent.style.display = ''; if (selectedTab === 'preview') { await this.loadPreview(); } } async loadPreview() { const previewTarget = document.getElementById('preview-output'); if (!previewTarget) return; previewTarget.innerHTML = `
`; await new Promise(resolve => setTimeout(resolve, 500)); const textarea = document.querySelector(this.textareaSelector); const markdown = textarea ? textarea.value : ''; const res = await fetch(this.previewUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `content=${encodeURIComponent(markdown)}` }); const html = await res.text(); previewTarget.innerHTML = html; } } // Usage document.addEventListener('DOMContentLoaded', () => { new TabSwitcherController({ tabSelector: '.tabs', contentPrefix: 'tab', textareaSelector: '#description', previewUrl: '/parsedown/preview' }); });