Panel UI improvements: - Replace heading elements (h1-h6) with styled divs to avoid navigation interference - Change ContentsControl position from northwest to west for better accessibility Panel collapse/expand enhancements: - Fix panel dragging to prevent unexpected positioning jumps - Keep panel width and upper-left position when collapsing to header-only mode - Complete height reduction when collapsed (no minimal size maintained) - Toggle resize handle visibility based on panel state Resize handle improvements: - Change resize symbol from arrow to clean dot (●) in bottom-right corner - Remove background circle, show transparent dot only - Fix resize direction to properly follow mouse movement from bottom-right - Set dynamic minimum size constraints (header height + padding) - Allow arbitrary panel sizing with proper bounds checking - Reset panel size to defaults when closed/collapsed 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
227 lines
8.6 KiB
JavaScript
227 lines
8.6 KiB
JavaScript
/**
|
|
* Main Markitect JavaScript Entry Point - Clean Architecture Version
|
|
*
|
|
* Uses ONLY the JSON configuration interface - NO Python-generated JavaScript!
|
|
* Initializes all controls and systems when document is ready
|
|
* Implements graceful degradation for missing dependencies
|
|
*/
|
|
|
|
// Main application module
|
|
const MarkitectMain = {
|
|
initialized: false,
|
|
config: null,
|
|
|
|
// Initialize the complete application
|
|
initialize: function() {
|
|
if (this.initialized) {
|
|
console.log('⚠️ MarkitectMain already initialized, skipping');
|
|
return;
|
|
}
|
|
|
|
console.log('🚀 MarkitectMain initializing...');
|
|
|
|
try {
|
|
// Get configuration - if not loaded, use defaults
|
|
this.config = window.markitectConfig;
|
|
if (!this.config || !this.config.loaded) {
|
|
console.warn('⚠️ Configuration not loaded, proceeding with defaults');
|
|
this.config = {
|
|
markdownContent: document.querySelector('#markdown-content')?.textContent || '',
|
|
mode: 'edit',
|
|
theme: 'github'
|
|
};
|
|
}
|
|
|
|
// Initialize core systems
|
|
this.initializeCoreComponents();
|
|
this.initializeControlPanels();
|
|
this.setupEventHandlers();
|
|
this.renderContent();
|
|
|
|
this.initialized = true;
|
|
console.log('✅ MarkitectMain initialization complete');
|
|
|
|
} catch (error) {
|
|
console.error('❌ MarkitectMain initialization failed:', error);
|
|
this.fallbackMode();
|
|
}
|
|
},
|
|
|
|
// Initialize core modular components
|
|
initializeCoreComponents: function() {
|
|
console.log('🔧 Initializing core components...');
|
|
|
|
const container = document.getElementById('markdown-content') || document.body;
|
|
|
|
// Initialize section manager
|
|
if (typeof SectionManager !== 'undefined') {
|
|
this.sectionManager = new SectionManager();
|
|
console.log('✅ SectionManager initialized');
|
|
} else {
|
|
throw new Error('SectionManager not available');
|
|
}
|
|
|
|
// Initialize DOM renderer
|
|
if (typeof DOMRenderer !== 'undefined') {
|
|
this.domRenderer = new DOMRenderer(this.sectionManager, container);
|
|
console.log('✅ DOMRenderer initialized');
|
|
} else {
|
|
throw new Error('DOMRenderer not available');
|
|
}
|
|
|
|
// Initialize debug panel
|
|
if (typeof DebugPanel !== 'undefined') {
|
|
this.debugPanel = new DebugPanel();
|
|
console.log('✅ DebugPanel initialized');
|
|
}
|
|
|
|
// Legacy DocumentControls removed - functionality now in enhanced control panels
|
|
},
|
|
|
|
// Initialize enhanced control panels with compass positioning
|
|
initializeControlPanels: function() {
|
|
console.log('🎛️ Initializing enhanced control panels with compass positioning...');
|
|
|
|
// ContentsControl (West)
|
|
if (typeof ContentsControl !== 'undefined') {
|
|
this.contentsControl = new ContentsControl();
|
|
this.contentsControl.config.position = 'w';
|
|
this.contentsControl.show();
|
|
window.contentsControl = this.contentsControl;
|
|
console.log('✅ ContentsControl initialized (West) with enhanced ControlBase');
|
|
}
|
|
|
|
// StatusControl (East)
|
|
if (typeof StatusControl !== 'undefined') {
|
|
this.statusControl = new StatusControl();
|
|
this.statusControl.config.position = 'e';
|
|
this.statusControl.show();
|
|
window.statusControl = this.statusControl;
|
|
console.log('✅ StatusControl initialized (East) with enhanced ControlBase');
|
|
}
|
|
|
|
// DebugControl (Southeast)
|
|
if (typeof DebugControl !== 'undefined') {
|
|
this.debugControl = new DebugControl();
|
|
this.debugControl.config.position = 'se';
|
|
this.debugControl.show();
|
|
window.debugControl = this.debugControl;
|
|
console.log('✅ DebugControl initialized (Southeast) with enhanced ControlBase');
|
|
}
|
|
|
|
// EditControl (Northeast)
|
|
if (typeof EditControl !== 'undefined') {
|
|
this.editControl = new EditControl();
|
|
this.editControl.config.position = 'ne';
|
|
this.editControl.show();
|
|
window.editControl = this.editControl;
|
|
console.log('✅ EditControl initialized (Northeast) with enhanced ControlBase');
|
|
}
|
|
},
|
|
|
|
// Setup core event handlers (enhanced control panels handle their own events)
|
|
setupEventHandlers: function() {
|
|
console.log('🔌 Setting up core event handlers...');
|
|
|
|
// Setup section manager event handlers for debug panel
|
|
if (this.sectionManager && this.debugPanel) {
|
|
this.sectionManager.on('sections-created', (data) => {
|
|
this.debugPanel.addMessage(`Created ${data.count} sections`, 'INFO');
|
|
});
|
|
|
|
this.sectionManager.on('edit-started', (data) => {
|
|
this.debugPanel.addMessage(`Edit started for section: ${data.sectionId}`, 'DEBUG');
|
|
});
|
|
|
|
this.sectionManager.on('changes-accepted', (data) => {
|
|
this.debugPanel.addMessage(`Changes accepted for section: ${data.sectionId}`, 'SUCCESS');
|
|
this.updateSectionDOM(data.sectionId);
|
|
});
|
|
|
|
this.sectionManager.on('changes-cancelled', (data) => {
|
|
this.debugPanel.addMessage(`Changes cancelled for section: ${data.sectionId}`, 'WARNING');
|
|
});
|
|
}
|
|
|
|
// Make core components available globally for enhanced controls
|
|
window.sectionManager = this.sectionManager;
|
|
window.domRenderer = this.domRenderer;
|
|
window.debugPanel = this.debugPanel;
|
|
|
|
console.log('✅ Core event handlers and global references set up');
|
|
},
|
|
|
|
// Render content using the configuration
|
|
renderContent: function() {
|
|
console.log('📄 Rendering markdown content...');
|
|
|
|
const markdownToRender = this.config.markdownContent || '';
|
|
if (markdownToRender.trim()) {
|
|
const sections = this.sectionManager.createSectionsFromMarkdown(markdownToRender);
|
|
this.domRenderer.renderAllSections(sections);
|
|
|
|
if (this.debugPanel) {
|
|
this.debugPanel.addMessage(`Initialized with ${sections.length} sections`, 'INFO');
|
|
}
|
|
console.log(`✅ Rendered ${sections.length} sections`);
|
|
} else {
|
|
if (this.debugPanel) {
|
|
this.debugPanel.addMessage('No markdown content to initialize', 'WARNING');
|
|
}
|
|
console.warn('⚠️ No markdown content to render');
|
|
}
|
|
},
|
|
|
|
// Update section DOM after changes
|
|
updateSectionDOM: function(sectionId) {
|
|
try {
|
|
const section = this.sectionManager.sections.get(sectionId);
|
|
if (section) {
|
|
const sectionElement = this.domRenderer.findSectionElement(sectionId);
|
|
if (sectionElement) {
|
|
const newElement = this.domRenderer.renderSection(section);
|
|
sectionElement.parentNode.replaceChild(newElement, sectionElement);
|
|
|
|
if (this.debugPanel) {
|
|
this.debugPanel.addMessage(`DOM updated for section: ${sectionId}`, 'INFO');
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('❌ Failed to update section DOM:', error);
|
|
}
|
|
},
|
|
|
|
// Fallback mode if initialization fails
|
|
fallbackMode: function() {
|
|
console.warn('⚠️ Running in fallback mode');
|
|
|
|
// Basic content rendering fallback
|
|
const contentDiv = document.getElementById('markdown-content');
|
|
if (contentDiv && this.config && this.config.markdownContent) {
|
|
const basicHtml = this.config.markdownContent
|
|
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
|
|
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
|
|
.replace(/^### (.*$)/gim, '<h3>$1</h3>')
|
|
.replace(/\n\n/g, '</p><p>')
|
|
.replace(/\n/g, '<br>');
|
|
|
|
contentDiv.innerHTML = `<p>${basicHtml}</p>`;
|
|
console.log('✅ Fallback content rendered');
|
|
}
|
|
}
|
|
};
|
|
|
|
// Make components globally available for debugging
|
|
window.MarkitectMain = MarkitectMain;
|
|
|
|
// Auto-initialize when DOM is ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Small delay to ensure config is loaded
|
|
setTimeout(() => MarkitectMain.initialize(), 100);
|
|
});
|
|
} else {
|
|
// DOM already ready
|
|
setTimeout(() => MarkitectMain.initialize(), 100);
|
|
} |