/**
* Simple WYSIWYG Editor
* Lightweight rich text editor for publication content
*/
class WYSIWYGEditor {
constructor(textareaId, options = {}) {
this.textarea = document.getElementById(textareaId);
this.options = {
toolbar: ['bold', 'italic', 'underline', '|', 'link', 'image', '|', 'ul', 'ol', '|', 'h1', 'h2', 'h3'],
...options
};
this.selectedImages = [];
this.createEditor();
this.bindEvents();
this.setupImageUpload();
}
createEditor() {
// Create editor container
this.container = document.createElement('div');
this.container.className = 'wysiwyg-container';
// Create toolbar
this.toolbar = document.createElement('div');
this.toolbar.className = 'wysiwyg-toolbar';
this.createToolbarButtons();
// Create content area
this.content = document.createElement('div');
this.content.className = 'wysiwyg-content';
this.content.contentEditable = true;
// Create character count
this.charCount = document.createElement('div');
this.charCount.className = 'wysiwyg-char-count';
// Assemble editor
this.container.appendChild(this.toolbar);
this.container.appendChild(this.content);
this.container.appendChild(this.charCount);
// Replace textarea
this.textarea.parentNode.insertBefore(this.container, this.textarea);
this.textarea.style.display = 'none';
// Initialize content
this.content.innerHTML = this.textarea.value;
this.updateCharCount();
}
createToolbarButtons() {
this.options.toolbar.forEach(item => {
if (item === '|') {
const separator = document.createElement('div');
separator.className = 'wysiwyg-separator';
this.toolbar.appendChild(separator);
} else {
const button = document.createElement('button');
button.className = 'wysiwyg-btn';
button.type = 'button';
button.innerHTML = this.getButtonLabel(item);
button.dataset.command = item;
button.addEventListener('click', () => this.execCommand(item));
this.toolbar.appendChild(button);
}
});
}
getButtonLabel(command) {
const labels = {
'bold': 'B',
'italic': 'I',
'underline': 'U',
'link': '🔗',
'image': '🖼️',
'ul': '• List',
'ol': '1. List',
'h1': 'H1',
'h2': 'H2',
'h3': 'H3'
};
return labels[command] || command;
}
execCommand(command) {
switch (command) {
case 'bold':
document.execCommand('bold', false, null);
break;
case 'italic':
document.execCommand('italic', false, null);
break;
case 'underline':
document.execCommand('underline', false, null);
break;
case 'link':
this.insertLink();
break;
case 'image':
this.insertImage();
break;
case 'ul':
document.execCommand('insertUnorderedList', false, null);
break;
case 'ol':
document.execCommand('insertOrderedList', false, null);
break;
case 'h1':
this.formatHeading('h1');
break;
case 'h2':
this.formatHeading('h2');
break;
case 'h3':
this.formatHeading('h3');
break;
}
this.content.focus();
}
insertLink() {
const selection = window.getSelection();
const url = prompt('Enter URL:');
if (url) {
document.execCommand('createLink', false, url);
}
}
insertImage() {
this.openImageGallery();
}
openImageGallery() {
this.selectedImages = [];
this.loadGalleryImages();
document.getElementById('imageGallery').classList.add('open');
}
closeImageGallery() {
document.getElementById('imageGallery').classList.remove('open');
this.selectedImages = [];
this.updateInsertButton();
}
showGalleryTab(tab) {
// Hide all tabs
document.getElementById('galleryBrowse').style.display = 'none';
document.getElementById('galleryUpload').style.display = 'none';
// Remove active class from all tabs
document.querySelectorAll('.gallery-tab').forEach(tab => {
tab.classList.remove('active');
});
// Show selected tab and add active class
if (tab === 'browse') {
document.getElementById('galleryBrowse').style.display = 'block';
document.querySelectorAll('.gallery-tab')[0].classList.add('active');
} else if (tab === 'upload') {
document.getElementById('galleryUpload').style.display = 'block';
document.querySelectorAll('.gallery-tab')[1].classList.add('active');
}
}
async loadGalleryImages() {
try {
const response = await fetch('upload_image.php');
const data = await response.json();
if (data.success) {
this.renderGalleryImages(data.images);
} else {
console.error('Failed to load images:', data.error);
}
} catch (error) {
console.error('Error loading images:', error);
}
}
renderGalleryImages(images) {
const grid = document.getElementById('galleryGrid');
grid.innerHTML = '';
images.forEach(image => {
const item = document.createElement('div');
item.className = 'gallery-item';
item.dataset.imageId = image.id;
item.dataset.imageUrl = image.url;
item.dataset.imageName = image.original_name;
item.innerHTML = `