Forum / static /js /editor.js
kuro223's picture
o9
91073d4
document.addEventListener('DOMContentLoaded', function() {
// Initialize editor toolbar functionality
initializeEditor();
});
/**
* Initialize the editor toolbar and functionality
*/
function initializeEditor() {
const editorContainer = document.querySelector('.editor-container');
if (!editorContainer) return;
const textarea = editorContainer.querySelector('textarea');
const toolbar = editorContainer.querySelector('.editor-toolbar');
if (!textarea || !toolbar) return;
// Set up toolbar buttons
setupToolbarButtons(toolbar, textarea);
// Add input handler for tab key
textarea.addEventListener('keydown', function(e) {
// Handle tab key for indentation
if (e.key === 'Tab') {
e.preventDefault();
const start = this.selectionStart;
const end = this.selectionEnd;
// Set textarea value to: text before + tab + text after
this.value = this.value.substring(0, start) + " " + this.value.substring(end);
// Set cursor position after the inserted tab
this.selectionStart = this.selectionEnd = start + 4;
}
});
}
/**
* Set up the toolbar buttons for the editor
* @param {HTMLElement} toolbar - The toolbar element
* @param {HTMLTextAreaElement} textarea - The textarea element
*/
function setupToolbarButtons(toolbar, textarea) {
// Define toolbar buttons and their actions
const buttons = [
{
name: 'bold',
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"></path><path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"></path></svg>',
action: (text) => wrapText(textarea, '[b]', '[/b]')
},
{
name: 'italic',
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="4" x2="10" y2="4"></line><line x1="14" y1="20" x2="5" y2="20"></line><line x1="15" y1="4" x2="9" y2="20"></line></svg>',
action: (text) => wrapText(textarea, '[i]', '[/i]')
},
{
name: 'underline',
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3"></path><line x1="4" y1="21" x2="20" y2="21"></line></svg>',
action: (text) => wrapText(textarea, '[u]', '[/u]')
},
{
name: 'link',
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>',
action: (text) => insertLink(textarea)
},
{
name: 'image',
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>',
action: (text) => insertImage(textarea)
},
{
name: 'code',
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>',
action: (text) => wrapText(textarea, '[code]', '[/code]')
},
{
name: 'quote',
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21c3.87-7.05 5.02-13.54 5.02-13.54 0-3.31 2.67-5.99 5.98-6 3.31 0 6 2.68 6 5.99 0 3.31-2.69 6.01-6 6.01h-2c.73 2 2.97 3.02 5.02 3.02-1.59 1.38-3.09 2.51-5.02 3.53C9.08 21.42 6.24 21.43 3 21z"></path></svg>',
action: (text) => wrapText(textarea, '[quote]', '[/quote]')
}
];
// Create buttons
buttons.forEach(button => {
const btn = document.createElement('button');
btn.type = 'button';
btn.setAttribute('aria-label', button.name);
btn.innerHTML = button.icon;
btn.classList.add('editor-button');
btn.addEventListener('click', () => {
button.action();
textarea.focus(); // Return focus to textarea
});
toolbar.appendChild(btn);
});
}
/**
* Wrap selected text with BBCode tags
* @param {HTMLTextAreaElement} textarea - The textarea element
* @param {string} openTag - The opening tag
* @param {string} closeTag - The closing tag
*/
function wrapText(textarea, openTag, closeTag) {
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
const selectedText = textarea.value.substring(start, end);
const replacement = openTag + selectedText + closeTag;
textarea.value = textarea.value.substring(0, start) + replacement + textarea.value.substring(end);
// Adjust selection to be between the tags
textarea.selectionStart = start + openTag.length;
textarea.selectionEnd = start + openTag.length + selectedText.length;
}
/**
* Insert a link BBCode
* @param {HTMLTextAreaElement} textarea - The textarea element
*/
function insertLink(textarea) {
const selectedText = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd);
let url = prompt('Enter the URL:', 'http://');
if (!url) return;
let text = selectedText || prompt('Enter the link text:', '');
if (!text) text = url;
const linkBBCode = `[url=${url}]${text}[/url]`;
insertAtCursor(textarea, linkBBCode);
}
/**
* Insert an image BBCode
* @param {HTMLTextAreaElement} textarea - The textarea element
*/
function insertImage(textarea) {
const url = prompt('Enter the image URL:', 'http://');
if (!url) return;
const imageBBCode = `[img]${url}[/img]`;
insertAtCursor(textarea, imageBBCode);
}
/**
* Insert text at cursor position
* @param {HTMLTextAreaElement} textarea - The textarea element
* @param {string} text - The text to insert
*/
function insertAtCursor(textarea, text) {
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
textarea.value = textarea.value.substring(0, start) + text + textarea.value.substring(end);
// Set selection after inserted text
textarea.selectionStart = textarea.selectionEnd = start + text.length;
}