export default class TextEditor { constructor(container, options = {}) { this.options = { charsPerPage: 500, // Default to 500 chars per page onTextChange: null, ...options }; this.container = container; this.currentPage = 1; this.pages = ['']; this.charCount = 0; this.fullText = ''; this.isTyping = false; this.setupDOM(); this.bindEvents(); } setupDOM() { this.container.innerHTML = `
`; // Cache DOM elements this.elements = { pageContent: this.container.querySelector('.page-content'), prevBtn: this.container.querySelector('.prev-btn'), nextBtn: this.container.querySelector('.next-btn'), pageInfo: this.container.querySelector('.page-info'), fileInput: this.container.querySelector('.file-input'), uploadBtn: this.container.querySelector('.upload-btn'), clearBtn: this.container.querySelector('.clear-btn'), charCount: this.container.querySelector('.char-count'), charsPerPage: this.container.querySelector('.chars-input'), formatBtn: this.container.querySelector('.format-btn') }; // Set initial chars per page value this.elements.charsPerPage.value = this.options.charsPerPage; } bindEvents() { // Handle page content changes this.elements.pageContent.addEventListener('input', (e) => { const newContent = e.target.value; this.pages[this.currentPage - 1] = newContent; // Only handle empty pages, otherwise just update the text if (!newContent.trim() && this.pages.length > 1) { // Remove the empty page and adjust this.pages.splice(this.currentPage - 1, 1); this.currentPage = Math.min(this.currentPage, this.pages.length); this.updatePageDisplay(); } // Update full text and char count - join with space since pages are just for UI this.fullText = this.pages.join(' '); this.updateCharCount(); if (this.options.onTextChange) { this.options.onTextChange(this.fullText); } }); // Navigation this.elements.prevBtn.addEventListener('click', () => { if (this.currentPage > 1) { this.currentPage--; this.updatePageDisplay(); } }); this.elements.nextBtn.addEventListener('click', () => { if (this.currentPage < this.pages.length) { this.currentPage++; this.updatePageDisplay(); } }); // File upload this.elements.uploadBtn.addEventListener('click', () => { this.elements.fileInput.click(); }); this.elements.fileInput.addEventListener('change', (e) => { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = (e) => { this.setText(e.target.result); if (this.options.onTextChange) { this.options.onTextChange(this.getText()); } }; reader.readAsText(file); } }); // Clear text this.elements.clearBtn.addEventListener('click', () => { this.clear(); if (this.options.onTextChange) { this.options.onTextChange(''); } }); // Cache format button this.elements.formatBtn = this.container.querySelector('.format-btn'); // Characters per page control - just update the value this.elements.charsPerPage.addEventListener('change', (e) => { const value = parseInt(e.target.value); if (value >= 100 && value <= 2000) { this.options.charsPerPage = value; } }); // Format pages button - trigger the split this.elements.formatBtn.addEventListener('click', () => { const value = parseInt(this.elements.charsPerPage.value); if (value >= 100 && value <= 2000) { this.options.charsPerPage = value; this.splitIntoPages(this.fullText); } }); } splitIntoPages(text) { if (!text || !text.trim()) { this.pages = ['']; this.fullText = ''; this.currentPage = 1; this.updatePageDisplay(); this.updateCharCount(); return; } // Store original text to preserve natural line breaks this.fullText = text.trim(); const words = text.trim().split(/\s+/); this.pages = []; let currentPage = ''; for (let i = 0; i < words.length; i++) { const word = words[i]; const potentialPage = currentPage + (currentPage ? ' ' : '') + word; if (potentialPage.length >= this.options.charsPerPage && currentPage) { this.pages.push(currentPage); currentPage = word; } else { currentPage = potentialPage; } } if (currentPage) { this.pages.push(currentPage); } if (this.pages.length === 0) { this.pages = ['']; this.currentPage = 1; } else { // Keep current page in bounds this.currentPage = Math.min(this.currentPage, this.pages.length); } this.updatePageDisplay(); this.updateCharCount(); } setText(text) { // Just set the text without splitting into pages this.fullText = text; this.pages = [text]; this.currentPage = 1; this.updatePageDisplay(); this.updateCharCount(); } updatePageDisplay() { this.elements.pageContent.value = this.pages[this.currentPage - 1] || ''; this.elements.pageInfo.textContent = `Page ${this.currentPage} of ${this.pages.length}`; // Update button states this.elements.prevBtn.disabled = this.currentPage === 1; this.elements.nextBtn.disabled = this.currentPage === this.pages.length; } updateCharCount() { const totalChars = this.fullText.length; this.elements.charCount.textContent = `${totalChars} characters`; } prevPage() { if (this.currentPage > 1) { this.currentPage--; this.updatePageDisplay(); } } nextPage() { if (this.currentPage < this.pages.length) { this.currentPage++; this.updatePageDisplay(); } } getText() { return this.fullText; } clear() { this.setText(''); } }