/** * HAProxy Configuration Editor * Auto-grow textarea + CodeMirror integration */ document.addEventListener('DOMContentLoaded', function() { // Auto-grow textarea (fallback if CodeMirror fails) initAutoGrowTextarea(); // Try to initialize CodeMirror initCodeMirror(); }); /** * Initialize auto-grow textarea */ function initAutoGrowTextarea() { 'use strict'; const ta = document.getElementById('haproxy_config'); if (!ta) return; const autoGrow = () => { ta.style.height = 'auto'; ta.style.height = (ta.scrollHeight + 6) + 'px'; }; ta.addEventListener('input', autoGrow); ta.addEventListener('change', autoGrow); // Initial auto-size autoGrow(); // Resize on window resize window.addEventListener('resize', autoGrow); console.log('[Editor] Auto-grow textarea initialized'); } /** * Initialize CodeMirror editor */ function initCodeMirror() { 'use strict'; // Check if CodeMirror is available if (typeof CodeMirror === 'undefined') { console.warn('[Editor] CodeMirror not loaded, using fallback textarea'); document.getElementById('haproxy_config').style.display = 'block'; return; } try { const editorElement = document.getElementById('haproxy_editor'); if (!editorElement) { console.warn('[Editor] haproxy_editor element not found'); return; } const editor = CodeMirror.fromTextArea(editorElement, { lineNumbers: true, lineWrapping: true, indentUnit: 4, indentWithTabs: false, theme: 'material-darker', mode: 'text/x-nginx-conf', styleActiveLine: true, styleSelectedText: true, highlightSelectionMatches: { annotateScrollbar: true }, foldGutter: true, gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], matchBrackets: true, autoCloseBrackets: true, extraKeys: { 'Ctrl-S': function() { document.querySelector('button[value="save"]').click(); }, 'Ctrl-L': function() { editor.clearHistory(); }, 'Ctrl-/': 'toggleComment' } }); // Hide fallback textarea document.getElementById('haproxy_config').style.display = 'none'; // Update line/col info editor.on('cursorActivity', function() { const pos = editor.getCursor(); document.getElementById('line_col').textContent = `Line ${pos.line + 1}, Col ${pos.ch + 1}`; document.getElementById('char_count').textContent = editor.getValue().length; }); // Auto-save to localStorage let saveTimeout; editor.on('change', function() { clearTimeout(saveTimeout); saveTimeout = setTimeout(() => { localStorage.setItem('haproxy_draft', editor.getValue()); }, 1000); }); // Recover from localStorage const draft = localStorage.getItem('haproxy_draft'); const currentContent = editorElement.value.trim(); if (draft && draft.trim() !== currentContent && currentContent === '') { if (confirm('📝 Recover unsaved draft?')) { editor.setValue(draft); localStorage.removeItem('haproxy_draft'); } } // Form submission - sync values const editForm = document.getElementById('edit_form'); editForm.addEventListener('submit', function(e) { editorElement.value = editor.getValue(); document.getElementById('haproxy_config').value = editor.getValue(); }); // Initial info document.getElementById('char_count').textContent = editor.getValue().length; console.log('[Editor] CodeMirror initialized successfully'); } catch (e) { console.warn('[Editor] CodeMirror initialization failed:', e); // Fallback textarea is already visible document.getElementById('haproxy_config').style.display = 'block'; } }