2025-04-09 17:02:19 -06:00

991 lines
35 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function() {
console.log('DOM loaded - initializing builder');
// Initialize preview mode state
let previewModeActive = false;
// Preview Mode Toggle
const previewToggle = document.getElementById('preview-toggle');
if (previewToggle) {
console.log('Preview toggle found, adding event listener');
document.addEventListener('click', function(e) {
// Hacky way: find any click anywhere near the toggle and check status
if (e.target.closest('.toggle-switch') || e.target.id === 'preview-toggle') {
// Give time for the checkbox to update
setTimeout(function() {
previewModeActive = previewToggle.checked;
console.log('Preview toggle changed to:', previewModeActive);
// Add a direct style change to visually confirm toggle works
document.querySelector('.toggle-label').style.color = previewModeActive ? 'blue' : '';
togglePreviewMode(previewModeActive);
}, 50);
}
});
} else {
console.error('Preview toggle element not found!');
}
// Function to toggle preview mode
function togglePreviewMode(active) {
console.log('Toggle preview mode called with active =', active);
// Use inline styles for preview mode
// This directly styles elements without relying on classes
const styleId = 'preview-mode-style';
let styleElement = document.getElementById(styleId);
if (active) {
// Create style element if it doesn't exist
if (!styleElement) {
styleElement = document.createElement('style');
styleElement.id = styleId;
document.head.appendChild(styleElement);
}
// Find all textareas with content to mark for display
const contentTextareas = [];
document.querySelectorAll('textarea').forEach(textarea => {
if (textarea.value && textarea.value.trim()) {
// Get the ID for later targeting
contentTextareas.push('#' + textarea.id);
// Mark parents for visibility
const field = textarea.closest('.field');
if (field) field.classList.add('has-content');
const component = textarea.closest('.component-card');
if (component) component.classList.add('has-content');
const stage = textarea.closest('.stage-section');
if (stage) stage.classList.add('has-content');
// Ensure stage is expanded
if (stage) {
const stageBody = stage.querySelector('.stage-body');
if (stageBody) stageBody.style.display = 'block';
}
}
});
// Apply direct CSS to create preview mode
styleElement.textContent = `
/* Hide module selectors and empty fields */
.module-selector { display: none !important; }
.field:not(.has-content) { display: none !important; }
/* Hide empty components and sections */
.component-card:not(.has-content) { display: none !important; }
.stage-section:not(.has-content) { display: none !important; }
/* Hide template selector */
.protocol-template-selector { display: none !important; }
/* Expand all sections */
.stage-body { display: block !important; }
/* Make textareas read-only appearance */
textarea {
border: none !important;
background-color: transparent !important;
padding: 0 !important;
min-height: unset !important;
height: auto !important;
resize: none !important;
pointer-events: none !important;
outline: none !important;
box-shadow: none !important;
}
/* Only show filled textareas */
textarea:not(${contentTextareas.join(',')}) {
display: none !important;
}
/* Clean styling for components */
.component-header {
background-color: transparent !important;
border-bottom: none !important;
padding-bottom: 0 !important;
}
.component-short-label { display: none !important; }
/* Improved typography for preview mode */
.component-header h3 {
font-size: 1.4rem !important;
margin-bottom: 1rem !important;
color: #000 !important;
border-bottom: 1px solid #eee !important;
padding-bottom: 0.5rem !important;
}
`;
// Replace textareas with divs for better display in preview mode
updatePreviewContent();
// Make other fields read-only
document.querySelectorAll('#community-name, #protocol-summary').forEach(el => {
el.setAttribute('readonly', 'readonly');
});
} else {
// Remove preview styles
if (styleElement) {
styleElement.textContent = '';
}
// Remove preview content divs and show textareas again
document.querySelectorAll('.preview-content').forEach(div => {
const textareaId = div.dataset.forTextarea;
if (textareaId) {
const textarea = document.getElementById(textareaId);
if (textarea) {
textarea.style.display = '';
}
}
div.parentNode.removeChild(div);
});
// Make fields editable again
document.querySelectorAll('textarea, #community-name, #protocol-summary').forEach(el => {
el.removeAttribute('readonly');
});
// Remove content markers
document.querySelectorAll('.has-content').forEach(el => {
el.classList.remove('has-content');
});
// Reset any display properties that were directly set
document.querySelectorAll('.stage-body').forEach(el => {
el.style.display = '';
});
}
}
// Function to mark components and stages that have content
function markComponentsWithContent() {
// First reset all markers
document.querySelectorAll('.has-content').forEach(el => {
el.classList.remove('has-content');
});
// Mark fields with content
document.querySelectorAll('textarea').forEach(textarea => {
if (textarea.value && textarea.value.trim()) {
const field = textarea.closest('.field');
if (field) field.classList.add('has-content');
const component = textarea.closest('.component-card');
if (component) component.classList.add('has-content');
const stage = textarea.closest('.stage-section');
if (stage) stage.classList.add('has-content');
}
});
// Show all expanded sections that have content
document.querySelectorAll('.stage-section.has-content').forEach(stage => {
const stageBody = stage.querySelector('.stage-body');
if (stageBody) {
stageBody.style.display = 'block';
const toggleBtn = stage.querySelector('.toggle-btn');
if (toggleBtn) {
toggleBtn.textContent = '-';
}
}
});
}
// Load module data
let allModules = {};
try {
// Check if moduleData is defined (from modules.js)
if (typeof moduleData !== 'undefined') {
allModules = moduleData;
console.log('Module data loaded from modules.js');
}
} catch (e) {
console.error('Error loading module data:', e);
allModules = {};
}
// Load and process template data
let templates = [];
try {
// Check if raw templates are defined (from templates.js)
if (typeof rawProtocolTemplates !== 'undefined' && typeof templateMapper !== 'undefined') {
console.log('Raw protocol templates loaded from templates.js');
// Process each template to use module references
rawProtocolTemplates.forEach(rawTemplate => {
const processedTemplate = templateMapper.convertTemplateToModules(rawTemplate, allModules);
templates.push(processedTemplate);
});
console.log('Processed templates to use module references:', templates);
}
} catch (e) {
console.error('Error processing protocol templates:', e);
templates = [];
}
// Protocol data structure
let protocol = {
metadata: {
communityName: "",
summary: ""
},
stages: {}
};
// DOM elements
const stageHeaders = document.querySelectorAll('.stage-header');
console.log('Found stage headers:', stageHeaders.length);
const stageContents = document.querySelectorAll('.stage-body');
console.log('Found stage bodies:', stageContents.length);
const moduleSelects = document.querySelectorAll('.module-select');
console.log('Found module selects:', moduleSelects.length);
const protocolTemplateSelect = document.getElementById('protocol-template');
const communityNameInput = document.getElementById('community-name');
const protocolSummaryTextarea = document.getElementById('protocol-summary');
const exportBtn = document.getElementById('export-btn');
const exportMdBtn = document.getElementById('export-md');
const exportPdfBtn = document.getElementById('export-pdf');
const exportJsonBtn = document.getElementById('export-json');
const importJsonInput = document.getElementById('import-json');
const importBtn = document.getElementById('import-btn');
// Populate protocol template select
if (protocolTemplateSelect && templates.length > 0) {
templates.forEach(template => {
const option = document.createElement('option');
option.value = template.id;
option.textContent = template.title;
protocolTemplateSelect.appendChild(option);
});
// Add template selection event handler
protocolTemplateSelect.addEventListener('change', function() {
const selectedTemplateId = this.value;
if (selectedTemplateId) {
// Find the selected template
const selectedTemplate = templates.find(t => t.id === selectedTemplateId);
if (selectedTemplate) {
console.log('Applying template:', selectedTemplate);
console.log('Selected template:', selectedTemplate.title);
// Reset protocol data while preserving metadata
protocol = {
metadata: {
communityName: communityNameInput.value || "",
summary: protocolSummaryTextarea.value || ""
},
stages: {},
templateId: selectedTemplate.id,
templateTitle: selectedTemplate.title,
templateDescription: selectedTemplate.description
};
// If summary is empty, use template description
if (!protocol.metadata.summary) {
protocolSummaryTextarea.value = selectedTemplate.description;
protocol.metadata.summary = selectedTemplate.description;
}
// Apply the template module references to the form
for (const stageId in selectedTemplate.moduleRefs) {
if (!protocol.stages[stageId]) {
protocol.stages[stageId] = {};
}
for (const componentId in selectedTemplate.moduleRefs[stageId]) {
if (!protocol.stages[stageId][componentId]) {
protocol.stages[stageId][componentId] = {};
}
for (const fieldId in selectedTemplate.moduleRefs[stageId][componentId]) {
const moduleId = selectedTemplate.moduleRefs[stageId][componentId][fieldId];
const textarea = document.getElementById(fieldId);
if (textarea) {
// Find the module with this ID
let moduleContent = '';
for (const category in allModules) {
const foundModule = allModules[category].find(m => m.id === moduleId);
if (foundModule) {
moduleContent = foundModule.content;
break;
}
}
// Apply the module content to the textarea
textarea.value = moduleContent;
// Store in protocol data
protocol.stages[stageId][componentId][fieldId] = moduleContent;
// If there's a template selector for this field, update it
const moduleSelector = document.querySelector(`select.module-select[data-field-id="${fieldId}"][data-component-id="${componentId}"]`);
if (moduleSelector) {
moduleSelector.value = moduleId;
}
}
}
}
}
// Expand all sections to show the populated content
stageContents.forEach(content => {
content.style.display = 'block';
const toggleBtn = content.parentElement.querySelector('.toggle-btn');
if (toggleBtn) {
toggleBtn.textContent = '-';
}
});
// Update preview mode if active
if (previewModeActive) {
markComponentsWithContent();
}
}
} else {
// Clear all fields if "Create Your Own" is selected
document.querySelectorAll('textarea').forEach(textarea => {
textarea.value = '';
});
// Reset protocol data
protocol = { stages: {} };
// Collapse all sections
stageContents.forEach(content => {
content.style.display = 'none';
const toggleBtn = content.parentElement.querySelector('.toggle-btn');
if (toggleBtn) {
toggleBtn.textContent = '+';
}
});
// Update preview mode if active
if (previewModeActive) {
markComponentsWithContent();
}
}
});
}
// Initialize all module selects
populateModuleSelects();
// Module selection handlers
moduleSelects.forEach(select => {
select.addEventListener('change', function() {
const fieldId = this.getAttribute('data-field-id');
const componentId = this.getAttribute('data-component-id');
const targetTextarea = document.getElementById(fieldId);
if (targetTextarea && this.value) {
// Find the selected module
for (const category in allModules) {
const selectedModule = allModules[category].find(m => m.id === this.value);
if (selectedModule) {
targetTextarea.value = selectedModule.content;
// Update protocol data
updateProtocolData();
// Update preview mode if active
if (previewModeActive) {
markComponentsWithContent();
}
break;
}
}
}
});
});
// Function to populate module select dropdowns
function populateModuleSelects() {
console.log('Populating module selects...');
console.log('Available module categories:', Object.keys(allModules));
// Debugging: Log all modules to check componentId and fieldId
console.log('All module mapping:');
for (const category in allModules) {
console.log(`Category: ${category}`);
allModules[category].forEach(module => {
console.log(` Module: ${module.id}, Component: ${module.componentId}, Field: ${module.fieldId}`);
});
}
moduleSelects.forEach(select => {
const fieldId = select.getAttribute('data-field-id');
const componentId = select.getAttribute('data-component-id');
console.log(`Processing module select for fieldId: ${fieldId}, componentId: ${componentId}`);
// Clear existing options except the first one
while (select.options.length > 1) {
select.remove(1);
}
// Find modules that match this field and component
let hasOptions = false;
// Always show select first - we'll hide it later if no options found
select.closest('.module-selector').style.display = 'flex';
// Check for case matching issues and missing references
for (const category in allModules) {
let exactMatches = allModules[category].filter(m =>
m.fieldId === fieldId && m.componentId === componentId
);
let caseInsensitiveMatches = allModules[category].filter(m =>
m.fieldId.toLowerCase() === fieldId.toLowerCase() &&
m.componentId.toLowerCase() === componentId.toLowerCase() &&
!exactMatches.includes(m)
);
if (caseInsensitiveMatches.length > 0) {
console.warn(`Found ${caseInsensitiveMatches.length} case-insensitive matches for ${componentId}/${fieldId}. Consider fixing these module references.`);
// Add case-insensitive matches to the collection
caseInsensitiveMatches.forEach(module => {
// Create a copy with corrected references
const correctedModule = {
...module,
componentId: componentId,
fieldId: fieldId
};
// Add to the exact matches
exactMatches.push(correctedModule);
});
}
if (exactMatches.length > 0) {
console.log(`Found ${exactMatches.length} modules in category ${category} for ${componentId}/${fieldId}`);
hasOptions = true;
// Don't use option groups - add options directly to the select
// This avoids showing category labels which can be confusing
exactMatches.forEach(module => {
const option = document.createElement('option');
option.value = module.id;
// Use the module title directly from the definition
// This relies on proper module titles being defined in modules.js
option.textContent = module.title;
// Add directly to select instead of to a group
select.appendChild(option);
});
}
}
// If no modules found, hide the selector
if (!hasOptions) {
console.log(`No modules found for ${componentId}/${fieldId}, hiding selector`);
select.closest('.module-selector').style.display = 'none';
}
});
}
// Update protocol data from form inputs
function updateProtocolData() {
// Update metadata
protocol.metadata = {
communityName: communityNameInput.value || "",
summary: protocolSummaryTextarea.value || ""
};
// Reset the stages data
protocol.stages = {};
// Get all textareas and their values
const textareas = document.querySelectorAll('textarea');
textareas.forEach(textarea => {
const fieldId = textarea.id;
const fieldValue = textarea.value;
// Skip empty fields
if (!fieldValue || !fieldValue.trim()) return;
// Find the component and stage for this field
const componentCard = textarea.closest('.component-card');
if (!componentCard) return;
const componentId = componentCard.id.replace('component-', '');
const stageSection = textarea.closest('.stage-section');
if (!stageSection) return;
const stageId = stageSection.id.replace('stage-', '');
// Initialize stage and component if they don't exist
if (!protocol.stages[stageId]) {
protocol.stages[stageId] = {};
}
if (!protocol.stages[stageId][componentId]) {
protocol.stages[stageId][componentId] = {};
}
// Set the field value
protocol.stages[stageId][componentId][fieldId] = fieldValue;
});
// If a template is selected, preserve the template information
const selectedTemplateId = protocolTemplateSelect ? protocolTemplateSelect.value : '';
if (selectedTemplateId) {
const selectedTemplate = templates.find(t => t.id === selectedTemplateId);
if (selectedTemplate) {
protocol.templateId = selectedTemplateId;
protocol.templateTitle = selectedTemplate.title;
protocol.templateDescription = selectedTemplate.description;
}
}
// Remove empty components and stages
for (const stageId in protocol.stages) {
// Check if stage has any non-empty components
const stageComponents = protocol.stages[stageId];
let stageHasContent = false;
for (const componentId in stageComponents) {
// Check if component has any fields
const component = stageComponents[componentId];
const fieldCount = Object.keys(component).length;
if (fieldCount > 0) {
stageHasContent = true;
} else {
// Remove empty component
delete stageComponents[componentId];
}
}
// If stage has no content, remove it
if (!stageHasContent) {
delete protocol.stages[stageId];
}
}
}
// Export to Markdown
exportMdBtn.addEventListener('click', function(e) {
e.preventDefault();
updateProtocolData();
try {
// Use community name if available, otherwise default
const communityName = protocol.metadata.communityName || "Community";
let markdown = `# ${communityName}\n# CommunityDispute\n\n`;
// Include protocol summary if available
if (protocol.metadata.summary) {
markdown += `${protocol.metadata.summary}\n\n`;
markdown += '---\n\n';
}
// Template information removed as requested
// Loop through the stages in order
stageHeaders.forEach(header => {
const stageId = header.getAttribute('data-stage');
const stageName = header.querySelector('h2').textContent;
let stageContent = '';
let hasContent = false;
// Get components for this stage
const stageComponents = protocol.stages[stageId];
if (stageComponents) {
// Loop through components
for (const componentId in stageComponents) {
const componentCard = document.getElementById(`component-${componentId}`);
if (componentCard) {
const componentName = componentCard.querySelector('h3').textContent;
let componentContent = '';
let componentHasContent = false;
// Loop through fields
for (const fieldId in stageComponents[componentId]) {
const fieldValue = stageComponents[componentId][fieldId];
// Skip empty fields
if (fieldValue && fieldValue.trim()) {
// Skip the field label, just add the content
componentContent += `${fieldValue}\n\n`;
componentHasContent = true;
hasContent = true;
}
}
// Only add component if it has content
if (componentHasContent) {
stageContent += `### ${componentName}\n\n${componentContent}`;
}
}
}
}
// Only add stage if it has content
if (hasContent) {
// Get the stage section ID (e.g., "Intake")
const stageSection = header.closest('.stage-section');
const stageSectionId = stageSection ? stageSection.id.replace('stage-', '') : '';
const stageSectionTitle = stageSectionId ? stageSectionId.charAt(0).toUpperCase() + stageSectionId.slice(1) : '';
// Use just the section title to avoid duplication
if (stageSectionTitle) {
markdown += `## ${stageSectionTitle}\n\n${stageContent}`;
} else {
markdown += `## ${stageName}\n\n${stageContent}`;
}
}
});
// Create and download the file
downloadFile('communityDispute.md', markdown);
} catch (error) {
console.error('Error generating Markdown:', error);
alert('Failed to generate Markdown. Please try again.');
}
});
// Export to PDF
exportPdfBtn.addEventListener('click', function(e) {
e.preventDefault();
updateProtocolData();
try {
// Check if jspdf is properly loaded
if (typeof window.jspdf === 'undefined') {
console.error('jsPDF library not loaded properly');
alert('PDF export is currently unavailable. The required library failed to load.');
return;
}
// Create a styled HTML version for PDF export
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
// Set consistent text width parameters
const margins = {
left: 14,
right: 14,
pageWidth: 210, // A4 width in mm (portrait)
width: 182 // We'll use this as the consistent text width - should be pageWidth - left - right
};
let yPos = 20;
// Use community name if available, otherwise default
const communityName = protocol.metadata.communityName || "Community";
// Add title with line break
doc.setFontSize(18);
doc.text(`${communityName}\nCommunityDispute`, 105, yPos, { align: 'center' });
yPos += 25;
// Page width indicator removed
// Add protocol summary if available
if (protocol.metadata.summary) {
doc.setFontSize(12);
const summaryLines = doc.splitTextToSize(protocol.metadata.summary, margins.width);
doc.text(summaryLines, margins.left, yPos);
yPos += summaryLines.length * 7 + 8;
}
// Template information removed as requested
// Set up direct rendering approach to avoid duplication
const sectionsToProcess = [];
// Find all unique stage sections with content
document.querySelectorAll('.stage-section').forEach(section => {
const sectionId = section.id.replace('stage-', '');
const sectionTitle = sectionId.charAt(0).toUpperCase() + sectionId.slice(1);
const componentsWithContent = [];
// Look for components with content in this section
section.querySelectorAll('.component-card').forEach(componentCard => {
const componentId = componentCard.id.replace('component-', '');
// Check if this component has content in the protocol data
const stageId = section.id.replace('stage-', '');
if (protocol.stages[stageId] &&
protocol.stages[stageId][componentId] &&
Object.keys(protocol.stages[stageId][componentId]).length > 0) {
componentsWithContent.push({
id: componentId,
element: componentCard,
name: componentCard.querySelector('h3').textContent
});
}
});
// Only include sections that have components with content
if (componentsWithContent.length > 0) {
sectionsToProcess.push({
id: sectionId,
title: sectionTitle,
components: componentsWithContent
});
}
});
// Process each section directly to avoid duplication
sectionsToProcess.forEach(section => {
// Add page break if needed
if (yPos > 250) {
doc.addPage();
yPos = 20;
}
// Add section header only once (e.g., "Intake")
doc.setFontSize(18);
doc.text(section.title, margins.left, yPos);
yPos += 15;
// Process components in this section
section.components.forEach(component => {
// Add page break if needed
if (yPos > 250) {
doc.addPage();
yPos = 20;
}
// Add component heading
doc.setFontSize(14);
doc.text(component.name, margins.left, yPos);
yPos += 8;
// Get fields for this component
const stageId = section.id;
const componentId = component.id;
if (protocol.stages[stageId] && protocol.stages[stageId][componentId]) {
// Loop through fields
for (const fieldId in protocol.stages[stageId][componentId]) {
const fieldValue = protocol.stages[stageId][componentId][fieldId];
// Skip empty fields
if (fieldValue && fieldValue.trim()) {
// Add page break if needed
if (yPos > 250) {
doc.addPage();
yPos = 20;
}
// Format field content with larger font size (12)
doc.setFontSize(12);
// Use consistent width for all text
const textLines = doc.splitTextToSize(fieldValue, margins.width);
doc.text(textLines, margins.left, yPos);
yPos += textLines.length * 6 + 8; // Slightly increase spacing for larger font
}
}
}
});
});
// Save the PDF
doc.save('communityDispute.pdf');
} catch (error) {
console.error('Error generating PDF:', error);
alert('Failed to generate PDF. Please try again or use another export format.');
}
});
// Export to JSON
exportJsonBtn.addEventListener('click', function(e) {
e.preventDefault();
updateProtocolData();
const jsonData = JSON.stringify(protocol, null, 2);
downloadFile('communityDispute.json', jsonData);
});
// Import from JSON
importBtn.addEventListener('click', function() {
importJsonInput.click();
});
importJsonInput.addEventListener('change', function(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
try {
const importedProtocol = JSON.parse(e.target.result);
protocol = importedProtocol;
// Populate metadata fields if present
if (protocol.metadata) {
if (protocol.metadata.communityName) {
communityNameInput.value = protocol.metadata.communityName;
}
if (protocol.metadata.summary) {
protocolSummaryTextarea.value = protocol.metadata.summary;
}
}
// Populate the component fields with the imported data
for (const stageId in protocol.stages) {
for (const componentId in protocol.stages[stageId]) {
for (const fieldId in protocol.stages[stageId][componentId]) {
const textarea = document.getElementById(fieldId);
if (textarea) {
textarea.value = protocol.stages[stageId][componentId][fieldId];
}
}
}
}
// If the imported protocol has template information, select that template
if (protocol.templateId && protocolTemplateSelect) {
protocolTemplateSelect.value = protocol.templateId;
// Update template description
if (protocol.templateDescription && templateDescription) {
templateDescription.textContent = protocol.templateDescription;
templateDescription.style.display = 'block';
}
// Expand all sections
stageContents.forEach(content => {
content.style.display = 'block';
const toggleBtn = content.parentElement.querySelector('.toggle-btn');
if (toggleBtn) {
toggleBtn.textContent = '-';
}
});
} else {
// If no template, reset the template selector
if (protocolTemplateSelect) {
protocolTemplateSelect.value = '';
}
if (templateDescription) {
templateDescription.textContent = '';
templateDescription.style.display = 'none';
}
}
// Update preview mode if active
if (previewModeActive) {
markComponentsWithContent();
}
alert('Protocol imported successfully!');
} catch (error) {
alert('Failed to import protocol. Invalid JSON format.');
console.error(error);
}
};
reader.readAsText(file);
}
});
// Helper function to download a file
function downloadFile(filename, content) {
const element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(content));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
// Save data when inputs change
document.querySelectorAll('textarea').forEach(textarea => {
textarea.addEventListener('input', function() {
updateProtocolData();
// Update preview mode if active
if (previewModeActive) {
markComponentsWithContent();
}
});
});
// Function to update preview content
function updatePreviewContent() {
// First, clear any existing preview divs
document.querySelectorAll('.preview-content').forEach(div => {
div.parentNode.removeChild(div);
});
// Show all textareas again
document.querySelectorAll('textarea').forEach(textarea => {
textarea.style.display = '';
});
// Then create new preview divs for all textareas with content
document.querySelectorAll('textarea').forEach(textarea => {
if (textarea.value && textarea.value.trim()) {
// Create a div to replace the textarea for preview
const previewDiv = document.createElement('div');
previewDiv.className = 'preview-content';
previewDiv.textContent = textarea.value;
previewDiv.dataset.forTextarea = textarea.id;
// Hide the textarea and insert the div
textarea.style.display = 'none';
textarea.parentNode.insertBefore(previewDiv, textarea.nextSibling);
}
});
}
// Update preview content when preview mode is toggled
document.getElementById('preview-toggle').addEventListener('change', function() {
if (this.checked) {
// Wait for the preview mode styles to apply, then update content
setTimeout(updatePreviewContent, 100);
}
});
// Update preview content when module content changes
document.querySelectorAll('.module-select').forEach(select => {
select.addEventListener('change', function() {
setTimeout(() => {
if (document.getElementById('preview-toggle').checked) {
updatePreviewContent();
}
}, 100);
});
});
// Update preview content on window resize
window.addEventListener('resize', function() {
if (document.getElementById('preview-toggle').checked) {
updatePreviewContent();
}
});
console.log('Builder initialization complete');
});