tp_servicedesk/public/js/markdown_preview.js

73 lines
2.2 KiB
JavaScript

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 = `
<div class="skeleton-lines">
<div></div><div></div><div></div><div></div><div></div>
</div>
`;
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'
});
});