/* Target the paragraph containing the country field */ .wpcf7-form p:has(#country_field) { position: absolute !important; opacity: 0 !important; width: 0 !important; height: 0 !important; overflow: hidden !important; } /* Fallback: Directly target the country dropdown */ #country_field { display: none !important; } /* Set all label text to black */ .wpcf7-form label { color: black !important; } /* Form layout styling */ .form-row { display: flex; gap: 15px; margin-bottom: 15px; width: 100%; } .form-col { flex: 1; min-width: 0; /* Prevents flex items from overflowing */ } .form-col label { display: block; margin-bottom: 5px; } .form-col select, .form-col input { width: 100%; height: 40px; border-radius: 4px; border: 1px solid #ddd; padding: 8px 12px; font-size: 14px; background-color: white; } /* Improved daterangepicker styling */ #date_range { height: 40px; border-radius: 4px; border: 1px solid #ddd; padding: 8px 12px; width: 100%; font-size: 14px; background-color: white; cursor: pointer; } /* Submit button styling - ensure it's not white */ .wpcf7-submit { background-color: #0D7EE8 !important; color: #ffffff !important; border: none !important; font-weight: 500 !important; cursor: pointer !important; } .wpcf7-submit:hover { background-color: #0A6AC7 !important; } /* Fixed daterangepicker styling to prevent page disruption */ .daterangepicker { position: absolute !important; font-family: inherit; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); border: none; width: 320px !important; /* Narrower without ranges */ max-width: 95vw; padding: 0; z-index: 9999 !important; background-color: white; margin-top: 5px; overflow: visible !important; /* Prevent scrolling */ } /* Calendar styling */ .daterangepicker .drp-calendar.left { clear: none !important; float: none !important; padding: 15px; width: 100%; } /* Hide the right calendar */ .daterangepicker .drp-calendar.right { display: none !important; } /* Hide the ranges completely */ .daterangepicker .ranges { display: none !important; } /* Calendar table styling */ .daterangepicker .calendar-table { border-radius: 6px; padding: 0; } .daterangepicker .calendar-table table { width: 100%; border-spacing: 0; border-collapse: collapse; } .daterangepicker td, .daterangepicker th { width: 36px; height: 36px; text-align: center; vertical-align: middle; min-width: 36px; padding: 0; line-height: 36px; } .daterangepicker td.active, .daterangepicker td.active:hover { background-color: #0D7EE8 !important; } .daterangepicker td.in-range { background-color: #E6F3FF; color: #333; } /* Button area styling */ .daterangepicker .drp-buttons { padding: 15px; border-top: 1px solid #eee; display: flex; justify-content: space-between; align-items: center; clear: both; } .daterangepicker .drp-buttons .btn { border-radius: 4px; font-weight: 500; margin: 0 5px; padding: 8px 16px; } .daterangepicker .drp-buttons .btn.btn-primary { background-color: #0D7EE8; border-color: #0D7EE8; } .daterangepicker .drp-selected { font-size: 13px; color: #666; margin-right: 10px; } /* Responsive fixes */ @media (max-width: 767px) { .form-row { flex-direction: column; gap: 10px; } } Select Your State* Select Your City* Select Your Billboard Location* Please select state and city first Select Your Purpose* Select Run Dates* document.addEventListener('DOMContentLoaded', function() { var countryField = document.getElementById('country_field'); var stateField = document.getElementById('state_field'); var cityField = document.getElementById('city_field'); var dateRangeField = document.getElementById('date_range'); // Initialize daterangepicker with single calendar if(dateRangeField) { jQuery(dateRangeField).daterangepicker({ autoUpdateInput: false, minDate: new Date(), opens: 'center', showDropdowns: true, singleDatePicker: false, autoApply: false, linkedCalendars: false, locale: { cancelLabel: 'Clear', format: 'MM/DD/YYYY', applyLabel: 'Apply', daysOfWeek: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] }, // Remove the ranges option completely }); // Professional date handling with immediate localStorage saving jQuery(dateRangeField).on('apply.daterangepicker', function(ev, picker) { const dateRange = picker.startDate.format('MM/DD/YYYY') + ' - ' + picker.endDate.format('MM/DD/YYYY'); jQuery(this).val(dateRange); // Immediately save to localStorage localStorage.setItem('runDates', dateRange); console.log('Date range selected and saved to localStorage:', dateRange); // Trigger validation check validateFormData(); }); jQuery(dateRangeField).on('cancel.daterangepicker', function() { jQuery(this).val(''); // Remove from localStorage when cleared localStorage.removeItem('runDates'); console.log('Date range cleared from localStorage'); // Trigger validation check validateFormData(); }); // Add calendar icon to input jQuery(dateRangeField).css('background-image', 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'16\' height=\'16\' viewBox=\'0 0 24 24\' fill=\'none\' stroke=\'%23666\' stroke-width=\'2\' stroke-linecap=\'round\' stroke-linejoin=\'round\'%3E%3Crect x=\'3\' y=\'4\' width=\'18\' height=\'18\' rx=\'2\' ry=\'2\'%3E%3C/rect%3E%3Cline x1=\'16\' y1=\'2\' x2=\'16\' y2=\'6\'%3E%3C/line%3E%3Cline x1=\'8\' y1=\'2\' x2=\'8\' y2=\'6\'%3E%3C/line%3E%3Cline x1=\'3\' y1=\'10\' x2=\'21\' y2=\'10\'%3E%3C/line%3E%3C/svg%3E")'); jQuery(dateRangeField).css('background-repeat', 'no-repeat'); jQuery(dateRangeField).css('background-position', 'right 10px center'); jQuery(dateRangeField).css('background-size', '16px'); jQuery(dateRangeField).css('padding-right', '36px'); // Configure the datepicker on show jQuery(dateRangeField).on('show.daterangepicker', function(ev, picker) { // Get the position of the input field var $input = jQuery(this); var inputPos = $input.offset(); var inputHeight = $input.outerHeight(); var inputWidth = $input.outerWidth(); // Position the picker directly below the input var topPos = inputPos.top + inputHeight + 5; var leftPos = inputPos.left + (inputWidth / 2) - (320 / 2); // Center based on 320px width // Adjust if too close to edges var windowWidth = jQuery(window).width(); if (leftPos windowWidth - 10) { leftPos = windowWidth - 320 - 10; } // Apply the position picker.container.css({ top: topPos + 'px', left: leftPos + 'px', overflow: 'visible' }); // Hide right calendar picker.container.find('.drp-calendar.right').hide(); // Hide ranges completely picker.container.find('.ranges').hide(); // Make left calendar take full width picker.container.find('.drp-calendar.left').css({ 'float': 'none', 'width': '100%', 'padding': '15px' }); // Fix button layout picker.container.find('.drp-buttons').css({ 'display': 'flex', 'justify-content': 'space-between', 'align-items': 'center', 'padding': '15px', 'clear': 'both' }); }); } // Function to initialize country, state, city fields function initializeLocationFields() { // Check if fields exist if (!countryField) { console.log('Country field not found, retrying in 500ms'); setTimeout(initializeLocationFields, 500); return; } // Set country to US jQuery(countryField).val('US'); // Trigger change event using jQuery jQuery(countryField).trigger('change'); // Check if state field populated after a delay setTimeout(function() { if (!stateField || stateField.options.length <= 1) { console.log('State field not populated with "US", trying "United States"'); jQuery(countryField).val('United States').trigger('change'); // Check again after another delay setTimeout(function() { if (!stateField || stateField.options.length { jQuery('select[name="state"], select.state_auto').val(existingData.state); }, 1000); } if (existingData.city) { setTimeout(() => { jQuery('select[name="city"], select.city_auto').val(existingData.city); }, 1500); } if (existingData.location) { setTimeout(() => { // First update billboard locations, then set the value updateBillboardLocations(); setTimeout(() => { jQuery('select[name="Billboard-Location"]').val(existingData.location); }, 200); }, 500); } if (existingData.dates) { jQuery('#date_range').val(existingData.dates); } // Run initial validation and update billboard locations setTimeout(() => { updateBillboardLocations(); validateFormData(); }, 2000); } // Initialize form data after a delay to ensure all fields are loaded setTimeout(initializeFormData, 1000); // Professional real-time data saving for all fields // Function to update billboard locations based on selected state and city function updateBillboardLocations() { const selectedState = jQuery('select.state_auto, select[name="state"]').val(); const selectedCity = jQuery('select.city_auto, select[name="city"]').val(); const billboardLocationSelect = jQuery('#billboard_location_field'); console.log('Updating billboard locations for:', { state: selectedState, city: selectedCity }); // Clear existing options billboardLocationSelect.empty(); // Define billboard locations data const billboardLocations = { 'Texas': { 'Stephenville': [ { value: 'Texas > Stephenville > 2095 West South loop, Stephenville, TX 76401', text: 'Texas > Stephenville > 2095 West South loop, Stephenville, TX 76401' } ] } }; // Check if we have locations for the selected state and city if (selectedState && selectedCity && billboardLocations[selectedState] && billboardLocations[selectedState][selectedCity]) { // Add default option billboardLocationSelect.append('Select a Billboard Location'); // Add available locations for this state/city combination const locations = billboardLocations[selectedState][selectedCity]; locations.forEach(location => { billboardLocationSelect.append(`${location.text}`); }); console.log(`Added ${locations.length} billboard location(s) for ${selectedState} > ${selectedCity}`); } else { // No locations available or state/city not selected if (!selectedState || !selectedCity) { billboardLocationSelect.append('Please select state and city first'); } else { billboardLocationSelect.append('No billboard locations available for this area'); } } // Clear any previously selected billboard location since options changed localStorage.removeItem('billboardLocation'); } // Add event listener for state field changes with immediate saving jQuery(document).on('change', 'select.state_auto, select[name="state"]', function() { const selectedState = jQuery(this).val(); console.log('State changed to:', selectedState); if (selectedState) { localStorage.setItem('selectedState', selectedState); console.log('State saved to localStorage:', selectedState); } // Update billboard locations when state changes updateBillboardLocations(); validateFormData(); }); // Add event listener for city field changes with immediate saving jQuery(document).on('change', 'select.city_auto, select[name="city"]', function() { const selectedCity = jQuery(this).val(); console.log('City changed to:', selectedCity); if (selectedCity) { localStorage.setItem('selectedCity', selectedCity); console.log('City saved to localStorage:', selectedCity); } // Update billboard locations when city changes updateBillboardLocations(); validateFormData(); }); // Add event listener for billboard location changes with immediate saving jQuery(document).on('change', 'select[name="Billboard-Location"]', function() { const billboardLocation = jQuery(this).val(); console.log('Billboard location changed to:', billboardLocation); if (billboardLocation) { localStorage.setItem('billboardLocation', billboardLocation); console.log('Billboard location saved to localStorage:', billboardLocation); } validateFormData(); }); // Professional form validation function function validateFormData() { const requiredData = { purpose: localStorage.getItem('selectedPurpose'), state: localStorage.getItem('selectedState'), city: localStorage.getItem('selectedCity'), location: localStorage.getItem('billboardLocation'), dates: localStorage.getItem('runDates') }; const missingFields = []; Object.keys(requiredData).forEach(field => { const value = requiredData[field]; if (!value || value === 'Select a Purpose' || value === 'Not selected' || value.trim() === '') { missingFields.push(field); } }); console.log('Form validation check:', { data: requiredData, missingFields: missingFields, isValid: missingFields.length === 0 }); // Update UI to show validation status (optional) updateValidationStatus(missingFields); return missingFields.length === 0; } // Update validation status in UI - Only for latest-dropdowns form function updateValidationStatus(missingFields) { console.log('updateValidationStatus: Checking validation status with missing fields:', missingFields); // Remove existing validation messages only from the latest-dropdowns context jQuery('.latest-dropdowns-validation').remove(); // Find the specific form that contains our dropdown fields const targetForm = jQuery('#state_field, #city_field, #billboard_location_field').closest('.wpcf7-form'); if (targetForm.length === 0) { console.log('updateValidationStatus: No latest-dropdowns form found, skipping UI update'); return; } if (missingFields && missingFields.length > 0) { const message = `Please complete: ${missingFields.join(', ')}`; const statusDiv = jQuery(`${message}`); targetForm.prepend(statusDiv); } else { const statusDiv = jQuery(`✅ All required fields completed!`); targetForm.prepend(statusDiv); } // Update continue button if it exists const continueBtn = jQuery('.continue-btn, #continueBtn'); if (continueBtn.length > 0) { const isValid = !missingFields || missingFields.length === 0; continueBtn.prop('disabled', !isValid); continueBtn.css('opacity', isValid ? '1' : '0.5'); } console.log('updateValidationStatus: Validation status updated for latest-dropdowns context'); } // Add event listener for purpose field changes with immediate saving jQuery(document).on('change', 'select[name="purpose"]', function() { const selectedPurpose = jQuery(this).val(); console.log('Purpose changed to:', selectedPurpose); if (selectedPurpose && selectedPurpose !== 'Select a Purpose') { // Store in localStorage for persistence localStorage.setItem('selectedPurpose', selectedPurpose); console.log('Purpose saved to localStorage:', selectedPurpose); // Send message to Ad Design and Content form if it's in another window/iframe try { // Try to find the Ad Design and Content form window const adDesignWindow = window.parent || window.opener || window; // Send postMessage to communicate the purpose selection adDesignWindow.postMessage({ type: 'purposeSelected', purpose: selectedPurpose }, window.location.origin); // Also try to send to all frames if this is in a parent window if (window.frames && window.frames.length > 0) { for (let i = 0; i < window.frames.length; i++) { try { window.frames[i].postMessage({ type: 'purposeSelected', purpose: selectedPurpose }, window.location.origin); } catch (e) { // Ignore cross-origin errors } } } } catch (e) { console.log('Could not send message to other window:', e); } // Also trigger a custom event on the current document const purposeEvent = new CustomEvent('purposeSelected', { detail: { purpose: selectedPurpose } }); document.dispatchEvent(purposeEvent); } // Trigger validation check validateFormData(); }); // Add form submission handler to store data for checkout jQuery(document).on('submit', '.wpcf7-form', function(e) { const selectedPurpose = jQuery('select[name="purpose"]').val(); const selectedState = jQuery('select[name="state"]').val(); const selectedCity = jQuery('select[name="city"]').val(); const billboardLocation = jQuery('select[name="Billboard-Location"]').val(); const dateRange = jQuery('#date_range').val(); // Store all form data for checkout if (selectedPurpose && selectedPurpose !== 'Select a Purpose') { localStorage.setItem('selectedPurpose', selectedPurpose); } if (selectedState) { localStorage.setItem('selectedState', selectedState); } if (selectedCity) { localStorage.setItem('selectedCity', selectedCity); } if (billboardLocation) { localStorage.setItem('billboardLocation', billboardLocation); } if (dateRange) { localStorage.setItem('runDates', dateRange); } console.log('Form data stored for checkout:', { purpose: selectedPurpose, state: selectedState, city: selectedCity, location: billboardLocation, dates: dateRange }); }); });

      /* Section headers */ .design-section-title { font-size: 24px; font-weight: 600; margin: 30px 0 20px; color: #333; text-align: center; } /* Billboard preview container */ .billboard-preview-container { background: white; border-radius: 8px; padding: 20px; margin-bottom: 30px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .billboard-canvas-container { position: relative; width: 100%; max-width: 800px; margin: 0 auto; background: #000; border-radius: 8px; overflow: hidden; } #billboardCanvas { width: 100%; height: auto; display: block; background: #000; } /* Template selection */ .template-selection { display: flex; justify-content: center; gap: 10px; margin-bottom: 30px; flex-wrap: wrap; } .template-option { width: 120px; height: 80px; border: 3px solid transparent; border-radius: 8px; cursor: pointer; transition: all 0.3s; overflow: hidden; position: relative; } .template-option.active { border-color: #0D7EE8; box-shadow: 0 0 15px rgba(13,126,232,0.3); } .template-option img { width: 100%; height: 100%; object-fit: cover; } .template-option::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.3); opacity: 0; transition: opacity 0.3s; } .template-option:hover::after { opacity: 1; } /* Text editor section */ .text-editor-section { background: white; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .text-line-container { margin-bottom: 15px; display: flex; align-items: center; gap: 10px; } .text-line-input { flex: 1; padding: 12px 15px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px; font-weight: bold; } .text-controls { display: flex; gap: 5px; } /* Color picker dropdown */ .color-picker-dropdown { position: relative; width: 36px; height: 36px; } .color-picker-btn { width: 100%; height: 100%; border: 1px solid #ddd; border-radius: 4px; cursor: pointer; position: relative; background: #ffffff; } .color-picker-btn::after { content: '▼'; position: absolute; right: 2px; top: 50%; transform: translateY(-50%); font-size: 8px; color: white; text-shadow: 1px 1px 2px rgba(0,0,0,0.5); } .color-dropdown { position: absolute; top: 100%; left: 0; background: #f5f5f5; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); z-index: 1000; display: none; padding: 20px; width: 420px; } .color-dropdown.show { display: block; } .color-palette { display: grid; grid-template-columns: repeat(10, 20px); gap: 3px; margin-bottom: 20px; padding: 15px; background: white; border-radius: 8px; border: 1px solid #e0e0e0; } .color-swatch { width: 20px; height: 20px; border-radius: 3px; cursor: pointer; border: 1px solid #ddd; transition: all 0.2s ease; position: relative; } .color-swatch:hover { transform: scale(1.1); border-color: #999; box-shadow: 0 2px 6px rgba(0,0,0,0.2); z-index: 1; } .color-swatch.selected { border: 2px solid #333; transform: scale(1.05); } .color-swatch.checkmark { background: #00ff00 !important; display: flex; align-items: center; justify-content: center; font-weight: bold; color: #000; font-size: 14px; } /* Advanced Color Picker Components */ .color-picker-advanced { display: flex; gap: 15px; background: white; border-radius: 8px; padding: 15px; border: 1px solid #e0e0e0; } .color-gradient-area { width: 240px; height: 180px; position: relative; background: linear-gradient(to right, #fff, #ff0000); border: 1px solid #ccc; cursor: crosshair; border-radius: 4px; } .color-gradient-area::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(to bottom, transparent, #000); pointer-events: none; border-radius: 3px; } .color-gradient-picker { position: absolute; width: 12px; height: 12px; border: 2px solid #fff; border-radius: 50%; box-shadow: 0 0 4px rgba(0,0,0,0.6); transform: translate(-50%, -50%); pointer-events: none; } .hue-slider-container { display: flex; flex-direction: column; gap: 10px; } .hue-slider { width: 24px; height: 180px; background: linear-gradient(to bottom, #ff0000 0%, #ffff00 16.66%, #00ff00 33.33%, #00ffff 50%, #0000ff 66.66%, #ff00ff 83.33%, #ff0000 100%); border: 1px solid #ccc; position: relative; cursor: pointer; border-radius: 4px; } .hue-slider-handle { position: absolute; width: 28px; height: 8px; background: #fff; border: 1px solid #333; left: -2px; transform: translateY(-50%); pointer-events: none; border-radius: 2px; } .color-preview-section { display: flex; flex-direction: column; gap: 15px; align-items: center; } .color-preview-large { width: 60px; height: 60px; border: 1px solid #ccc; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .color-picker-buttons { display: flex; gap: 10px; flex-direction: column; } .color-picker-btn-small { padding: 8px 16px; border: 1px solid #ddd; background: #fff; border-radius: 4px; cursor: pointer; font-size: 13px; transition: all 0.2s; min-width: 60px; } .color-picker-btn-small:hover { background: #f8f9fa; border-color: #999; } .color-picker-btn-small.cancel { color: #dc3545; border-color: #dc3545; } .color-picker-btn-small.cancel:hover { background: #f8d7da; } .color-picker-btn-small.choose { color: #28a745; border-color: #28a745; font-weight: 600; } .color-picker-btn-small.choose:hover { background: #d4edda; } /* Image Resize Dialog - Now uses Background Modal structure */ /* Specific styles for image resize content within modal */ #imageResizeModal .image-resize-container { position: relative; display: flex; align-items: center; justify-content: center; background: #f8f9fa; border-radius: 8px; padding: 20px; } #imageResizeModal .image-resize-canvas { position: relative; display: inline-block; max-width: 600px; max-height: 400px; } #imageResizeModal .resize-image { max-width: 600px; max-height: 400px; display: block; user-select: none; pointer-events: none; } #imageResizeModal .crop-overlay { position: absolute; border: 2px solid #00bcd4; background: rgba(0, 188, 212, 0.2); cursor: move; min-width: 50px; min-height: 50px; box-sizing: border-box; } #imageResizeModal .crop-overlay::before { content: ''; position: absolute; top: 2px; left: 2px; right: 2px; bottom: 2px; border: 1px dashed #ffffff; pointer-events: none; } #imageResizeModal .crop-handle { position: absolute; width: 12px; height: 12px; background: #00bcd4; border: 2px solid white; border-radius: 50%; box-shadow: 0 2px 4px rgba(0,0,0,0.3); } #imageResizeModal .crop-handle.nw { top: -6px; left: -6px; cursor: nw-resize; } #imageResizeModal .crop-handle.ne { top: -6px; right: -6px; cursor: ne-resize; } #imageResizeModal .crop-handle.sw { bottom: -6px; left: -6px; cursor: sw-resize; } #imageResizeModal .crop-handle.se { bottom: -6px; right: -6px; cursor: se-resize; } .resize-btn.done { background: #007bff; color: white; } .resize-btn.done:hover { background: #0056b3; } .settings-btn { width: 36px; height: 36px; border: 1px solid #ddd; background: #f8f9fa; border-radius: 4px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; } .settings-btn:hover { background: #e9ecef; border-color: #0D7EE8; } /* Font selector */ .font-selector { margin-bottom: 20px; } .font-dropdown { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; background: white; } /* Design options section */ .design-options-section { background: white; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .design-options-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 20px; } .design-option { display: flex; flex-direction: column; } .design-option-label { font-weight: 600; margin-bottom: 10px; color: #333; } .color-picker-container { display: flex; align-items: center; gap: 10px; } .color-preview { width: 40px; height: 40px; border-radius: 6px; border: 2px solid #ddd; cursor: pointer; transition: all 0.2s; } .color-preview:hover { border-color: #0D7EE8; transform: scale(1.05); } .color-value { font-family: monospace; font-size: 14px; color: #666; } /* Upload section */ .upload-section { background: white; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .upload-container { border: 2px dashed #ddd; border-radius: 8px; padding: 40px 20px; text-align: center; transition: all 0.3s; cursor: pointer; background: #fafafa; } .upload-container:hover { border-color: #0D7EE8; background-color: rgba(13,126,232,0.05); } .upload-icon { font-size: 48px; color: #999; margin-bottom: 15px; } .upload-text { color: #666; margin-bottom: 10px; font-weight: 500; } .upload-subtext { color: #999; font-size: 14px; } /* Validation messages */ .validation-message { margin-top: 10px; padding: 8px 12px; border-radius: 4px; font-size: 14px; font-weight: 500; } .validation-message.error { background-color: #fee; color: #c33; border: 1px solid #fcc; } .validation-message.warning { background-color: #fff3cd; color: #856404; border: 1px solid #ffeaa7; } .validation-message.success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; } /* Character counter */ .character-counter { font-size: 12px; color: #666; margin-top: 5px; text-align: right; } .character-counter.warning { color: #856404; } .character-counter.error { color: #c33; } /* Background graphics section */ .background-graphics { display: grid; grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); gap: 10px; margin-top: 10px; } .background-graphic-item { aspect-ratio: 1; border: 2px solid transparent; border-radius: 6px; overflow: hidden; cursor: pointer; transition: all 0.2s; background: #f8f9fa; display: flex; align-items: center; justify-content: center; font-size: 12px; color: #666; text-align: center; } .background-graphic-item:hover { border-color: #0D7EE8; transform: scale(1.05); } .background-graphic-item.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.1); } .background-graphic-item img { width: 100%; height: 100%; object-fit: cover; } /* Font settings modal - Now uses Background Modal structure */ /* Specific styles for font settings content within modal */ #fontModal .font-setting-row, #editorFontModal .font-setting-row { display: flex; align-items: center; margin-bottom: 15px; gap: 15px; } #fontModal .font-setting-label, #editorFontModal .font-setting-label { font-weight: 600; color: #333; min-width: 120px; font-size: 14px; } #fontModal .font-setting-control, #editorFontModal .font-setting-control { flex: 1; } #fontModal .font-dropdown, #fontModal .font-family-dropdown, #editorFontModal .font-dropdown, #editorFontModal .font-family-dropdown { width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; background: white; } #fontModal .font-size-input, #editorFontModal .font-size-input { width: 80px; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; } #fontModal .shadow-checkbox, #editorFontModal .shadow-checkbox { width: 18px; height: 18px; } #fontModal .shadow-width-slider, #editorFontModal .shadow-width-slider { flex: 1; margin-right: 10px; } #fontModal .apply-all-checkbox, #editorFontModal .apply-all-checkbox { margin-top: 20px; padding-top: 15px; border-top: 1px solid #eee; display: flex; align-items: center; gap: 8px; } #fontModal .apply-all-checkbox input, #editorFontModal .apply-all-checkbox input { width: 16px; height: 16px; } #fontModal .apply-all-checkbox label, #editorFontModal .apply-all-checkbox label { font-size: 14px; color: #333; cursor: pointer; } .font-setting-row { display: flex; align-items: center; margin-bottom: 18px; min-height: 40px; } .font-setting-label { width: 130px; font-weight: 600; color: #333; font-size: 14px; flex-shrink: 0; } .font-setting-control { flex: 1; display: flex; align-items: center; } .font-dropdown, .font-size-dropdown, .font-size-input { width: 100%; padding: 10px 12px; border: 2px solid #e1e1e1; border-radius: 6px; font-size: 14px; transition: border-color 0.3s ease; } .font-dropdown:focus, .font-size-input:focus { outline: none; border-color: #007cba; box-shadow: 0 0 0 3px rgba(0, 124, 186, 0.1); } .font-size-input { text-align: center; font-weight: bold; max-width: 80px; } .shadow-checkbox { width: 20px; height: 20px; cursor: pointer; accent-color: #007cba; } .shadow-width-slider { width: 100%; height: 6px; border-radius: 3px; background: #e1e1e1; outline: none; cursor: pointer; -webkit-appearance: none; appearance: none; } .shadow-width-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 20px; height: 20px; border-radius: 50%; background: #007cba; cursor: pointer; box-shadow: 0 2px 6px rgba(0,0,0,0.2); } .shadow-width-slider::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%; background: #007cba; cursor: pointer; border: none; box-shadow: 0 2px 6px rgba(0,0,0,0.2); } .apply-all-checkbox { margin: 25px 0 20px 0; padding: 15px; background: #f8f9fa; border-radius: 8px; border: 1px solid #e9ecef; display: flex; align-items: center; gap: 12px; } .apply-all-checkbox input[type="checkbox"] { width: 18px; height: 18px; cursor: pointer; accent-color: #007cba; } .apply-all-checkbox label { color: #495057 !important; font-weight: 500; font-size: 14px; cursor: pointer; margin: 0; user-select: none; } .modal-buttons { display: flex; gap: 12px; justify-content: center; margin-top: 25px; padding-top: 20px; border-top: 1px solid #e9ecef; } .modal-btn { padding: 12px 30px; border: none; border-radius: 25px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.2s; } .modal-btn.apply { background: #007bff; color: white; } .modal-btn.apply:hover { background: #0056b3; } .modal-btn.cancel { background: #6c757d; color: white; } .modal-btn.cancel:hover { background: #545b62; } /* Submit button */ .submit-container { text-align: center; margin: 30px 0; } .submit-button { background-color: #0D7EE8; color: white; border: none; padding: 15px 40px; font-size: 16px; border-radius: 6px; cursor: pointer; font-weight: 600; transition: all 0.2s; text-transform: uppercase; letter-spacing: 1px; } .submit-button:hover { background-color: #0A6AC7; transform: translateY(-2px); box-shadow: 0 4px 15px rgba(13,126,232,0.3); } /* No templates message */ .no-templates-message { text-align: center; padding: 60px 20px; color: #666; font-size: 16px; background: linear-gradient(135deg, #f8f9fa, #e9ecef); border-radius: 12px; margin: 20px 0; border: 2px dashed #ddd; min-height: 200px; display: flex; flex-direction: column; justify-content: center; align-items: center; } .no-templates-message h3 { color: #333; margin-bottom: 15px; font-size: 24px; font-weight: 600; } .no-templates-message p { margin: 0; font-size: 16px; color: #666; max-width: 400px; line-height: 1.5; } /* Purpose display styling */ #purposeDisplay { background: linear-gradient(135deg, #0D7EE8, #0A6AC7); color: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(13,126,232,0.2); } /* Checkout Dialog - Now uses Background Modal structure */ /* Specific styles for checkout content within modal */ #checkoutDialog .order-summary { background: #f9f9f9; padding: 16px; border-radius: 4px; margin-bottom: 16px; border: 1px solid #ddd; } #checkoutDialog .order-summary h3 { margin: 0 0 12px 0; color: #23282d; font-size: 16px; font-weight: 600; font-family: Arial, sans-serif; } #checkoutDialog .summary-row { display: flex; justify-content: space-between; align-items: center; padding: 6px 0; border-bottom: 1px solid #e1e1e1; font-size: 14px; } #checkoutDialog .summary-row:last-child { border-bottom: none; font-weight: 600; font-size: 16px; color: #007cba; margin-top: 8px; padding-top: 12px; border-top: 2px solid #e1e1e1; } #checkoutDialog .summary-label { font-weight: 500; color: #555; } #checkoutDialog .summary-value { font-weight: 600; color: #23282d; } #checkoutDialog .checkbox-section { background: #f8f9fa; padding: 16px; border-radius: 4px; border: 1px solid #ddd; } #checkoutDialog .checkbox-section h3 { margin: 0 0 12px 0; color: #23282d; font-size: 16px; font-weight: 600; font-family: Arial, sans-serif; } #checkoutDialog .checkbox-item { display: flex; align-items: flex-start; margin-bottom: 10px; gap: 8px; } #checkoutDialog .checkbox-item:last-child { margin-bottom: 0; } #checkoutDialog .checkbox-item input[type="checkbox"] { margin-top: 2px; flex-shrink: 0; width: 16px; height: 16px; } #checkoutDialog .checkbox-text { font-size: 14px; line-height: 1.4; color: #23282d; cursor: pointer; font-family: Arial, sans-serif; } #checkoutDialog .terms-link { color: #007cba !important; text-decoration: underline !important; cursor: pointer !important; font-weight: 500 !important; } #checkoutDialog .terms-link:hover { color: #005a87 !important; } /* Order Summary Styles for Dialog */ .order-summary { background: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .summary-row { display: flex; justify-content: space-between; margin-bottom: 10px; padding: 10px 0; border-bottom: 1px solid #eee; } .summary-row:last-child { border-bottom: 2px solid #0D7EE8; font-weight: bold; font-size: 18px; } .checkbox-section { background: white; padding: 25px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .checkbox-section h3 { margin-top: 0; margin-bottom: 20px; color: #0D7EE8; font-size: 18px; font-weight: 600; } .checkbox-item { margin-bottom: 20px; display: flex; align-items: flex-start; gap: 12px; line-height: 1.5; } .checkbox-item:last-child { margin-bottom: 0; } .checkbox-item input[type="checkbox"] { margin: 0; margin-top: 3px; flex-shrink: 0; width: 18px; height: 18px; cursor: pointer; } .checkbox-item label { color: #333 !important; font-weight: 500; cursor: pointer; margin: 0; flex: 1; font-size: 14px; line-height: 1.5; display: block; } .checkbox-item .checkbox-text { display: block; color: #333; font-weight: 500; font-size: 14px; line-height: 1.5; cursor: pointer; } .terms-link { color: #0D7EE8 !important; text-decoration: underline !important; cursor: pointer !important; font-weight: 500 !important; } .terms-link:hover { color: #0A6AC7 !important; text-decoration: none !important; } /* Terms Modal - Now uses Background Modal structure */ /* Specific styles for terms content within modal */ #termsModal .cf7-modal-body { max-height: 60vh; overflow-y: auto; line-height: 1.6; color: #333; } #termsModal .cf7-step-title { color: #007cba; font-size: 18px; font-weight: 600; margin-top: 25px; margin-bottom: 15px; } #termsModal .cf7-step-title:first-child { margin-top: 0; } #termsModal p, #termsModal li { margin-bottom: 12px; font-size: 14px; } #termsModal ul { padding-left: 20px; margin-bottom: 20px; } #termsModal strong { color: #d63384; font-weight: 600; } /* Anniversary Templates Styling */ .anniversary-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .anniversary-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .anniversary-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .anniversary-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Benefit Templates Styling */ .benefit-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .benefit-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .benefit-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .benefit-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Christian Templates Styling */ .christian-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .christian-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .christian-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .christian-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Graduation Templates Styling */ .graduation-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .graduation-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .graduation-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .graduation-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* UNIVERSAL TEMPLATE STYLING - Works for any purpose */ .universal-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .universal-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .universal-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .universal-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } .universal-template-preview { height: 200px; overflow: hidden; position: relative; background: #000; display: flex; align-items: center; justify-content: center; color: white; text-align: center; padding: 20px; } .universal-template-content { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; } .universal-template-text { margin: 4px 0; font-weight: bold; text-shadow: 1px 1px 2px rgba(0,0,0,0.5); } .universal-template-label { padding: 12px; text-align: center; font-weight: 600; color: #333; background: #f8f9fa; border-top: 1px solid #eee; } .template-preview { height: 200px; overflow: hidden; position: relative; } /* Anniversary template background images */ .anniversary-template-card[data-template="anniversary-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-1.png'); background-size: cover; background-position: center; } .anniversary-template-card[data-template="anniversary-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-2.png'); background-size: cover; background-position: center; } .anniversary-template-card[data-template="anniversary-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-3.png'); background-size: cover; background-position: center; } /* Benefit template background images */ .benefit-template-card[data-template="benefit-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-3.png'); background-size: cover; background-position: center; } .benefit-template-card[data-template="benefit-template-2"] .template-preview { background-color: #000000; } .benefit-template-card[data-template="benefit-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-5.png'); background-size: cover; background-position: center; } /* Christian template background images */ .christian-template-card[data-template="christian-template-1"] .template-preview { background-color: #000000; } .christian-template-card[data-template="christian-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-15.png'); background-size: cover; background-position: center; } .christian-template-card[data-template="christian-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-12.png'); background-size: cover; background-position: center; } /* Graduation template background images */ .graduation-template-card[data-template="graduation-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-13.png'); background-size: cover; background-position: center; } .graduation-template-card[data-template="graduation-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-14.png'); background-size: cover; background-position: center; } .graduation-template-card[data-template="graduation-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-3.png'); background-size: cover; background-position: center; } /* Holiday Templates Styling */ .holiday-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .holiday-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 8px rgba(0,0,0,0.1); } .holiday-template-card:hover { transform: translateY(-5px); box-shadow: 0 8px 16px rgba(0,0,0,0.2); border-color: #28a745; } .holiday-template-card.selected { border-color: #28a745; background: rgba(40,167,69,0.05); } /* Holiday template background images */ .holiday-template-card[data-template="holiday-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-1.png'); background-size: cover; background-position: center; } .holiday-template-card[data-template="holiday-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-8.png'); background-size: cover; background-position: center; } .holiday-template-card[data-template="holiday-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-4.png'); background-size: cover; background-position: center; } /* Local School Templates Styling */ .local-school-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .local-school-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 8px rgba(0,0,0,0.1); } .local-school-template-card:hover { transform: translateY(-2px); box-shadow: 0 8px 16px rgba(0,0,0,0.2); border-color: #0D7EE8; } .local-school-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Local School template background images */ .local-school-template-card[data-template="local-school-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-3.png'); background-size: cover; background-position: center; } .local-school-template-card[data-template="local-school-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-7.png'); background-size: cover; background-position: center; } .local-school-template-card[data-template="local-school-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-5.png'); background-size: cover; background-position: center; } /* Love Templates Styling */ .love-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .love-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 8px rgba(0,0,0,0.1); } .love-template-card:hover { transform: translateY(-2px); box-shadow: 0 8px 16px rgba(0,0,0,0.2); border-color: #e91e63; } .love-template-card.selected { border-color: #e91e63; background: rgba(233,30,99,0.05); } /* Love template background images */ .love-template-card[data-template="love-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-6.png'); background-size: cover; background-position: center; } .love-template-card[data-template="love-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-14.png'); background-size: cover; background-position: center; } .love-template-card[data-template="love-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-3.png'); background-size: cover; background-position: center; } /* Marry Me Templates Styling */ .marry-me-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .marry-me-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .marry-me-template-card:hover { transform: translateY(-2px); box-shadow: 0 8px 16px rgba(0,0,0,0.2); border-color: #ff69b4; } .marry-me-template-card.selected { border-color: #ff69b4; background: rgba(255,105,180,0.05); } /* Marry Me template background images */ .marry-me-template-card[data-template="marry-me-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-5.png'); background-size: cover; background-position: center; } .marry-me-template-card[data-template="marry-me-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-11.png'); background-size: cover; background-position: center; } .marry-me-template-card[data-template="marry-me-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-1.png'); background-size: cover; background-position: center; } /* Newborn Templates Styling */ .newborn-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .newborn-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .newborn-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .newborn-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Newborn template background images */ .newborn-template-card[data-template="newborn-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-1.png'); background-size: cover; background-position: center; } .newborn-template-card[data-template="newborn-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-12.png'); background-size: cover; background-position: center; } .newborn-template-card[data-template="newborn-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-7.png'); background-size: cover; background-position: center; } /* Obituary Templates Styling */ .obituary-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .obituary-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .obituary-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .obituary-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Obituary template background images */ .obituary-template-card[data-template="obituary-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-11.png'); background-size: cover; background-position: center; } .obituary-template-card[data-template="obituary-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-8.png'); background-size: cover; background-position: center; } .obituary-template-card[data-template="obituary-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-2.png'); background-size: cover; background-position: center; } /* Other Templates Styling */ .other-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .other-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .other-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .other-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Other template background images */ .other-template-card[data-template="other-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-2.png'); background-size: cover; background-position: center; } .other-template-card[data-template="other-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-5.png'); background-size: cover; background-position: center; } .other-template-card[data-template="other-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-1.png'); background-size: cover; background-position: center; } .template-preview { height: 200px; overflow: hidden; position: relative; } /* Pet Templates Styling */ .pet-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .pet-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .pet-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .pet-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } .pet-template-card .template-preview { height: 200px; overflow: hidden; position: relative; } .pet-template-card .template-label { padding: 15px; text-align: center; font-weight: 600; color: #333; background: #f8f9fa; border-top: 1px solid #eee; } /* Pet Template Preview Backgrounds */ .pet-template-card[data-template="pet-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-11.png'); background-size: cover; background-position: center; } .pet-template-card[data-template="pet-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-4.png'); background-size: cover; background-position: center; } .pet-template-card[data-template="pet-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-10.png'); background-size: cover; background-position: center; } /* Pet Template 3 specific positioning - text in red area */ .pet-template-card[data-template="pet-template-3"] .text-section { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); text-align: center; z-index: 2; } /* Retirement Templates Styling */ .retirement-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .retirement-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .retirement-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .retirement-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Wedding Templates Styling */ .wedding-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .wedding-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .wedding-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .wedding-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Prayer Templates Styling */ .prayer-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .prayer-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .prayer-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .prayer-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Retirement template background images */ .retirement-template-card[data-template="retirement-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-9.png'); background-size: cover; background-position: center; } .retirement-template-card[data-template="retirement-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-10.png'); background-size: cover; background-position: center; } .retirement-template-card[data-template="retirement-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-4.png'); background-size: cover; background-position: center; } /* Wedding template background images */ .wedding-template-card[data-template="wedding-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-10.png'); background-size: cover; background-position: center; } .wedding-template-card[data-template="wedding-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-1.png'); background-size: cover; background-position: center; } .wedding-template-card[data-template="wedding-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-3.png'); background-size: cover; background-position: center; } /* Prayer template background images */ .prayer-template-card[data-template="prayer-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-2.png'); background-size: cover; background-position: center; } .prayer-template-card[data-template="prayer-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-9.png'); background-size: cover; background-position: center; } .prayer-template-card[data-template="prayer-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-10.png'); background-size: cover; background-position: center; } /* Welcome Templates Styling */ .welcome-templates-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin: 20px 0; } .welcome-template-card { border: 3px solid transparent; border-radius: 12px; overflow: hidden; cursor: pointer; transition: all 0.3s ease; background: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } .welcome-template-card:hover { border-color: #0D7EE8; transform: translateY(-5px); box-shadow: 0 8px 25px rgba(13,126,232,0.2); } .welcome-template-card.selected { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } /* Welcome template background images */ .welcome-template-card[data-template="welcome-template-1"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-10.png'); background-size: cover; background-position: center; } .welcome-template-card[data-template="welcome-template-2"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-15.png'); background-size: cover; background-position: center; } .welcome-template-card[data-template="welcome-template-3"] .template-preview { background-image: url('https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-11.png'); background-size: cover; background-position: center; } /* Prayer Template Text Centering */ .prayer-template-card .text-section { display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; height: 100%; width: 100%; } .prayer-template-card .template-field-text { text-align: center; width: 100%; margin: 2px 0; } .template-layout.horizontal-split { display: flex; height: 100%; width: 100%; } .template-layout.text-only { display: flex; height: 100%; width: 100%; align-items: center; justify-content: center; } .text-section { flex: 1; padding: 15px; display: flex; flex-direction: column; justify-content: center; background: transparent; color: white; position: relative; } .text-section.full-width { width: 100%; text-align: center; align-items: center; } .template-field-text { font-size: 14px; font-weight: bold; margin: 2px 0; text-align: center; text-shadow: 1px 1px 2px rgba(0,0,0,0.5); } /* Benefit Template 2 specific styles */ .template-layout.full-text { display: flex; height: 100%; width: 100%; } .text-section.full-width { width: 100%; padding: 10px; display: flex; flex-direction: column; justify-content: center; align-items: center; } .template-field-text.red-text { color: #ff0000 !important; } /* Christian template text styling */ .template-field-text.gold-text { color: #FFD700 !important; font-weight: bold; } .template-field-text.gold-text.large { color: #FFD700 !important; font-size: 18px; font-weight: 900; letter-spacing: 1px; } .template-field-text.white-text { color: #ffffff !important; } .template-field-text.large { font-size: 18px !important; font-weight: 900 !important; letter-spacing: 1px; } .template-field-text.script { font-family: 'Dancing Script', cursive !important; font-style: italic; font-size: 16px !important; } .template-field-text.bold { font-weight: 700 !important; font-size: 15px !important; } .template-field-text.medium { font-size: 13px !important; font-weight: 700 !important; } .image-section { flex: 1; display: flex; align-items: center; justify-content: center; background: transparent; } .image-section.full-image img { width: 100%; height: 100%; object-fit: cover; } .image-section.placeholder-space { background: transparent; } .upload-placeholder { text-align: center; color: #666; } .upload-placeholder .upload-icon { font-size: 24px; margin-bottom: 5px; } .upload-placeholder .upload-text { font-size: 12px; font-weight: 500; } .image-section.centered-image { padding: 20px; } .image-section.centered-image img { width: 80px; height: 80px; border-radius: 50%; object-fit: cover; border: 3px solid white; box-shadow: 0 2px 10px rgba(0,0,0,0.2); } .template-label { padding: 12px; text-align: center; font-weight: 600; color: #333; background: #f8f9fa; border-top: 1px solid #eee; } /* Interactive Template Editor */ .template-editor-container { display: none; background: white; border-radius: 12px; padding: 30px; margin: 20px 0; box-shadow: 0 4px 20px rgba(0,0,0,0.1); border: 2px solid #0D7EE8; } .template-editor-container.active { display: block; } .editor-canvas-container { position: relative; width: 100%; max-width: 800px; margin: 0 auto 30px; background: #000; border-radius: 8px; overflow: hidden; aspect-ratio: 2/1; /* Fixed 2:1 aspect ratio */ } .editor-canvas { width: 100%; height: 100%; display: block; background: #000; } .editor-controls { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-top: 20px; } .text-editing-panel { background: #f8f9fa; border-radius: 8px; padding: 20px; } .image-editing-panel { background: #f8f9fa; border-radius: 8px; padding: 20px; } .background-graphic-button { background: #0D7EE8; color: white; border: none; padding: 12px 24px; border-radius: 6px; font-weight: 600; cursor: pointer; transition: all 0.2s; margin-bottom: 15px; width: 100%; } .background-graphic-button:hover { background: #0A6AC7; transform: translateY(-1px); } /* Background Graphic Dialog - Now uses Background Modal structure */ /* CF7 Modal Styles - WordPress Compatible (copied from working dfindex.html) */ .wpcf7 .cf7-background-modal, .cf7-background-modal { border: none !important; border-radius: 8px !important; padding: 0 !important; max-width: 90vw !important; max-height: 90vh !important; width: 800px !important; background: white !important; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3) !important; overflow: hidden !important; position: fixed !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; z-index: 999999 !important; margin: 0 !important; inset: auto !important; } /* Modal Backdrop - WordPress Override */ .wpcf7 .cf7-background-modal::backdrop, .cf7-background-modal::backdrop { background: rgba(0, 0, 0, 0.5) !important; backdrop-filter: blur(2px) !important; position: fixed !important; top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important; z-index: 999998 !important; } /* Modal Content - WordPress Override - FIXED: Remove conflicting overflow */ .wpcf7 .cf7-modal-content, .cf7-modal-content { display: flex !important; flex-direction: column !important; height: 100% !important; max-height: 80vh !important; min-height: 400px !important; width: 100% !important; box-sizing: border-box !important; overflow: visible !important; /* FIXED: Changed from hidden to visible to prevent double scrollbars */ } .cf7-modal-header { position: relative; padding: 20px; border-bottom: 1px solid #ddd; background: #f8f9fa; } .cf7-modal-title { margin: 0 0 5px 0; font-size: 1.5em; color: #333; font-weight: 600; } .cf7-modal-description { margin: 0; color: #666; font-size: 0.9em; } .cf7-modal-close { position: absolute; top: 15px; right: 15px; background: none; border: none; font-size: 24px; cursor: pointer; color: #666; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.2s; } .cf7-modal-close:hover { background: #e9ecef; color: #333; } .cf7-modal-body { flex: 1; padding: 20px; overflow-y: auto !important; /* ONLY scrollbar should be here in modal body */ overflow-x: hidden !important; background: white; max-height: calc(80vh - 140px) !important; /* Account for header and footer */ } .cf7-modal-footer { padding: 15px 20px; border-top: 1px solid #ddd; background: #f8f9fa; display: flex; justify-content: flex-end; gap: 10px; } .cf7-btn-cancel, .cf7-btn-apply { padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.2s; min-width: 80px; } .cf7-btn-cancel { background: #6c757d; color: white; } .cf7-btn-cancel:hover { background: #545b62; } .cf7-btn-apply { background: #007cba; color: white; } .cf7-btn-apply:hover { background: #005a87; } /* Modal Fallback for WordPress - Force positioning */ .wpcf7 dialog.cf7-background-modal, dialog.cf7-background-modal { position: fixed !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; z-index: 999999 !important; margin: 0 !important; inset: auto !important; } /* Ensure modal shows above WordPress admin bar and other elements */ .wpcf7 .cf7-background-modal[open], .cf7-background-modal[open] { display: flex !important; position: fixed !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; z-index: 999999 !important; visibility: visible !important; opacity: 1 !important; } /* WordPress Modal Content Layout Fix */ .wpcf7 .cf7-background-modal .cf7-modal-content, .cf7-background-modal .cf7-modal-content { width: 100% !important; height: 100% !important; display: flex !important; flex-direction: column !important; overflow: hidden !important; } /* Modal Steps - WordPress Override with proper step switching */ .wpcf7 .cf7-modal-step, .cf7-modal-step { width: 100% !important; height: auto !important; visibility: visible !important; opacity: 1 !important; position: relative !important; box-sizing: border-box !important; } /* When step is explicitly shown */ .wpcf7 .cf7-modal-step[style*="display: block"], .cf7-modal-step[style*="display: block"] { display: block !important; visibility: visible !important; opacity: 1 !important; } /* When step is explicitly hidden */ .wpcf7 .cf7-modal-step[style*="display: none"], .cf7-modal-step[style*="display: none"] { display: none !important; visibility: hidden !important; opacity: 0 !important; } /* Fix for WordPress theme interference */ .wpcf7 .cf7-background-modal * { box-sizing: border-box !important; } /* Specific styles for background graphic content within modal */ #backgroundGraphicDialog .background-type-selector { display: flex; gap: 12px; margin-bottom: 24px; justify-content: center; flex-wrap: wrap; } #backgroundGraphicDialog .background-type-btn { padding: 12px 24px; border: 2px solid #ddd; background: white; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 14px; transition: all 0.3s ease; display: flex; align-items: center; gap: 8px; min-width: 160px; justify-content: center; } #backgroundGraphicDialog .background-type-btn:hover { border-color: #007cba; background: #f0f8ff; transform: translateY(-1px); box-shadow: 0 2px 8px rgba(0, 124, 186, 0.2); } #backgroundGraphicDialog .background-type-btn.active { background: #007cba; color: white; border-color: #007cba; box-shadow: 0 4px 12px rgba(0, 124, 186, 0.3); } #backgroundGraphicDialog .background-section { margin-top: 24px; min-height: 300px; } #backgroundGraphicDialog .stockImage-backgrounds-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 16px; max-height: none !important; /* FIXED: Remove max-height to prevent double scrollbar */ overflow: visible !important; /* FIXED: Remove overflow to prevent double scrollbar */ padding: 20px; border: 2px solid #e1e5e9; border-radius: 8px; background: #fafbfc; margin-bottom: 20px; } /* REMOVED: Custom scrollbar styles since grid no longer has overflow */ /* Style for individual background image items */ #backgroundGraphicDialog .stockImage-bg-option { border-radius: 8px !important; overflow: hidden; cursor: pointer; transition: all 0.3s ease !important; border: 3px solid transparent !important; background: white; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important; aspect-ratio: 1 !important; } #backgroundGraphicDialog .stockImage-bg-option:hover { transform: translateY(-2px) !important; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15) !important; border-color: #007cba !important; } #backgroundGraphicDialog .stockImage-bg-option.selected { border-color: #007cba !important; box-shadow: 0 4px 16px rgba(0, 124, 186, 0.3) !important; } #backgroundGraphicDialog .stockImage-bg-option img { width: 100% !important; height: 100% !important; object-fit: cover !important; display: block !important; } #backgroundGraphicDialog .background-color-picker-container { padding: 24px; border: 2px solid #e1e5e9; border-radius: 8px; background: #fafbfc; text-align: center; } #backgroundGraphicDialog .background-color-picker-container h4 { margin: 0 0 16px 0; color: #333; font-size: 16px; font-weight: 600; } #backgroundGraphicDialog .color-picker-wrapper { display: flex; flex-direction: column; align-items: center; gap: 12px; } #backgroundGraphicDialog .color-picker-input { width: 80px; height: 40px; border: 2px solid #ddd; border-radius: 6px; cursor: pointer; transition: all 0.2s ease; } #backgroundGraphicDialog .color-picker-input:hover { border-color: #007cba; transform: scale(1.05); } #backgroundGraphicDialog .color-picker-label { font-size: 14px; color: #666; font-weight: 500; } /* Improve modal footer for background dialog */ #backgroundGraphicDialog .cf7-modal-footer { padding: 20px 24px; border-top: 2px solid #e1e5e9; background: #f8f9fa; display: flex; justify-content: center; gap: 16px; } #backgroundGraphicDialog .cf7-btn-apply { min-width: 140px; padding: 12px 24px; font-size: 16px; font-weight: 600; } /* Mobile Responsive (copied from working dfindex.html) */ @media (max-width: 768px) { .cf7-background-modal { width: 95vw !important; max-height: 95vh !important; } .cf7-modal-header, .cf7-modal-body, .cf7-modal-footer { padding: 15px !important; } .cf7-modal-footer { flex-direction: column !important; } .cf7-btn-cancel, .cf7-btn-apply { width: 100% !important; margin: 5px 0 !important; } /* Mobile-specific background dialog improvements */ #backgroundGraphicDialog .background-type-selector { flex-direction: column; gap: 8px; } #backgroundGraphicDialog .background-type-btn { min-width: auto; padding: 10px 16px; font-size: 14px; } #backgroundGraphicDialog .stockImage-backgrounds-grid { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 12px; padding: 16px; max-height: none !important; /* FIXED: Remove max-height to prevent double scrollbar on mobile */ } #backgroundGraphicDialog .stockImage-bg-option { border-width: 2px !important; } #backgroundGraphicDialog .stockImage-bg-option img { height: auto !important; } } .stockImage-backgrounds-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 15px; margin-top: 20px; } .stockImage-bg-option { aspect-ratio: 1; border: 3px solid transparent; border-radius: 8px; overflow: hidden; cursor: pointer; transition: all 0.2s; position: relative; } .stockImage-bg-option:hover { border-color: #0D7EE8; transform: scale(1.05); } .stockImage-bg-option.selected { border-color: #0D7EE8; box-shadow: 0 0 15px rgba(13,126,232,0.3); } .stockImage-bg-option img { width: 100%; height: 100%; object-fit: cover; } /* Background Type Selector */ .background-type-selector { display: flex; gap: 10px; margin-bottom: 20px; justify-content: center; } .background-type-btn { padding: 12px 24px; border: 2px solid #ddd; background: white; border-radius: 8px; cursor: pointer; font-weight: 600; transition: all 0.2s; font-size: 14px; } .background-type-btn:hover { border-color: #0D7EE8; background: rgba(13,126,232,0.05); } .background-type-btn.active { border-color: #0D7EE8; background: #0D7EE8; color: white; } /* Background Sections */ .background-section { margin-top: 20px; } /* Background Color Picker Container */ .background-color-picker-container { display: flex; justify-content: center; padding: 20px; } .template-editor-actions { display: flex; justify-content: center; gap: 20px; margin-top: 30px; padding-top: 20px; border-top: 1px solid #eee; } .template-editor-actions .modal-btn { padding: 12px 30px; border: none; border-radius: 25px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.2s; min-width: 150px; } .template-editor-actions .modal-btn.apply { background: #007bff; color: white; } .template-editor-actions .modal-btn.apply:hover { background: #0056b3; transform: translateY(-1px); } .template-editor-actions .modal-btn.cancel { background: #6c757d; color: white; } .template-editor-actions .modal-btn.cancel:hover { background: #545b62; transform: translateY(-1px); } .template-editor-actions .modal-btn.secondary { background: #ffc107; color: #212529; border: 1px solid #ffc107; } .template-editor-actions .modal-btn.secondary:hover { background: #e0a800; border-color: #d39e00; transform: translateY(-1px); } /* Responsive adjustments for Anniversary */ @media (max-width: 768px) { .anniversary-templates-container { grid-template-columns: 1fr; } .editor-controls { grid-template-columns: 1fr; } /* Template Editor Mobile Optimizations */ .template-editor-container { padding: 15px; margin: 10px 0; border-radius: 8px; } .editor-canvas-container { margin-bottom: 20px; } .text-editing-panel, .image-editing-panel { padding: 15px; margin-bottom: 15px; } .text-editing-panel h3, .image-editing-panel h3 { font-size: 16px; margin-bottom: 15px; } .background-graphic-button { padding: 12px 20px; font-size: 14px; margin-bottom: 15px; } .template-editor-actions { flex-direction: column; gap: 10px; } .modal-btn { padding: 12px 20px; font-size: 14px; width: 100%; } /* Background Graphic Dialog Mobile */ .background-graphic-dialog .dialog-content { width: 95%; max-width: none; margin: 10px; padding: 20px; } .stockImage-backgrounds-grid { grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); gap: 10px; } .stockImage-bg-option { border-width: 2px; } } /* Extra small screens */ @media (max-width: 480px) { .template-editor-container { padding: 10px; margin: 5px 0; } .text-editing-panel, .image-editing-panel { padding: 12px; } .stockImage-backgrounds-grid { grid-template-columns: repeat(auto-fill, minmax(70px, 1fr)); gap: 8px; } .background-graphic-dialog .dialog-content { padding: 15px; } } Selected Purpose: Select a Design Please Select a Purpose Choose a purpose from the dropdown menu to view available templates. Choose Your Anniversary Template HAPPY ANNIVERSARY John & Jane Love: Family Template 1: Full Image HAPPY ANNIVERSARY John & Jane Love: Family Template 2: Upload Space HAPPY ANNIVERSARY John & Jane Love: Family Template 3: Centered Image Choose Your Benefit Template BENEFIT FOR John & Jane Smith for Medical Bills Jan. 12, 5 PM at the City Park Template 1: Classic Red BENEFIT FOR John & Jane Smith for Medical Bills Jan. 12, 5 PM at the City Park Template 2: Text Only BENEFIT FOR John & Jane Smith for Medical Bills Jan. 12, 5 PM at the City Park Template 3: Green Accent Choose Your Graduation Template Congratulations! John Doe Wishing you success ahead. Cheers to new beginnings! Template 1: Text Only It's time! John Doe Congratulations! Make it count! Template 2: Gold Style HAPPY GRADUATION John Doe CHS Graduate Template 3: Happy Graduation Choose Your Christian Template For the Spirit God gave us does not make us timid, but gives us power, love and self-discipline. 2 Timothy 1:7 Template 1: Scripture Black Therefore, if anyone is in Christ, the new creation has come: The old has gone, the new is here! 2 Corinthians 5:17 Template 2: Cross Background I can do all things through Christ who strengthens me. Philippians 4:13 Template 3: Inspirational Gold Choose Your Holiday Template Warmest Wishes for a Joyful Holiday Season from Us All! Template 1: Holiday Wishes Merry Christmas Filled with Love and Cheerful Moments from Our Family! Template 2: Christmas Family Happy New Year Wishing You Joy and New Beginnings from Us All! Template 3: New Year Choose Your Local School Template Inspire Every Mind Learn with Passion Grow with Purpose Achieve Your Dreams Template 1: Inspire Every Mind Embrace Knowledge Spark Creativity Build Your Future Shine Brightly Template 2: Embrace Knowledge Discover Your Path Grow with Courage Learn Without Limits Lead with Heart Template 3: Discover Your Path Choose Your Love Template I LOVE YOU Jane Doe John Doe Template 1: Love Declaration I LOVE YOU Jane Doe John Doe Template 2: Love Message I LOVE YOU Jane Doe John Doe Template 3: Pure Love Choose Your Marry Me Template Jane Doe Will You Marry ME? -John Doe Template 1: Romantic Proposal Jane Doe Will You Marry ME? -John Doe Template 2: Centered Proposal Jane Doe Will You Marry ME? -John Doe Template 3: Pure Proposal Choose Your Newborn Template Baby John Doe 9 lbs. 4 oz. Parents: John & Jane Doe Template 1: Sweet Arrival Baby John Doe 9 lbs. 4 oz. Parents: John & Jane Doe Template 2: Joyful Welcome Welcome to the world Jane Doe 10 lbs. 5 oz. 20 " Long Love Mom & Dad Template 3: Blessed Arrival Choose Your Obituary Template In Loving Memory of John Doe 1950 - 2021 Template 1: Memorial Portrait In Loving Memory of John Doe 1950 - 2021 Template 2: Full Memorial In Loving Memory of John Doe 1950 - 2021 Template 3: Memorial Text Choose Your Other Template YOUR TEXT Text Here Text Here Text Here Template 1: Centered Image YOUR TEXT Text Here Text Here Text Here Template 2: Full Image YOUR TEXT Your Text Goes Here Your Text Here Your Text Goes Here Template 3: Text Only Choose Your Pet Template LOST DOG LAST SEEN ON MAIN ST. Terra 555-555-55555 Template 1: Centered Image LOST DOG LAST SEEN ON MAIN ST. Terra 555-555-55555 Template 2: Full Image LOST DOG LAST SEEN ON MAIN ST. Terra 555-555-55555 Template 3: Full Image Choose Your Retirement Template HAPPY RETIREMENT JOHN DOE From Your Friends Template 1: Full Image HAPPY RETIREMENT JOHN DOE From Your Friends Template 2: Full Image HAPPY RETIREMENT JOHN DOE From Your Friends Template 3: Text Only Choose Your Wedding Template Congratulations John & Jane Smith Love Your Parents Template 1: Full Image Congratulations John & Jane Smith Love Your Parents Template 2: Full Image Congratulations John & Jane Smith Love Your Parents Template 3: Text Only Choose Your Welcome Template WELCOME HOME JOHN DOE Love: Your Family Template 1: Full Image WELCOME HOME JOHN DOE Love: Your Family Template 2: Full Image WELCOME HOME JOHN DOE Love: Your Family Template 3: Text Only Choose Your Prayer Template YOUR PRAYER MESSAGE GOES RIGHT HERE PRAY FOR OUR COUNTRY PRAY FOR OUR COUNTRY Template 1: Full Image YOUR PRAYER MESSAGE GOES RIGHT HERE PRAY FOR OUR COUNTRY PRAY FOR OUR COUNTRY Template 2: Text Only YOUR PRAYER MESSAGE GOES RIGHT HERE PRAY FOR OUR COUNTRY PRAY FOR OUR COUNTRY Template 3: Text Only Choose Your Template Choose Your Template Edit Text ⚙️ ⚙️ ⚙️ ⚙️ Customize Design Background Graphic Upload Your Photo 📷 Click to upload your photo Accepted formats: JPG, PNG. High resolution recommended. Back to Templates Confirm Design 🖼️ Select Background Choose an image or color background for your billboard × 🖼️ Image Background 🎨 Color Background Reset Select 🔤 Editor Font Settings Customize font family, size, and shadow settings for editor text × Font Family Mouse Memoirs Domine Baloo Tamma Courgette Oswald Kaushan Script Alfa Slab One Montserrat Yellowtail Paytone One Indie Flower Dancing Script Anton Luckiest Guy Permanent Marker Sniglet Lobster Arial Font Size Shadow? Shadow Width 4 Apply to all text areas Cancel Apply 🔤 Font Settings Customize font family, size, and shadow settings × Font Mouse Memoirs Domine Baloo Tamma Courgette Oswald Kaushan Script Alfa Slab One Montserrat Yellowtail Paytone One Indie Flower Dancing Script Anton Luckiest Guy Permanent Marker Sniglet Lobster Arial Font Size Shadow? Shadow Width 4 Apply to all text areas Cancel Apply Continue to Checkout 📋 Review Your Billboard Order Review your order details and agree to terms before proceeding to payment × 📊 Order Summary Purpose: Loading... Billboard Location: Loading... Run Dates: Loading... Duration: Loading... Total Cost: $0.00 📋 Agreement & Requirements I agree to the terms and conditions Click here to read full terms I have NOT used photos of people smoking, drinking, hand symbols, showing too much skin. My ad is not a business ad or promotional ad in any way. The design above is exactly what my ad will look like. If it has to be changed, I will be charged $25. If your ad does not comply it will not play and you will not be refunded. Email me a copy of this ad Cancel Proceed to Payment 📋 Terms & Conditions Please read and accept our terms and conditions × Agreement These Terms are an agreement between you and Borges Media.com. Your access to and use of the Service is conditioned on your acceptance of and compliance with these Terms. These Terms apply to all visitors, users and others who access or use the Service. By accessing or using the Service you agree to be bound by these Terms. If you disagree with any part of the terms then you may not access or use the Service. Message Frequency IF AN ORDER IS PLACED LATE AT NIGHT, YOUR BILLBOARD MIGHT NOT START UNTIL THE NEXT MORNING. YOU WILL STILL GET 24 HOURS OF PLAY. Your billboard message/ad will be displayed (pop-up) roughly every one to five minutes, all day long on the dates you select (or 24 hours); depending on how many other Borges Media.com customers are posting messages. Your billboard message/ad will only be displayed on the billboard you select per order. Your billboard message/ad may be resized to fit the specific location. What You Can Post Borges Media does not own billboards, we rent space on billboards, therefore, the types of messages we can put up are limited. Borges Media is for posting birthday messages, anniversary messages, congratulations graduate messages, lost pets, and memorials. Anything out of this scope will be rejected and a refund will NOT be given. NO POLITICAL MESSAGES OF ANY KIND. NO PRACTICAL JOKE MESSAGES. NO BUSINESS ADS (Must get prior consent). NO NEGATIVE OR SLANDEROUS MESSAGES. Any order of the above nature will be rejected and NO REFUND will be given. We reserve the right to deny any message/ad for any reason we deem necessary. If your message/ad is denied you may or may not be issued a refund, solely based on Borges Media's discretion. This is based on the birthday/anniversary/other messages our site was built for. Borges Media.com may use your ads in promotional materials/advertisements. Changes We reserve the right, at our sole discretion, to modify or replace these Terms at any time. If a revision is material we will try to provide at least 30 days notice prior to any new terms taking effect. What constitutes a material change will be determined at our sole discretion. By continuing to access or use our Service after those revisions become effective, you agree to be bound by the revised terms. If you do not agree to the new terms, please stop using the Service. Liability By using borgesmedia.com you agree and understand that borgesmedia.com cannot and will not be held liable for any legal matters whatsoever caused by the ads you create or messages you post/send/share with the borgesmedia.com software program. You agree that you are using this software at your own risk and liability. Borges media is not liable for any accidents/injuries/losses that may incur if you decide to take pictures of billboard messages. Do not take pictures or videos while driving. Do not park/stop on roadways or get out of your vehicle to see or photograph billboards. These terms and conditions are made upon the express condition that Borges Media.com, its agents and employees shall be free from all liabilities and claims for damages and/or suits for or by any reason. You agree to save and hold harmless Borges Media, its agents and employees from all liabilities, charges, expenses and costs on account of or by reason of any such liabilities, claims, suits or losses however occurring or damages growing out of the same. Images Available on Borges Media.com The free photos available in Borges Media.com are all licensed from websites which license their works under the Creative Commons Zero ("CC0"). And to the best of our knowledge, all of these photos are licensed under CC0. You may not use the photos in a derogatory way which would portray the author negatively. You may not use Borges Media.com to create ads using these photos for any slanderous, malicious, criminal, or otherwise negative intent to anyone or any business. By using Borges Media.com you agree to accept responsibility for any copyright or legal issues arising from ads you create and or distribute including but not limited to the photos. Any photos uploaded by yourself or your team that are under copyright and or not your own property are used at your own risk. You may not use copyrighted images/graphics/content without the owner's permission. If you use copyrighted material of any format with our service, knowing or not knowing, you are solely responsible for any legal issues that may arise. Any premium/paid photos through third party sites that we have integrated into Borges Media.com are to be used at your own risk. You may not use their photos or graphics to create ads for any slanderous, malicious, criminal, or otherwise negative intent to anyone or any business. By using any third party site's content/photos/graphics/media you agree to accept responsibility for any copyright or legal issues arising from ads you create and or distribute. Any slogan, tagline, headline, verbiage or wording that you input into our software, that may be copyrighted by another party is done so at your own risk. Borges Media.com will not be responsible in any way shape or form if a lawsuit or legal issue is caused by any words you type, paste, or input into our software. Refunds Borges Media.com does not guarantee refunds. If you order a billboard message for anything outside the scope of what is mentioned above (What You Can Post), you will NOT get a refund. If you feel you need a refund you must contact us with proof showing a refund is needed. Close I Accept These Terms ✂️ Resize & Crop Image Drag the corners to resize and position your image × Cancel Done // Font size inputs are now simple number inputs - no population needed! // Add event listeners for shadow width sliders to update value displays document.addEventListener('DOMContentLoaded', function() { // Editor modal shadow width slider const editorShadowSlider = document.getElementById('editorModalShadowWidth'); const editorShadowValue = document.getElementById('editorShadowWidthValue'); if (editorShadowSlider && editorShadowValue) { editorShadowSlider.addEventListener('input', function() { editorShadowValue.textContent = this.value; }); } // Regular modal shadow width slider const regularShadowSlider = document.getElementById('modalShadowWidth'); const regularShadowValue = document.getElementById('shadowWidthValue'); if (regularShadowSlider && regularShadowValue) { regularShadowSlider.addEventListener('input', function() { regularShadowValue.textContent = this.value; }); } }); // Professional button status updater function updateCheckoutButtonStatus() { const button = document.getElementById('checkoutButton'); const statusSpan = document.getElementById('buttonStatus'); if (!button || !statusSpan) return; const requiredData = { purpose: localStorage.getItem('selectedPurpose'), location: localStorage.getItem('billboardLocation'), dates: localStorage.getItem('runDates') }; const missingFields = []; Object.keys(requiredData).forEach(field => { const value = requiredData[field]; if (!value || value === 'Select a Purpose' || value === 'Not selected' || value.trim() === '') { missingFields.push(field); } }); if (missingFields.length === 0) { statusSpan.textContent = '✅ Ready for checkout'; statusSpan.style.color = '#28a745'; button.style.backgroundColor = '#28a745'; button.style.opacity = '1'; } else { statusSpan.textContent = `⚠️ Missing: ${missingFields.join(', ')}`; statusSpan.style.color = '#ffc107'; button.style.backgroundColor = '#6c757d'; button.style.opacity = '0.7'; } } // Update button status periodically setInterval(updateCheckoutButtonStatus, 2000); // Update immediately on page load setTimeout(updateCheckoutButtonStatus, 1000); // Professional auto-save functionality function setupAutoSave() { // Auto-save when text fields change ['line1', 'line2', 'line3', 'line4'].forEach(lineId => { const element = document.getElementById(lineId); if (element) { element.addEventListener('input', function() { console.log(`Auto-save triggered for ${lineId}`); setTimeout(() => { if (window.saveBillboardData && typeof window.saveBillboardData === 'function') { window.saveBillboardData(); } else { console.warn('saveBillboardData function not available'); } }, 500); // Debounced save }); } }); // Auto-save when editor text fields change ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4'].forEach(lineId => { const element = document.getElementById(lineId); if (element) { element.addEventListener('input', function() { console.log(`Auto-save triggered for ${lineId}`); setTimeout(() => { if (window.saveBillboardData && typeof window.saveBillboardData === 'function') { window.saveBillboardData(); } else { console.warn('saveBillboardData function not available'); } }, 500); // Debounced save }); } }); console.log('Auto-save functionality initialized'); } // Initialize auto-save after page loads setTimeout(setupAutoSave, 2000); // Load Google Fonts const link = document.createElement('link'); link.href = 'https://fonts.googleapis.com/css2?family=Mouse+Memoirs&family=Domine:wght@400;700&family=Baloo+Tamma+2:wght@400;700&family=Courgette&family=Oswald:wght@300;400;700&family=Kaushan+Script&family=Alfa+Slab+One&family=Montserrat:wght@400;700;900&family=Yellowtail&family=Paytone+One&family=Indie+Flower&family=Dancing+Script:wght@400;700&family=Anton&family=Luckiest+Guy&family=Permanent+Marker&family=Sniglet:wght@400;800&family=Lobster&display=swap'; link.rel = 'stylesheet'; document.head.appendChild(link); document.addEventListener('DOMContentLoaded', function() { // Global variables let currentPurpose = null; let currentTemplate = 'anniversary1'; let currentFont = 'Arial'; let currentBgColor = '#ff6b6b'; let currentBgGraphic = 'none'; let uploadedImage = null; // Canvas and context (removed billboard canvas, keeping editor canvas) let canvas = null; let ctx = null; // Text settings for each line const textSettings = { line1: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 }, line2: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 }, line3: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 }, line4: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 } }; // Anniversary Template definitions const anniversaryTemplates = { 'anniversary-template-1': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-1.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 200, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 1px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 1px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 1px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 1px rgba(0,0,0,0.8)' } ], imagePosition: { x: 400, y: 0, width: 400, height: 400 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['HAPPY', 'ANNIVERSARY', 'John & Jane Smith', 'Love: Family'] }, 'anniversary-template-2': { type: 'placeholder-space', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-2.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 200, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } ], imagePosition: { x: 400, y: 0, width: 400, height: 400 }, //placeholderText: 'Upload Your Photo' defaultTexts: ['HAPPY', 'ANNIVERSARY', 'John & Jane Smith', 'Love: Family'] }, 'anniversary-template-3': { type: 'centered-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-3.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 200, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } ], imagePosition: { x: 500, y: 100, width: 200, height: 200 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['HAPPY', 'ANNIVERSARY', 'John & Jane Smith', 'Love: Family'] } }; // Benefit Template definitions const benefitTemplates = { 'benefit-template-1': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-3.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } ], imagePosition: { x: 500, y: 55, width: 300, height: 300 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['BENEFIT FOR', 'John & Jane Smith', 'for Medical Bills', 'Jan. 12, 5 PM at the City Park'] }, 'benefit-template-2': { type: 'text-only', defaultBackground: '#000000', // Default black background (user can change) textPositions: [ { x: 400, y: 110, align: 'center' }, // BENEFIT FOR - top center { x: 400, y: 180, align: 'center' }, // John & Jane Smith - center { x: 400, y: 260, align: 'center' }, // for Medical Bills - center { x: 400, y: 335, align: 'center' } // Date/location - bottom center ], textStyles: [ { color: '#ff0000', fontSize: '72px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '4px' }, { color: '#ffffff', fontSize: '48px', fontFamily: 'Dancing Script', fontStyle: 'italic' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: '700' }, { color: '#ff0000', fontSize: '36px', fontFamily: 'Arial', fontWeight: '700' } ], imagePosition: null, // No image for this template defaultImage: null, defaultTexts: ['BENEFIT FOR', 'John & Jane Smith', 'for Medical Bills', 'Jan. 12, 5 PM at the City Park'] }, 'benefit-template-3': { type: 'centered-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-5.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } ], imagePosition: { x: 500, y: 100, width: 200, height: 200 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['BENEFIT FOR', 'John & Jane Smith', 'for Medical Bills', 'Jan. 12, 5 PM at the City Park'] } }; // Christian Template definitions const christianTemplates = { 'christian-template-1': { type: 'text-only', defaultBackground: '#000000', // Default black background (user can change) textPositions: [ { x: 400, y: 100, align: 'center' }, // Scripture line 1 - top center { x: 400, y: 160, align: 'center' }, // Scripture line 2 - center { x: 400, y: 220, align: 'center' }, // Scripture line 3 - center { x: 400, y: 300, align: 'center' } // Bible reference - bottom center ], textStyles: [ { color: '#FFD700', fontSize: '45px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '2px' }, { color: '#FFD700', fontSize: '45px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '2px' }, { color: '#FFD700', fontSize: '45px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '2px' }, { color: '#ffffff', fontSize: '36px', fontFamily: 'Dancing Script', fontStyle: 'italic' } ], imagePosition: null, // No image for this template defaultImage: null, defaultTexts: ['For the Spirit God gave us does', 'not make us timid, but gives us', 'power, love and self-discipline.', '2 Timothy 1:7'] }, 'christian-template-2': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-15.png', // Cross background textPositions: [ { x: 400, y: 100, align: 'center' }, // Scripture line 1 - top center { x: 400, y: 160, align: 'center' }, // Scripture line 2 - center { x: 400, y: 220, align: 'center' }, // Scripture line 3 - center { x: 400, y: 300, align: 'center' } // Bible reference - bottom center ], textStyles: [ { color: '#ffffff', fontSize: '39px', fontFamily: 'Arial', fontWeight: '900', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Scripture line 1 - white bold with shadow { color: '#ffffff', fontSize: '39px', fontFamily: 'Arial', fontWeight: '900', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Scripture line 2 - white bold with shadow { color: '#ffffff', fontSize: '39px', fontFamily: 'Arial', fontWeight: '900', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Scripture line 3 - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Dancing Script', fontStyle: 'italic', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // Bible reference - white italic with shadow ], imagePosition: null, // No image for this template defaultImage: null, defaultTexts: ['Therefore, if anyone is in Christ,', 'the new creation has come:', 'The old has gone, the new is here!', '2 Corinthians 5:17'] }, 'christian-template-3': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-12.png', // Dark gradient background textPositions: [ { x: 400, y: 100, align: 'center' }, // Scripture line 1 - top center { x: 400, y: 160, align: 'center' }, // Scripture line 2 - center { x: 400, y: 220, align: 'center' }, // Scripture line 3 - center { x: 400, y: 300, align: 'center' } // Bible reference - bottom center ], textStyles: [ { color: '#FFD700', fontSize: '38px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '4px' }, // Scripture line 1 - gold { color: '#FFD700', fontSize: '38px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '4px' }, // Scripture line 2 - gold { color: '#FFD700', fontSize: '38px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '4px' }, // Scripture line 3 - gold { color: '#ffffff', fontSize: '36px', fontFamily: 'Dancing Script', fontStyle: 'italic' } // Bible reference - white italic ], imagePosition: null, // No image for this template defaultImage: null, defaultTexts: ['I can do all things', 'through Christ', 'who strengthens me.', 'Philippians 4:13'] } }; // Graduation Template definitions const graduationTemplates = { 'graduation-template-1': { type: 'text-only', background: 'Graduation-9', textPositions: [ { x: 400, y: 130, align: 'center' }, // Congratulations! - top { x: 400, y: 195, align: 'center' }, // Name - second { x: 400, y: 245, align: 'center' }, // Wishing you success ahead - third { x: 400, y: 295, align: 'center' } // Cheers to new beginnings! - bottom ], textStyles: [ { color: '#ffffff', fontSize: '44px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // Congratulations! - white italic { color: '#FFD700', fontSize: '48px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // Name - red gold { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' }, // Wishing you success ahead - white { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // Cheers to new beginnings! - white ], imagePosition: null, defaultImage: null, defaultTexts: ['Congratulations!', 'John Doe', 'Wishing you success ahead.', 'Cheers to new beginnings!'] }, 'graduation-template-2': { type: 'full-image', background: 'Graduation-14', textPositions: [ { x: 375, y: 120, align: 'left' }, { x: 375, y: 180, align: 'left' }, { x: 375, y: 240, align: 'left' }, { x: 375, y: 300, align: 'left' } ], textStyles: [ { color: '#ffffff', fontSize: '40px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '4px' }, // It's time! - gold bold { color: '#FFD700', fontSize: '40px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '2px' }, // Name - white { color: '#ffffff', fontSize: '35px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '2px' }, // Congratulations! - white { color: '#ffffff', fontSize: '35px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // Make it count! - white ], imagePosition: { x: 50, y: 50, width: 300, height: 300 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['It\'s time!', 'John Doe', 'Congratulations!', 'Make it count!'] }, 'graduation-template-3': { type: 'centered-image', background: 'Graduation-3', textPositions: [ { x: 200, y: 130, align: 'center' }, { x: 200, y: 190, align: 'center' }, { x: 200, y: 250, align: 'center' }, { x: 200, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '3px' }, // HAPPY - white bold { color: '#ffffff', fontSize: '38px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // GRADUATION - white bold { color: '#ffffff', fontSize: '40px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '1px', fontStyle: 'italic' }, // Name - white italic { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '2px' } // School - white ], imagePosition: { x: 450, y: 100, width: 200, height: 200 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['HAPPY', 'GRADUATION', 'John Doe', 'CHS Graduate'] } }; // Local School Template definitions const localSchoolTemplates = { 'local-school-template-1': { type: 'text-only', background: 'Local-Schools-3', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 240, align: 'center' }, { x: 400, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '3px' }, { color: '#ffffff', fontSize: '38px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '2px' }, { color: '#ffffff', fontSize: '38px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '2px' }, { color: '#ffffff', fontSize: '36px', fontFamily: 'Dancing Script', fontWeight: '600', letterSpacing: '1px' } ], defaultTexts: ['Inspire Every Mind', 'Learn with Passion', 'Grow with Purpose', 'Achieve Your Dreams'] }, 'local-school-template-2': { type: 'text-only', background: 'Local-Schools-7', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 240, align: 'center' }, { x: 400, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '3px' }, { color: '#ffffff', fontSize: '38px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '2px' }, { color: '#ffffff', fontSize: '38px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '2px' }, { color: '#ffffff', fontSize: '36px', fontFamily: 'Dancing Script', fontWeight: '600', letterSpacing: '1px' } ], defaultTexts: ['Embrace Knowledge', 'Spark Creativity', 'Build Your Future', 'Shine Brightly'] }, 'local-school-template-3': { type: 'text-only', background: 'Local-Schools-5', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 240, align: 'center' }, { x: 400, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '3px' }, { color: '#ffffff', fontSize: '38px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '2px' }, { color: '#ffffff', fontSize: '38px', fontFamily: 'Arial', fontWeight: '700', letterSpacing: '2px' }, { color: '#ffffff', fontSize: '36px', fontFamily: 'Dancing Script', fontWeight: '600', letterSpacing: '1px' } ], defaultTexts: ['Discover Your Path', 'Grow with Courage', 'Learn Without Limits', 'Lead with Heart'] } }; // Love Template definitions const loveTemplates = { 'love-template-1': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-1.png', defaultBackground: '#ff69b4', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // I LOVE - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // YOU - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Jane Doe - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // John Doe - white bold with shadow ], imagePosition: { x: 500, y: 55, width: 300, height: 300 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['I LOVE', 'YOU', 'Jane Doe', 'John Doe'] }, 'love-template-2': { type: 'centered-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-2.png', defaultBackground: '#ff1493', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // I LOVE - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // YOU - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Jane Doe - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // John Doe - white bold with shadow ], imagePosition: { x: 500, y: 100, width: 200, height: 200 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['I LOVE', 'YOU', 'Jane Doe', 'John Doe'] }, 'love-template-3': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-3.png', defaultBackground: '#dc143c', textPositions: [ { x: 400, y: 130, align: 'center' }, // I LOVE - top { x: 400, y: 195, align: 'center' }, // YOU - second { x: 400, y: 245, align: 'center' }, // Jane Doe - third { x: 400, y: 295, align: 'center' } // John Doe - bottom ], textStyles: [ { color: '#ffffff', fontSize: '44px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // I LOVE - white italic { color: '#FFD700', fontSize: '48px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // YOU - gold { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' }, // Jane Doe - white { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // John Doe - white ], imagePosition: null, defaultImage: null, defaultTexts: ['I LOVE', 'YOU', 'Jane Doe', 'John Doe'] } }; // Marry Me Template definitions const marryMeTemplates = { 'marry-me-template-1': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-5.png', defaultBackground: '#ff69b4', textPositions: [ { x: 200, y: 120, align: 'center' }, // Copying Benefit template 1 positions { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Jane Doe - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Will You - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Marry ME? - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // -John Doe - white bold with shadow ], imagePosition: { x: 500, y: 55, width: 300, height: 300 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['Jane Doe', 'Will You', 'Marry ME?', '-John Doe'] }, 'marry-me-template-2': { type: 'centered-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-11.png', defaultBackground: '#ff1493', textPositions: [ { x: 200, y: 120, align: 'center' }, // Copying Benefit template 3 positions { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Jane Doe - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Will You - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Marry ME? - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // -John Doe - white bold with shadow ], imagePosition: { x: 500, y: 100, width: 200, height: 200 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['Jane Doe', 'Will You', 'Marry ME?', '-John Doe'] }, 'marry-me-template-3': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-1.png', defaultBackground: '#dc143c', textPositions: [ { x: 400, y: 130, align: 'center' }, // Copying Graduation template 1 positions { x: 400, y: 195, align: 'center' }, { x: 400, y: 245, align: 'center' }, { x: 400, y: 295, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '44px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // Jane Doe - white italic { color: '#FFD700', fontSize: '48px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // Will You - gold { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' }, // Marry ME? - white { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // -John Doe - white ], imagePosition: null, defaultImage: null, defaultTexts: ['Jane Doe', 'Will You', 'Marry ME?', '-John Doe'] } }; // Newborn Template definitions const newbornTemplates = { 'newborn-template-1': { type: 'centered-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-1.png', defaultBackground: '#87CEEB', textPositions: [ { x: 200, y: 120, align: 'center' }, // Copying Benefit template 3 positions { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Baby - white bold with shadow { color: '#FFD700', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // John Doe - gold bold with shadow { color: '#ffffff', fontSize: '24px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // 9 lbs. 4 oz. - white bold with shadow { color: '#ffffff', fontSize: '20px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // Parents: John & Jane Doe - white bold with shadow ], imagePosition: { x: 500, y: 100, width: 200, height: 200 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['Baby', 'John Doe', '9 lbs. 4 oz.', 'Parents: John & Jane Doe'] }, 'newborn-template-2': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-12.png', defaultBackground: '#FFB6C1', textPositions: [ { x: 200, y: 120, align: 'center' }, // Copying Benefit template 1 positions { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Baby - white bold with shadow { color: '#FFD700', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // John Doe - gold bold with shadow { color: '#ffffff', fontSize: '24px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // 9 lbs. 4 oz. - white bold with shadow { color: '#ffffff', fontSize: '20px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // Parents: John & Jane Doe - white bold with shadow ], imagePosition: { x: 500, y: 55, width: 300, height: 300 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['Baby', 'John Doe', '9 lbs. 4 oz.', 'Parents: John & Jane Doe'] }, 'newborn-template-3': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-7.png', defaultBackground: '#98FB98', textPositions: [ { x: 400, y: 130, align: 'center' }, // Copying Graduation template 1 positions { x: 400, y: 195, align: 'center' }, { x: 400, y: 245, align: 'center' }, { x: 400, y: 295, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // Welcome to the world - white italic { color: '#FFD700', fontSize: '36px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // Jane Doe - gold { color: '#ffffff', fontSize: '24px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' }, // 10 lbs. 5 oz. 20 " Long - white { color: '#ffffff', fontSize: '22px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // Love Mom & Dad - white ], imagePosition: null, defaultImage: null, defaultTexts: ['Welcome to the world', 'Jane Doe', '10 lbs. 5 oz. 20 " Long', 'Love Mom & Dad'] } }; // Other Template definitions const otherTemplates = { 'other-template-1': { type: 'centered-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-2.png', defaultBackground: '#2F2F2F', textPositions: [ { x: 200, y: 120, align: 'center' }, // Copying Benefit template 3 positions { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // YOUR TEXT - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Text Here - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Text Here - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // Text Here - white bold with shadow ], imagePosition: { x: 500, y: 100, width: 200, height: 200 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['YOUR TEXT', 'Text Here', 'Text Here', 'Text Here'] }, 'other-template-2': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-5.png', defaultBackground: '#1C1C1C', textPositions: [ { x: 200, y: 120, align: 'center' }, // Copying Benefit template 1 positions { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // YOUR TEXT - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Text Here - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Text Here - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // Text Here - white bold with shadow ], imagePosition: { x: 400, y: 0, width: 400, height: 400 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['YOUR TEXT', 'Text Here', 'Text Here', 'Text Here'] }, 'other-template-3': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-1.png', defaultBackground: '#000000', textPositions: [ { x: 400, y: 130, align: 'center' }, // Copying Graduation template 1 positions { x: 400, y: 195, align: 'center' }, { x: 400, y: 245, align: 'center' }, { x: 400, y: 295, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '44px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // YOUR TEXT - white italic { color: '#FFD700', fontSize: '48px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // Your Text Goes Here - gold { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' }, // Your Text Here - white { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // Your Text Goes Here - white ], imagePosition: null, defaultImage: null, defaultTexts: ['YOUR TEXT', 'Your Text Goes Here', 'Your Text Here', 'Your Text Goes Here'] } }; // Pet Template definitions const petTemplates = { 'pet-template-1': { type: 'centered-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-11.png', defaultBackground: '#2F2F2F', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // LOST DOG - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // LAST SEEN ON MAIN ST. - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Terra - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // 555-555-55555 - white bold with shadow ], imagePosition: { x: 500, y: 100, width: 200, height: 200 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/default-dog-image.jpg', defaultTexts: ['LOST DOG', 'LAST SEEN ON MAIN ST.', 'Terra', '555-555-55555'] }, 'pet-template-2': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-4.png', defaultBackground: '#1C1C1C', textPositions: [ { x: 200, y: 120, align: 'center' }, // Copying Benefit template 1 positions { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // LOST DOG - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // LAST SEEN ON MAIN ST. - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Terra - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // 555-555-55555 - white bold with shadow ], imagePosition: { x: 400, y: 0, width: 400, height: 400 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/default-dog-image.jpg', defaultTexts: ['LOST DOG', 'LAST SEEN ON MAIN ST.', 'Terra', '555-555-55555'] }, 'pet-template-3': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-10.png', defaultBackground: '#1C1C1C', textPositions: [ { x: 590, y: 320, align: 'center' }, // Moved right from x: 200 { x: 590, y: 340, align: 'center' }, { x: 590, y: 360, align: 'center' }, { x: 600, y: 380, align: 'center' } // This was x: 210 originally ], textStyles: [ { color: '#ffffff', fontSize: '20px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '20px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '20px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '20px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } ], imagePosition: { x: 500, y: 60, width: 200, height: 200 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/default-dog-image.jpg', defaultTexts: ['LOST DOG', 'LAST SEEN ON MAIN ST.', 'Terra', '555-555-55555'] } }; // Wedding Template definitions const weddingTemplates = { 'wedding-template-1': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-10.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } ], imagePosition: { x: 400, y: 0, width: 400, height: 400 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['Congratulations', 'John & Jane', 'Smith', 'Love Your Parents'] }, 'wedding-template-2': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-1.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } ], imagePosition: { x: 400, y: 0, width: 400, height: 400 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['Congratulations', 'John & Jane', 'Smith', 'Love Your Parents'] }, 'wedding-template-3': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-3.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 240, align: 'center' }, { x: 400, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#FFD700', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '42px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } ], defaultTexts: ['Congratulations', 'John & Jane', 'Smith', 'Love Your Parents'] } }; // Welcome Template definitions const welcomeTemplates = { 'welcome-template-1': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-10.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } ], imagePosition: { x: 500, y: 55, width: 300, height: 300 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['WELCOME', 'HOME', 'JOHN DOE', 'Love: Your Family'] }, 'welcome-template-2': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-15.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } ], imagePosition: { x: 400, y: 0, width: 400, height: 400 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['WELCOME', 'HOME', 'JOHN DOE', 'Love: Your Family'] }, 'welcome-template-3': { type: 'text-only', background: 'Welcome-11', textPositions: [ { x: 400, y: 130, align: 'center' }, // WELCOME - top { x: 400, y: 195, align: 'center' }, // HOME - second { x: 400, y: 245, align: 'center' }, // JOHN DOE - third { x: 400, y: 295, align: 'center' } // Love: Your Family - bottom ], textStyles: [ { color: '#ffffff', fontSize: '44px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // WELCOME - white italic { color: '#FFD700', fontSize: '48px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // HOME - gold { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' }, // JOHN DOE - white { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // Love: Your Family - white ], imagePosition: null, defaultImage: null, defaultTexts: ['WELCOME', 'HOME', 'JOHN DOE', 'Love: Your Family'] } }; // Retirement Template definitions const retirementTemplates = { 'retirement-template-1': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-9.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // HAPPY - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // RETIREMENT - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Name - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // From Your Friends - white bold with shadow ], imagePosition: { x: 400, y: 0, width: 400, height: 400 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['HAPPY', 'RETIREMENT', 'JOHN DOE', 'From Your Friends'] }, 'retirement-template-2': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-10.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // HAPPY - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // RETIREMENT - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Name - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // From Your Friends - white bold with shadow ], imagePosition: { x: 500, y: 55, width: 300, height: 300 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['HAPPY', 'RETIREMENT', 'JOHN DOE', 'From Your Friends'] }, 'retirement-template-3': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-4.png', textPositions: [ { x: 400, y: 130, align: 'center' }, // HAPPY - top { x: 400, y: 195, align: 'center' }, // RETIREMENT - second { x: 400, y: 245, align: 'center' }, // Name - third { x: 400, y: 295, align: 'center' } // From Your Friends - bottom ], textStyles: [ { color: '#ffffff', fontSize: '44px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // HAPPY - white italic { color: '#FFD700', fontSize: '48px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // RETIREMENT - gold { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' }, // Name - white { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // From Your Friends - white ], imagePosition: null, defaultImage: null, defaultTexts: ['HAPPY', 'RETIREMENT', 'JOHN DOE', 'From Your Friends'] } }; // Prayer Template definitions const prayerTemplates = { 'prayer-template-1': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-2.png', defaultBackground: '#2F2F2F', textPositions: [ { x: 250, y: 120, align: 'center' }, // Copying Benefit template 1 positions { x: 250, y: 180, align: 'center' }, { x: 250, y: 240, align: 'center' }, { x: 260, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // YOUR PRAYER MESSAGE - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // GOES RIGHT HERE - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // PRAY FOR OUR COUNTRY - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // PRAY FOR OUR COUNTRY - white bold with shadow ], imagePosition: { x: 500, y: 55, width: 300, height: 300 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['YOUR PRAYER MESSAGE', 'GOES RIGHT HERE', 'PRAY FOR OUR COUNTRY', 'PRAY FOR OUR COUNTRY'] }, 'prayer-template-2': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-9.png', defaultBackground: '#1C1C1C', textPositions: [ { x: 400, y: 105, align: 'center' }, { x: 400, y: 175, align: 'center' }, { x: 400, y: 240, align: 'center' }, { x: 400, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '44px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // YOUR PRAYER MESSAGE - white italic { color: '#FFD700', fontSize: '48px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // GOES RIGHT HERE - gold { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' }, // PRAY FOR OUR COUNTRY - white { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // PRAY FOR OUR COUNTRY - white ], imagePosition: null, defaultImage: null, defaultTexts: ['YOUR PRAYER MESSAGE', 'GOES RIGHT HERE', 'PRAY FOR OUR COUNTRY', 'PRAY FOR OUR COUNTRY'] }, 'prayer-template-3': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-10.png', defaultBackground: '#1C1C1C', textPositions: [ { x: 400, y: 105, align: 'center' }, { x: 400, y: 175, align: 'center' }, { x: 400, y: 240, align: 'center' }, { x: 400, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '44px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // YOUR PRAYER MESSAGE - white italic { color: '#FFD700', fontSize: '48px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // GOES RIGHT HERE - gold { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' }, // PRAY FOR OUR COUNTRY - white { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // PRAY FOR OUR COUNTRY - white ], imagePosition: null, defaultImage: null, defaultTexts: ['YOUR PRAYER MESSAGE', 'GOES RIGHT HERE', 'PRAY FOR OUR COUNTRY', 'PRAY FOR OUR COUNTRY'] } }; // Obituary Template definitions const obituaryTemplates = { 'obituary-template-1': { type: 'centered-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-11.png', defaultBackground: '#2F2F2F', textPositions: [ { x: 200, y: 120, align: 'center' }, // Copying Benefit template 3 positions { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // In Loving - white bold with shadow { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Memory of - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // John Doe - gold bold with shadow { color: '#ffffff', fontSize: '24px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // 1950 - 2021 - white bold with shadow ], imagePosition: { x: 500, y: 100, width: 200, height: 200 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['In Loving', 'Memory of', 'John Doe', '1950 - 2021'] }, 'obituary-template-2': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-8.png', defaultBackground: '#1C1C1C', textPositions: [ { x: 200, y: 120, align: 'center' }, // Copying Benefit template 1 positions { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // In Loving - white bold with shadow { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Memory of - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // John Doe - gold bold with shadow { color: '#ffffff', fontSize: '24px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // 1950 - 2021 - white bold with shadow ], imagePosition: { x: 400, y: 0, width: 400, height: 400 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['In Loving', 'Memory of', 'John Doe', '1950 - 2021'] }, 'obituary-template-3': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-2.png', defaultBackground: '#4A4A4A', textPositions: [ { x: 400, y: 130, align: 'center' }, // Copying Graduation template 1 positions { x: 400, y: 195, align: 'center' }, { x: 400, y: 245, align: 'center' }, { x: 400, y: 295, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // In Loving - white italic { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px', fontStyle: 'italic' }, // Memory of - white italic { color: '#ffffff', fontSize: '36px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '2px' }, // John Doe - gold { color: '#ffffff', fontSize: '28px', fontFamily: 'Arial', fontWeight: '600', letterSpacing: '1px' } // 1950 - 2021 - white ], imagePosition: null, defaultImage: null, defaultTexts: ['In Loving', 'Memory of', 'John Doe', '1950 - 2021'] } }; // Preload default images for instant display const preloadedImages = {}; function preloadDefaultImage(url) { if (!preloadedImages[url]) { const img = new Image(); img.crossOrigin = 'anonymous'; img.src = url; preloadedImages[url] = img; } return preloadedImages[url]; } // Preload common default images preloadDefaultImage('https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg'); // Holiday Template definitions const holidayTemplates = { 'holiday-template-1': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-1.png', textPositions: [ { x: 400, y: 100, align: 'center' }, // Warmest Wishes - top center { x: 400, y: 160, align: 'center' }, // for a Joyful - center { x: 400, y: 220, align: 'center' }, // Holiday Season - center { x: 400, y: 300, align: 'center' } // from Us All! - bottom center ], textStyles: [ { color: '#ffffff', fontSize: '39px', fontFamily: 'Arial', fontWeight: '900', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Warmest Wishes - white bold with shadow { color: '#ffffff', fontSize: '39px', fontFamily: 'Arial', fontWeight: '900', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // for a Joyful - white bold with shadow { color: '#ffffff', fontSize: '39px', fontFamily: 'Arial', fontWeight: '900', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Holiday Season - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Dancing Script', fontStyle: 'italic', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // from Us All! - white italic with shadow ], imagePosition: null, // No image for this template defaultImage: null, defaultTexts: ['Warmest Wishes', 'for a Joyful', 'Holiday Season', 'from Us All!'] }, 'holiday-template-2': { type: 'full-image', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-8.png', textPositions: [ { x: 200, y: 120, align: 'center' }, { x: 200, y: 180, align: 'center' }, { x: 200, y: 240, align: 'center' }, { x: 210, y: 300, align: 'center' } ], textStyles: [ { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Merry Christmas - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Filled with Love - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // and Cheerful Moments - white bold with shadow { color: '#ffffff', fontSize: '25px', fontFamily: 'Arial', fontWeight: 'bold', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // from Our Family! - white bold with shadow ], imagePosition: { x: 460, y: 55, width: 300, height: 300 }, defaultImage: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg', defaultTexts: ['Merry Christmas', 'Filled with Love', 'and Cheerful Moments', 'from Our Family!'] }, 'holiday-template-3': { type: 'text-only', background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-4.png', textPositions: [ { x: 400, y: 100, align: 'center' }, // Happy New Year - top center { x: 400, y: 160, align: 'center' }, // Wishing You Joy - center { x: 400, y: 220, align: 'center' }, // and New Beginnings - center { x: 400, y: 300, align: 'center' } // from Us All! - bottom center ], textStyles: [ { color: '#ffffff', fontSize: '39px', fontFamily: 'Arial', fontWeight: '900', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Happy New Year - white bold with shadow { color: '#ffffff', fontSize: '39px', fontFamily: 'Arial', fontWeight: '900', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // Wishing You Joy - white bold with shadow { color: '#ffffff', fontSize: '39px', fontFamily: 'Arial', fontWeight: '900', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' }, // and New Beginnings - white bold with shadow { color: '#ffffff', fontSize: '32px', fontFamily: 'Dancing Script', fontStyle: 'italic', textShadow: '1px 1px 2px rgba(0,0,0,0.8)' } // from Us All! - white italic with shadow ], imagePosition: null, // No image for this template defaultImage: null, defaultTexts: ['Happy New Year', 'Wishing You Joy', 'and New Beginnings', 'from Us All!'] } }; // Template definitions (keeping existing for compatibility) const templates = { template1: { background: 'linear-gradient(45deg, #ff6b6b, #feca57)', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, template2: { background: 'linear-gradient(45deg, #48dbfb, #0abde3)', textPositions: [ { x: 400, y: 100, align: 'center' }, { x: 400, y: 160, align: 'center' }, { x: 400, y: 240, align: 'center' }, { x: 400, y: 300, align: 'center' } ] }, template3: { background: 'linear-gradient(45deg, #ff9ff3, #f368e0)', textPositions: [ { x: 400, y: 110, align: 'center' }, { x: 400, y: 170, align: 'center' }, { x: 400, y: 250, align: 'center' }, { x: 400, y: 310, align: 'center' } ] }, // Anniversary templates anniversary1: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-1.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary2: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-2.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary3: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-3.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary4: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-6.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary5: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-8.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary6: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-9.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary7: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-11.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary8: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-12.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary9: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-13.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary10: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-14.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary11: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-15.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary12: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-4.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary13: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-5.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary14: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-10.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, anniversary15: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-7.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, // Benefit templates benefit1: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-1.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit2: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-2.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit3: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-3.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit4: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-4.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit5: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-5.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit6: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-6.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit7: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-7.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit8: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-8.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit9: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-9.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit10: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-10.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit11: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-11.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit12: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-12.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit13: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-13.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit14: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-14.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, benefit15: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-15.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, // Christian templates christian1: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-1.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian2: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-2.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian3: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-3.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian4: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-4.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian5: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-5.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian6: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-6.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian7: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-7.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian8: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-8.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian9: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-9.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian10: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-10.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian11: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-11.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian12: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-12.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian13: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-13.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian14: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-14.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, christian15: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-15.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, // Graduation templates graduation1: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-1.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation2: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-2.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation3: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-3.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation4: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-4.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation5: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-5.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation6: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-6.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation7: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-7.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation8: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-8.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation9: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-9.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation10: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-10.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation11: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-11.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation12: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-12.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation13: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-13.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation14: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-14.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, graduation15: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-15.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, // Holiday templates holiday1: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-1.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday2: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-2.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday3: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-3.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday4: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-4.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday5: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-5.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday6: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-6.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday7: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-7.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday8: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-8.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday9: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-9.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday10: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-10.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday11: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-11.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday12: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-12.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday13: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-13.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday14: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-14.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, holiday15: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-15.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, // Local School templates localschool1: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-1.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, localschool2: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-2.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, localschool3: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-3.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, localschool4: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-4.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, localschool5: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-5.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, localschool6: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-6.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, localschool7: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-7.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, localschool8: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-8.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, localschool9: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-9.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, localschool10: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-10.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, // Love templates love1: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-1.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love2: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-2.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love3: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-3.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love4: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-4.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love5: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-5.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love6: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-6.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love7: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-7.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love8: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-8.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love9: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-9.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love10: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-10.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love11: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-11.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love12: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-12.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love13: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-13.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love14: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-14.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }, love15: { background: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-15.png', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] } }; // Debug function to check elements function debugElements() { const elements = [ 'billboardCanvas', 'line1', 'line2', 'line3', 'line4', 'colorBtn1', 'colorBtn2', 'colorBtn3', 'colorBtn4', 'settingsBtn1', 'settingsBtn2', 'settingsBtn3', 'settingsBtn4', 'fontModal', 'modalFontSelect', 'modalFontSize' ]; elements.forEach(id => { const element = document.getElementById(id); if (!element) { console.warn(`Element not found: ${id}`); } else { console.log(`Element found: ${id}`); } }); } // Initialize function init() { console.log('Initializing billboard editor...'); debugElements(); initializePurpose(); setupEventListeners(); // Note: Billboard canvas removed, using anniversary templates instead } // Check for purpose from URL parameters or localStorage function initializePurpose() { const urlParams = new URLSearchParams(window.location.search); const purposeFromUrl = urlParams.get('purpose'); const purposeFromStorage = localStorage.getItem('selectedPurpose'); if (purposeFromUrl) { currentPurpose = purposeFromUrl; localStorage.setItem('selectedPurpose', purposeFromUrl); } else if (purposeFromStorage) { currentPurpose = purposeFromStorage; } if (currentPurpose) { displayPurpose(currentPurpose); updatePurposeField(currentPurpose); } else { // No purpose selected, show default state showDefaultTemplateState(); } } // Show default template state when no purpose is selected function showDefaultTemplateState() { const templateSelectionSection = document.getElementById('templateSelectionSection'); const anniversaryTemplatesSection = document.getElementById('anniversaryTemplatesSection'); const noTemplatesMessage = document.getElementById('noTemplatesMessage'); const purposeDisplay = document.getElementById('purposeDisplay'); // Hide purpose display if (purposeDisplay) { purposeDisplay.style.display = 'none'; } // Show template selection section with no templates message templateSelectionSection.style.display = 'block'; anniversaryTemplatesSection.style.display = 'none'; // Show no templates message if (noTemplatesMessage) { noTemplatesMessage.style.display = 'block'; } } // Display the selected purpose function displayPurpose(purpose) { const purposeDisplay = document.getElementById('purposeDisplay'); const selectedPurposeText = document.getElementById('selectedPurposeText'); selectedPurposeText.textContent = purpose; purposeDisplay.style.display = 'block'; // Update template section title const templateSectionTitle = document.getElementById('templateSectionTitle'); if (templateSectionTitle) { templateSectionTitle.textContent = `Select Your ${purpose} Template`; } // Show appropriate template section based on purpose showTemplatesForPurpose(purpose); } // Show templates based on purpose - Enhanced for Universal Template System function showTemplatesForPurpose(purpose) { const templateSelectionSection = document.getElementById('templateSelectionSection'); const anniversaryTemplatesSection = document.getElementById('anniversaryTemplatesSection'); const universalTemplatesSection = document.getElementById('universalTemplatesSection'); const noTemplatesMessage = document.getElementById('noTemplatesMessage'); const editorContainer = document.getElementById('templateEditorContainer'); // Hide editor if it's currently showing if (editorContainer && editorContainer.classList.contains('active')) { editorContainer.classList.remove('active'); isEditorMode = false; } // Reset any selected templates document.querySelectorAll('.anniversary-template-card, .benefit-template-card, .christian-template-card, .graduation-template-card, .holiday-template-card, .local-school-template-card, .love-template-card, .marry-me-template-card, .newborn-template-card, .obituary-template-card, .other-template-card, .pet-template-card, .prayer-template-card, .retirement-template-card, .wedding-template-card, .universal-template-card').forEach(card => { card.classList.remove('selected'); }); // Hide all template sections first templateSelectionSection.style.display = 'none'; anniversaryTemplatesSection.style.display = 'none'; const benefitTemplatesSection = document.getElementById('benefitTemplatesSection'); if (benefitTemplatesSection) { benefitTemplatesSection.style.display = 'none'; } const christianTemplatesSection = document.getElementById('christianTemplatesSection'); if (christianTemplatesSection) { christianTemplatesSection.style.display = 'none'; } const graduationTemplatesSection = document.getElementById('graduationTemplatesSection'); if (graduationTemplatesSection) { graduationTemplatesSection.style.display = 'none'; } const holidayTemplatesSection = document.getElementById('holidayTemplatesSection'); if (holidayTemplatesSection) { holidayTemplatesSection.style.display = 'none'; } const localSchoolTemplatesSection = document.getElementById('localSchoolTemplatesSection'); if (localSchoolTemplatesSection) { localSchoolTemplatesSection.style.display = 'none'; } const loveTemplatesSection = document.getElementById('loveTemplatesSection'); if (loveTemplatesSection) { loveTemplatesSection.style.display = 'none'; } const marryMeTemplatesSection = document.getElementById('marryMeTemplatesSection'); if (marryMeTemplatesSection) { marryMeTemplatesSection.style.display = 'none'; } const newbornTemplatesSection = document.getElementById('newbornTemplatesSection'); if (newbornTemplatesSection) { newbornTemplatesSection.style.display = 'none'; } const obituaryTemplatesSection = document.getElementById('obituaryTemplatesSection'); if (obituaryTemplatesSection) { obituaryTemplatesSection.style.display = 'none'; } const otherTemplatesSection = document.getElementById('otherTemplatesSection'); if (otherTemplatesSection) { otherTemplatesSection.style.display = 'none'; } const petTemplatesSection = document.getElementById('petTemplatesSection'); if (petTemplatesSection) { petTemplatesSection.style.display = 'none'; } const prayerTemplatesSection = document.getElementById('prayerTemplatesSection'); if (prayerTemplatesSection) { prayerTemplatesSection.style.display = 'none'; } const retirementTemplatesSection = document.getElementById('retirementTemplatesSection'); if (retirementTemplatesSection) { retirementTemplatesSection.style.display = 'none'; } const weddingTemplatesSection = document.getElementById('weddingTemplatesSection'); if (weddingTemplatesSection) { weddingTemplatesSection.style.display = 'none'; } const welcomeTemplatesSection = document.getElementById('welcomeTemplatesSection'); if (welcomeTemplatesSection) { welcomeTemplatesSection.style.display = 'none'; } if (universalTemplatesSection) { universalTemplatesSection.style.display = 'none'; } if (purpose === 'Anniversary') { // Show anniversary interactive templates anniversaryTemplatesSection.style.display = 'block'; // Update the anniversary section title const anniversaryTitle = anniversaryTemplatesSection.querySelector('.design-section-title'); if (anniversaryTitle) { anniversaryTitle.textContent = 'Choose Your Anniversary Template'; } } else if (purpose === 'Benefit') { // Show benefit interactive templates if (benefitTemplatesSection) { benefitTemplatesSection.style.display = 'block'; // Update the benefit section title const benefitTitle = benefitTemplatesSection.querySelector('.design-section-title'); if (benefitTitle) { benefitTitle.textContent = 'Choose Your Benefit Template'; } } } else if (purpose === 'Christian') { // Show christian interactive templates if (christianTemplatesSection) { christianTemplatesSection.style.display = 'block'; // Update the christian section title const christianTitle = christianTemplatesSection.querySelector('.design-section-title'); if (christianTitle) { christianTitle.textContent = 'Choose Your Christian Template'; } } } else if (purpose === 'Graduation') { // Show graduation interactive templates if (graduationTemplatesSection) { graduationTemplatesSection.style.display = 'block'; // Update the graduation section title const graduationTitle = graduationTemplatesSection.querySelector('.design-section-title'); if (graduationTitle) { graduationTitle.textContent = 'Choose Your Graduation Template'; } } } else if (purpose === 'Holiday') { // Show holiday interactive templates if (holidayTemplatesSection) { holidayTemplatesSection.style.display = 'block'; // Update the holiday section title const holidayTitle = holidayTemplatesSection.querySelector('.design-section-title'); if (holidayTitle) { holidayTitle.textContent = 'Choose Your Holiday Template'; } } } else if (purpose === 'Local School') { // Show local school interactive templates if (localSchoolTemplatesSection) { localSchoolTemplatesSection.style.display = 'block'; // Update the local school section title const localSchoolTitle = localSchoolTemplatesSection.querySelector('.design-section-title'); if (localSchoolTitle) { localSchoolTitle.textContent = 'Choose Your Local School Template'; } } } else if (purpose === 'Love') { // Show love interactive templates if (loveTemplatesSection) { loveTemplatesSection.style.display = 'block'; // Update the love section title const loveTitle = loveTemplatesSection.querySelector('.design-section-title'); if (loveTitle) { loveTitle.textContent = 'Choose Your Love Template'; } } } else if (purpose === 'Marry Me') { // Show marry me interactive templates const marryMeTemplatesSection = document.getElementById('marryMeTemplatesSection'); if (marryMeTemplatesSection) { marryMeTemplatesSection.style.display = 'block'; // Update the marry me section title const marryMeTitle = marryMeTemplatesSection.querySelector('.design-section-title'); if (marryMeTitle) { marryMeTitle.textContent = 'Choose Your Marry Me Template'; } } } else if (purpose === 'New Born') { // Show newborn interactive templates const newbornTemplatesSection = document.getElementById('newbornTemplatesSection'); if (newbornTemplatesSection) { newbornTemplatesSection.style.display = 'block'; // Update the newborn section title const newbornTitle = newbornTemplatesSection.querySelector('.design-section-title'); if (newbornTitle) { newbornTitle.textContent = 'Choose Your Newborn Template'; } } } else if (purpose === 'Obituary') { // Show obituary interactive templates const obituaryTemplatesSection = document.getElementById('obituaryTemplatesSection'); if (obituaryTemplatesSection) { obituaryTemplatesSection.style.display = 'block'; // Update the obituary section title const obituaryTitle = obituaryTemplatesSection.querySelector('.design-section-title'); if (obituaryTitle) { obituaryTitle.textContent = 'Choose Your Obituary Template'; } } } else if (purpose === 'Other') { // Show other interactive templates const otherTemplatesSection = document.getElementById('otherTemplatesSection'); if (otherTemplatesSection) { otherTemplatesSection.style.display = 'block'; // Update the other section title const otherTitle = otherTemplatesSection.querySelector('.design-section-title'); if (otherTitle) { otherTitle.textContent = 'Choose Your Other Template'; } } } else if (purpose === 'Pet') { // Show pet interactive templates const petTemplatesSection = document.getElementById('petTemplatesSection'); if (petTemplatesSection) { petTemplatesSection.style.display = 'block'; // Update the pet section title const petTitle = petTemplatesSection.querySelector('.design-section-title'); if (petTitle) { petTitle.textContent = 'Choose Your Pet Template'; } } } else if (purpose === 'Prayer') { // Show prayer interactive templates const prayerTemplatesSection = document.getElementById('prayerTemplatesSection'); if (prayerTemplatesSection) { prayerTemplatesSection.style.display = 'block'; // Update the prayer section title const prayerTitle = prayerTemplatesSection.querySelector('.design-section-title'); if (prayerTitle) { prayerTitle.textContent = 'Choose Your Prayer Template'; } } } else if (purpose === 'Retirement') { // Show retirement interactive templates const retirementTemplatesSection = document.getElementById('retirementTemplatesSection'); if (retirementTemplatesSection) { retirementTemplatesSection.style.display = 'block'; // Update the retirement section title const retirementTitle = retirementTemplatesSection.querySelector('.design-section-title'); if (retirementTitle) { retirementTitle.textContent = 'Choose Your Retirement Template'; } } } else if (purpose === 'Wedding') { // Show wedding interactive templates const weddingTemplatesSection = document.getElementById('weddingTemplatesSection'); if (weddingTemplatesSection) { weddingTemplatesSection.style.display = 'block'; // Update the wedding section title const weddingTitle = weddingTemplatesSection.querySelector('.design-section-title'); if (weddingTitle) { weddingTitle.textContent = 'Choose Your Wedding Template'; } } } else if (purpose === 'Welcome') { // Show welcome interactive templates const welcomeTemplatesSection = document.getElementById('welcomeTemplatesSection'); if (welcomeTemplatesSection) { welcomeTemplatesSection.style.display = 'block'; // Update the welcome section title const welcomeTitle = welcomeTemplatesSection.querySelector('.design-section-title'); if (welcomeTitle) { welcomeTitle.textContent = 'Choose Your Welcome Template'; } } } else if (UNIVERSAL_TEMPLATE_CONFIG[purpose]) { // Show universal template system for configured purposes if (universalTemplatesSection) { universalTemplatesSection.style.display = 'block'; // Update the universal section title const universalTitle = document.getElementById('universalTemplateTitle'); if (universalTitle) { universalTitle.textContent = `Choose Your ${purpose} Template`; } // Load universal templates for the selected purpose loadUniversalTemplatesForPurpose(purpose); } } else { // Show regular template selection for other purposes templateSelectionSection.style.display = 'block'; // Update the template section title const templateSectionTitle = document.getElementById('templateSectionTitle'); if (templateSectionTitle) { templateSectionTitle.textContent = `Select Your ${purpose} Template`; } // Load templates for the selected purpose loadTemplatesForPurpose(purpose); } } // Update purpose in hidden field function updatePurposeField(purpose) { const selectedPurposeInput = document.getElementById('selectedPurpose'); if (selectedPurposeInput) { selectedPurposeInput.value = purpose; } } // Load Universal Templates for a specific purpose function loadUniversalTemplatesForPurpose(purpose) { const universalContainer = document.getElementById('universalTemplatesContainer'); if (!universalContainer) return; const config = UNIVERSAL_TEMPLATE_CONFIG[purpose]; if (!config || !config.templates) { universalContainer.innerHTML = ` No templates available for ${purpose} Templates for this purpose are coming soon. `; return; } // Clear existing templates universalContainer.innerHTML = ''; // Generate template cards config.templates.forEach(template => { const templateCard = document.createElement('div'); templateCard.className = 'universal-template-card'; templateCard.dataset.template = template.id; templateCard.dataset.purpose = purpose; // Create preview content based on template configuration let previewContent = ''; let backgroundStyle = ''; if (template.backgroundImage) { // Use background image (for Anniversary templates) backgroundStyle = `background-image: url('${template.backgroundImage}'); background-size: cover; background-position: center;`; } else if (template.backgroundColor) { // Use solid background color backgroundStyle = `background-color: ${template.backgroundColor};`; } else { // Default background backgroundStyle = 'background-color: #000000;'; } previewContent = ` ${config.defaultTexts.map((text, index) => { const style = template.textStyles && template.textStyles[index] ? template.textStyles[index] : {}; return `${text}`; }).join('')} `; templateCard.innerHTML = ` ${previewContent} ${template.name} `; // Add click event listener templateCard.addEventListener('click', function() { selectUniversalTemplate(template.id, purpose); }); universalContainer.appendChild(templateCard); }); } // Select Universal Template function selectUniversalTemplate(templateId, purpose) { // Remove previous selection document.querySelectorAll('.universal-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } // Store current template and purpose window.editorState = window.editorState || {}; window.editorState.currentTemplate = templateId; window.editorState.currentPurpose = purpose; // Get template configuration const config = UNIVERSAL_TEMPLATE_CONFIG[purpose]; const template = config.templates.find(t => t.id === templateId); if (template) { // Update editor with template data updateEditorWithTemplate(template, config); // Show editor showUniversalTemplateEditor(purpose); } } // Update Editor with Template Data function updateEditorWithTemplate(template, config) { // Update text inputs with default texts and placeholders config.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; input.placeholder = text; } }); // Update any remaining inputs with generic placeholders for (let i = config.defaultTexts.length; i { updateUniversalEditorCanvas(); }, 100); } } // Update Editor Title for any Purpose function updateEditorTitleForPurpose(purpose) { const editorTitle = document.getElementById('editorTitle'); if (editorTitle) { editorTitle.textContent = `Customize Your ${purpose} Billboard`; } } // Setup event listeners for universal template text inputs function setupUniversalTextInputListeners() { const textInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; textInputs.forEach(inputId => { const input = document.getElementById(inputId); if (input) { // Remove existing listeners to avoid duplicates input.removeEventListener('input', updateUniversalEditorCanvas); input.removeEventListener('keyup', updateUniversalEditorCanvas); // Add new listeners input.addEventListener('input', updateUniversalEditorCanvas); input.addEventListener('keyup', updateUniversalEditorCanvas); } }); } // Unified color palette - clean and organized const colorPalette = [ // Row 1: Grays and whites '#000000', '#333333', '#555555', '#777777', '#999999', '#bbbbbb', '#dddddd', '#eeeeee', '#f5f5f5', '#ffffff', // Row 2: Primary colors '#ff0000', '#ff6600', '#ffff00', '#00ff00', '#00ffff', '#0066ff', '#0000ff', '#6600ff', '#ff00ff', '#ff0066', // Row 3: Light tints '#ffcccc', '#ffddcc', '#ffffcc', '#ccffcc', '#ccffff', '#ccddff', '#ccccff', '#ddccff', '#ffccff', '#ffccdd', // Row 4: Medium tones '#ff9999', '#ffbb99', '#ffff99', '#99ff99', '#99ffff', '#99bbff', '#9999ff', '#bb99ff', '#ff99ff', '#ff99bb', // Row 5: Vibrant colors '#ff6600', '#99ff00', '#00ff99', '#0099ff', '#9900ff', '#ff0099', '#cc3300', '#ff3300', '#ff6600', '#cc6600', // Row 6: Dark tones '#663300', '#336600', '#003366', '#330066', '#660033', '#330000', '#003300', '#000033', '#660066', '#663333', // Row 7: Special colors with checkmark '✓', '#ffff66', '#ffff99', '#ffffcc', '#cccccc', '#000000' ]; let currentEditingLine = null; // Universal Template Configuration - Flexible for any purpose const UNIVERSAL_TEMPLATE_CONFIG = { 'Graduation': { defaultTexts: ['CONGRATULATIONS', 'Class of 2024', 'Achievement Unlocked', 'Proud Graduate'], templates: [ { id: 'graduation-template-1', name: 'Classic Graduation', backgroundColor: '#000080', textStyles: [ { color: '#FFD700', fontSize: '44px', fontFamily: 'Arial', fontWeight: '900', letterSpacing: '1px' }, { color: '#ffffff', fontSize: '32px', fontFamily: 'Georgia', fontStyle: 'italic' }, { color: '#FFD700', fontSize: '28px', fontFamily: 'Arial', fontWeight: '700' }, { color: '#ffffff', fontSize: '24px', fontFamily: 'Arial', fontWeight: '600' } ], textPositions: [ { x: 400, y: 100, align: 'center' }, { x: 400, y: 160, align: 'center' }, { x: 400, y: 220, align: 'center' }, { x: 400, y: 280, align: 'center' } ] } ] } }; // Dynamic Purpose Registration - Add new purposes at runtime window.registerNewPurpose = function(purposeName, config) { if (!purposeName || !config) { console.error('registerNewPurpose: Missing required parameters'); return false; } if (!config.defaultTexts || !config.templates) { console.error('registerNewPurpose: Config must have defaultTexts and templates'); return false; } // Add to universal template config UNIVERSAL_TEMPLATE_CONFIG[purposeName] = config; console.log(`✅ Purpose "${purposeName}" registered successfully`); console.log(`Templates available: ${config.templates.length}`); return true; }; // Get all available purposes window.getAvailablePurposes = function() { const purposes = Object.keys(UNIVERSAL_TEMPLATE_CONFIG); purposes.push('Anniversary'); // Anniversary uses its own system return purposes; }; // Check if purpose uses universal template system window.isUniversalPurpose = function(purpose) { return !!UNIVERSAL_TEMPLATE_CONFIG[purpose]; }; // Template data organized by purpose const templateData = { 'Anniversary': [ { id: 'anniversary1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-1.png', name: 'Anniversary Template 1' }, { id: 'anniversary2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-2.png', name: 'Anniversary Template 2' }, { id: 'anniversary3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-3.png', name: 'Anniversary Template 3' }, { id: 'anniversary4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-6.png', name: 'Anniversary Template 4' }, { id: 'anniversary5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-8.png', name: 'Anniversary Template 5' }, { id: 'anniversary6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-9.png', name: 'Anniversary Template 6' }, { id: 'anniversary7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-11.png', name: 'Anniversary Template 7' }, { id: 'anniversary8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-12.png', name: 'Anniversary Template 8' }, { id: 'anniversary9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-13.png', name: 'Anniversary Template 9' }, { id: 'anniversary10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-14.png', name: 'Anniversary Template 10' }, { id: 'anniversary11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-15.png', name: 'Anniversary Template 11' }, { id: 'anniversary12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-4.png', name: 'Anniversary Template 12' }, { id: 'anniversary13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-5.png', name: 'Anniversary Template 13' }, { id: 'anniversary14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-10.png', name: 'Anniversary Template 14' }, { id: 'anniversary15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Anniversary-7.png', name: 'Anniversary Template 15' } ], 'Benefit': [ { id: 'benefit1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-3.png', name: 'Benefit Template 1' }, { id: 'benefit2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-4.png', name: 'Benefit Template 2' }, { id: 'benefit3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-5.png', name: 'Benefit Template 3' }, { id: 'benefit4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-6.png', name: 'Benefit Template 4' }, { id: 'benefit5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-8.png', name: 'Benefit Template 5' }, { id: 'benefit6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-9.png', name: 'Benefit Template 6' }, { id: 'benefit7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-11.png', name: 'Benefit Template 7' }, { id: 'benefit8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-12.png', name: 'Benefit Template 8' }, { id: 'benefit9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-13.png', name: 'Benefit Template 9' }, { id: 'benefit10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-14.png', name: 'Benefit Template 10' }, { id: 'benefit11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-10.png', name: 'Benefit Template 11' }, { id: 'benefit12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-7.png', name: 'Benefit Template 12' }, { id: 'benefit13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-2.png', name: 'Benefit Template 13' }, { id: 'benefit14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-1.png', name: 'Benefit Template 14' }, { id: 'benefit15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Benefit-15.png', name: 'Benefit Template 15' } ], 'Christian': [ { id: 'christian1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-1.png', name: 'Christian Template 1' }, { id: 'christian2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-2.png', name: 'Christian Template 2' }, { id: 'christian3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-3.png', name: 'Christian Template 3' }, { id: 'christian4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-4.png', name: 'Christian Template 4' }, { id: 'christian5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-5.png', name: 'Christian Template 5' }, { id: 'christian6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-6.png', name: 'Christian Template 6' }, { id: 'christian7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-8.png', name: 'Christian Template 7' }, { id: 'christian8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-9.png', name: 'Christian Template 8' }, { id: 'christian9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-10.png', name: 'Christian Template 9' }, { id: 'christian10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-11.png', name: 'Christian Template 10' }, { id: 'christian11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-12.png', name: 'Christian Template 11' }, { id: 'christian12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-13.png', name: 'Christian Template 12' }, { id: 'christian13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-14.png', name: 'Christian Template 13' }, { id: 'christian14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-15.png', name: 'Christian Template 14' }, { id: 'christian15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Christian-7.png', name: 'Christian Template 15' } ], 'Graduation': [ { id: 'graduation1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-1.png', name: 'Graduation Template 1' }, { id: 'graduation2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-2.png', name: 'Graduation Template 2' }, { id: 'graduation3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-4.png', name: 'Graduation Template 3' }, { id: 'graduation4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-5.png', name: 'Graduation Template 4' }, { id: 'graduation5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-7.png', name: 'Graduation Template 5' }, { id: 'graduation6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-8.png', name: 'Graduation Template 6' }, { id: 'graduation7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-9.png', name: 'Graduation Template 7' }, { id: 'graduation8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-10.png', name: 'Graduation Template 8' }, { id: 'graduation9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-11.png', name: 'Graduation Template 9' }, { id: 'graduation10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-12.png', name: 'Graduation Template 10' }, { id: 'graduation11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-13.png', name: 'Graduation Template 11' }, { id: 'graduation12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-14.png', name: 'Graduation Template 12' }, { id: 'graduation13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-15.png', name: 'Graduation Template 13' }, { id: 'graduation14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-6.png', name: 'Graduation Template 14' }, { id: 'graduation15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Graduation-3.png', name: 'Graduation Template 15' } ], 'Holiday': [ { id: 'holiday1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-1.png', name: 'Holiday Template 1' }, { id: 'holiday2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-2.png', name: 'Holiday Template 2' }, { id: 'holiday3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-3.png', name: 'Holiday Template 3' }, { id: 'holiday4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-4.png', name: 'Holiday Template 4' }, { id: 'holiday5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-5.png', name: 'Holiday Template 5' }, { id: 'holiday6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-6.png', name: 'Holiday Template 6' }, { id: 'holiday7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-7.png', name: 'Holiday Template 7' }, { id: 'holiday8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-8.png', name: 'Holiday Template 8' }, { id: 'holiday9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-9.png', name: 'Holiday Template 9' }, { id: 'holiday10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-10.png', name: 'Holiday Template 10' }, { id: 'holiday11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-11.png', name: 'Holiday Template 11' }, { id: 'holiday12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-12.png', name: 'Holiday Template 12' }, { id: 'holiday13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-13.png', name: 'Holiday Template 13' }, { id: 'holiday14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-14.png', name: 'Holiday Template 14' }, { id: 'holiday15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Holiday-15.png', name: 'Holiday Template 15' } ], 'Local School': [ { id: 'localschool1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-1.png', name: 'Local Schools Template 1' }, { id: 'localschool2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-2.png', name: 'Local Schools Template 2' }, { id: 'localschool3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-3.png', name: 'Local Schools Template 3' }, { id: 'localschool4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-4.png', name: 'Local Schools Template 4' }, { id: 'localschool5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-5.png', name: 'Local Schools Template 5' }, { id: 'localschool6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-6.png', name: 'Local Schools Template 6' }, { id: 'localschool7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-7.png', name: 'Local Schools Template 7' }, { id: 'localschool8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-8.png', name: 'Local Schools Template 8' }, { id: 'localschool9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-9.png', name: 'Local Schools Template 9' }, { id: 'localschool10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/07/Local-Schools-10.png', name: 'Local Schools Template 10' } ], 'Love': [ { id: 'love1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-2.png', name: 'Love Template 1' }, { id: 'love2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-5.png', name: 'Love Template 2' }, { id: 'love3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-6.png', name: 'Love Template 3' }, { id: 'love4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-7.png', name: 'Love Template 4' }, { id: 'love5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-8.png', name: 'Love Template 5' }, { id: 'love6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-9.png', name: 'Love Template 6' }, { id: 'love7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-10.png', name: 'Love Template 7' }, { id: 'love8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-11.png', name: 'Love Template 8' }, { id: 'love9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-1.png', name: 'Love Template 9' }, { id: 'love10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-3.png', name: 'Love Template 10' }, { id: 'love11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-4.png', name: 'Love Template 11' }, { id: 'love12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-12.png', name: 'Love Template 12' }, { id: 'love13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-13.png', name: 'Love Template 13' }, { id: 'love14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-14.png', name: 'Love Template 14' }, { id: 'love15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Love-15.png', name: 'Love Template 15' } ], 'Marry Me': [ { id: 'marryme1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-1.png', name: 'Marry Me Template 1' }, { id: 'marryme2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-2.png', name: 'Marry Me Template 2' }, { id: 'marryme3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-3.png', name: 'Marry Me Template 3' }, { id: 'marryme4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-4.png', name: 'Marry Me Template 4' }, { id: 'marryme5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-5.png', name: 'Marry Me Template 5' }, { id: 'marryme6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-6.png', name: 'Marry Me Template 6' }, { id: 'marryme7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-7.png', name: 'Marry Me Template 7' }, { id: 'marryme8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-8.png', name: 'Marry Me Template 8' }, { id: 'marryme9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-11.png', name: 'Marry Me Template 9' }, { id: 'marryme10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-14.png', name: 'Marry Me Template 10' }, { id: 'marryme11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-15.png', name: 'Marry Me Template 11' }, { id: 'marryme12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-10.png', name: 'Marry Me Template 12' }, { id: 'marryme13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-12.png', name: 'Marry Me Template 13' }, { id: 'marryme14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-13.png', name: 'Marry Me Template 14' }, { id: 'marryme15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Marry-Me-9.png', name: 'Marry Me Template 15' } ], 'New Born': [ { id: 'newborn1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-1.png', name: 'New Born Template 1' }, { id: 'newborn2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-2.png', name: 'New Born Template 2' }, { id: 'newborn3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-3.png', name: 'New Born Template 3' }, { id: 'newborn4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-6.png', name: 'New Born Template 4' }, { id: 'newborn5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-8.png', name: 'New Born Template 5' }, { id: 'newborn6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-9.png', name: 'New Born Template 6' }, { id: 'newborn7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-12.png', name: 'New Born Template 7' }, { id: 'newborn8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-13.png', name: 'New Born Template 8' }, { id: 'newborn9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-14.png', name: 'New Born Template 9' }, { id: 'newborn10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-15.png', name: 'New Born Template 10' }, { id: 'newborn11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-4.png', name: 'New Born Template 11' }, { id: 'newborn12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-5.png', name: 'New Born Template 12' }, { id: 'newborn13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-7.png', name: 'New Born Template 13' }, { id: 'newborn14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-10.png', name: 'New Born Template 14' }, { id: 'newborn15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/New-Born-11.png', name: 'New Born Template 15' } ], 'Obituary': [ { id: 'obituary1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-1.png', name: 'Obituary Template 1' }, { id: 'obituary2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-2.png', name: 'Obituary Template 2' }, { id: 'obituary3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-3.png', name: 'Obituary Template 3' }, { id: 'obituary4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-4.png', name: 'Obituary Template 4' }, { id: 'obituary5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-6.png', name: 'Obituary Template 5' }, { id: 'obituary6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-7.png', name: 'Obituary Template 6' }, { id: 'obituary7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-9.png', name: 'Obituary Template 7' }, { id: 'obituary8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-10.png', name: 'Obituary Template 8' }, { id: 'obituary9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-11.png', name: 'Obituary Template 9' }, { id: 'obituary10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-12.png', name: 'Obituary Template 10' }, { id: 'obituary11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-13.png', name: 'Obituary Template 11' }, { id: 'obituary12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-14.png', name: 'Obituary Template 12' }, { id: 'obituary13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-15.png', name: 'Obituary Template 13' }, { id: 'obituary14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-5.png', name: 'Obituary Template 14' }, { id: 'obituary15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Obituary-8.png', name: 'Obituary Template 15' } ], 'Other': [ { id: 'other1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-2.png', name: 'Other Template 1' }, { id: 'other2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-3.png', name: 'Other Template 2' }, { id: 'other3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-7.png', name: 'Other Template 3' }, { id: 'other4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-11.png', name: 'Other Template 4' }, { id: 'other5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-12.png', name: 'Other Template 5' }, { id: 'other6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-13.png', name: 'Other Template 6' }, { id: 'other7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-14.png', name: 'Other Template 7' }, { id: 'other8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-15.png', name: 'Other Template 8' }, { id: 'other9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-1.png', name: 'Other Template 9' }, { id: 'other10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-4.png', name: 'Other Template 10' }, { id: 'other11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-5.png', name: 'Other Template 11' }, { id: 'other12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-6.png', name: 'Other Template 12' }, { id: 'other13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-8.png', name: 'Other Template 13' }, { id: 'other14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-9.png', name: 'Other Template 14' }, { id: 'other15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Other-10.png', name: 'Other Template 15' } ], 'Pet': [ { id: 'pet1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-1.png', name: 'Pet Template 1' }, { id: 'pet2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-2.png', name: 'Pet Template 2' }, { id: 'pet3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-3.png', name: 'Pet Template 3' }, { id: 'pet4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-4.png', name: 'Pet Template 4' }, { id: 'pet5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-5.png', name: 'Pet Template 5' }, { id: 'pet6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-6.png', name: 'Pet Template 6' }, { id: 'pet7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-7.png', name: 'Pet Template 7' }, { id: 'pet8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-8.png', name: 'Pet Template 8' }, { id: 'pet9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-9.png', name: 'Pet Template 9' }, { id: 'pet10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-10.png', name: 'Pet Template 10' }, { id: 'pet11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-11.png', name: 'Pet Template 11' }, { id: 'pet12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-12.png', name: 'Pet Template 12' }, { id: 'pet13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-13.png', name: 'Pet Template 13' }, { id: 'pet14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-14.png', name: 'Pet Template 14' }, { id: 'pet15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Pet-15.png', name: 'Pet Template 15' } ], 'Prayer': [ { id: 'prayer1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-1.png', name: 'Prayer Template 1' }, { id: 'prayer2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-2.png', name: 'Prayer Template 2' }, { id: 'prayer3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-3.png', name: 'Prayer Template 3' }, { id: 'prayer4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-4.png', name: 'Prayer Template 4' }, { id: 'prayer5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-5.png', name: 'Prayer Template 5' }, { id: 'prayer6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-7.png', name: 'Prayer Template 6' }, { id: 'prayer7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-8.png', name: 'Prayer Template 7' }, { id: 'prayer8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-11.png', name: 'Prayer Template 8' }, { id: 'prayer9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-12.png', name: 'Prayer Template 9' }, { id: 'prayer10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-13.png', name: 'Prayer Template 10' }, { id: 'prayer11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-14.png', name: 'Prayer Template 11' }, { id: 'prayer12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-15.png', name: 'Prayer Template 12' }, { id: 'prayer13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-10.png', name: 'Prayer Template 13' }, { id: 'prayer14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-6.png', name: 'Prayer Template 14' }, { id: 'prayer15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Prayer-9.png', name: 'Prayer Template 15' } ], 'Retirement': [ { id: 'retirement1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-3.png', name: 'Retirement Template 1' }, { id: 'retirement2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-4.png', name: 'Retirement Template 2' }, { id: 'retirement3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-5.png', name: 'Retirement Template 3' }, { id: 'retirement4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-6.png', name: 'Retirement Template 4' }, { id: 'retirement5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-7.png', name: 'Retirement Template 5' }, { id: 'retirement6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-8.png', name: 'Retirement Template 6' }, { id: 'retirement7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-9.png', name: 'Retirement Template 7' }, { id: 'retirement8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-10.png', name: 'Retirement Template 8' }, { id: 'retirement9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-11.png', name: 'Retirement Template 9' }, { id: 'retirement10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-12.png', name: 'Retirement Template 10' }, { id: 'retirement11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-13.png', name: 'Retirement Template 11' }, { id: 'retirement12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-14.png', name: 'Retirement Template 12' }, { id: 'retirement13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-15.png', name: 'Retirement Template 13' }, { id: 'retirement14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-1.png', name: 'Retirement Template 14' }, { id: 'retirement15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Retirement-2.png', name: 'Retirement Template 15' } ], 'Wedding': [ { id: 'wedding1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-1.png', name: 'Wedding Template 1' }, { id: 'wedding2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-2.png', name: 'Wedding Template 2' }, { id: 'wedding3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-3.png', name: 'Wedding Template 3' }, { id: 'wedding4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-4.png', name: 'Wedding Template 4' }, { id: 'wedding5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-5.png', name: 'Wedding Template 5' }, { id: 'wedding6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-6.png', name: 'Wedding Template 6' }, { id: 'wedding7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-7.png', name: 'Wedding Template 7' }, { id: 'wedding8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-8.png', name: 'Wedding Template 8' }, { id: 'wedding9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-10.png', name: 'Wedding Template 9' }, { id: 'wedding10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-11.png', name: 'Wedding Template 10' }, { id: 'wedding11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-12.png', name: 'Wedding Template 11' }, { id: 'wedding12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-13.png', name: 'Wedding Template 12' }, { id: 'wedding13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-15.png', name: 'Wedding Template 13' }, { id: 'wedding14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-14.png', name: 'Wedding Template 14' }, { id: 'wedding15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Wedding-9.png', name: 'Wedding Template 15' } ], 'Welcome': [ { id: 'welcome1', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-5.png', name: 'Welcome Template 1' }, { id: 'welcome2', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-6.png', name: 'Welcome Template 2' }, { id: 'welcome3', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-8.png', name: 'Welcome Template 3' }, { id: 'welcome4', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-9.png', name: 'Welcome Template 4' }, { id: 'welcome5', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-13.png', name: 'Welcome Template 5' }, { id: 'welcome6', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-14.png', name: 'Welcome Template 6' }, { id: 'welcome7', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-1.png', name: 'Welcome Template 7' }, { id: 'welcome8', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-2.png', name: 'Welcome Template 8' }, { id: 'welcome9', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-3.png', name: 'Welcome Template 9' }, { id: 'welcome10', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-4.png', name: 'Welcome Template 10' }, { id: 'welcome11', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-7.png', name: 'Welcome Template 11' }, { id: 'welcome12', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-10.png', name: 'Welcome Template 12' }, { id: 'welcome13', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-11.png', name: 'Welcome Template 13' }, { id: 'welcome14', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-12.png', name: 'Welcome Template 14' }, { id: 'welcome15', url: 'https://www.borgesmedia.com/wp-content/uploads/2025/06/Welcome-15.png', name: 'Welcome Template 15' } ], 'Birthday': [ // Placeholder for birthday templates - will be added later ], 'Business Promotion': [ // Placeholder for business templates - will be added later ] }; // Function to generate template definitions dynamically function generateTemplateDefinition(templateId, templateUrl) { return { background: templateUrl, textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }; } // Function to get template definition (checks both static and dynamic templates) function getTemplate(templateId) { // Check if template exists in static templates object if (templates[templateId]) { return templates[templateId]; } // Generate dynamic template definition // Find the template in templateData for (const purpose in templateData) { const purposeTemplates = templateData[purpose]; const template = purposeTemplates.find(t => t.id === templateId); if (template) { return generateTemplateDefinition(templateId, template.url); } } // Fallback to default return templates.anniversary1 || { background: '#ff6b6b', textPositions: [ { x: 400, y: 120, align: 'center' }, { x: 400, y: 180, align: 'center' }, { x: 400, y: 260, align: 'center' }, { x: 400, y: 320, align: 'center' } ] }; } // Function to load templates based on purpose function loadTemplatesForPurpose(purpose) { const templateSelection = document.getElementById('templateSelection'); const noTemplatesMessage = document.getElementById('noTemplatesMessage'); // Clear existing templates templateSelection.innerHTML = ''; if (!purpose || !templateData[purpose] || templateData[purpose].length === 0) { templateSelection.innerHTML = ` No templates available for ${purpose} Templates for this purpose are coming soon. `; return; } // Hide the no templates message if (noTemplatesMessage) { noTemplatesMessage.style.display = 'none'; } const templates = templateData[purpose]; templates.forEach((template, index) => { const templateOption = document.createElement('div'); templateOption.className = `template-option ${index === 0 ? 'active' : ''}`; templateOption.setAttribute('data-template', template.id); templateOption.setAttribute('data-purpose', purpose); const img = document.createElement('img'); img.src = template.url; img.alt = template.name; img.style.width = '100%'; img.style.height = '100%'; img.style.objectFit = 'cover'; templateOption.appendChild(img); templateSelection.appendChild(templateOption); // Add click event listener templateOption.addEventListener('click', function() { document.querySelectorAll('.template-option').forEach(opt => opt.classList.remove('active')); this.classList.add('active'); currentTemplate = this.getAttribute('data-template'); document.getElementById('selectedTemplate').value = currentTemplate; updateBillboard(); }); }); // Set the first template as current if available if (templates.length > 0) { currentTemplate = templates[0].id; document.getElementById('selectedTemplate').value = currentTemplate; updateBillboard(); } } // Setup event listeners function setupEventListeners() { // Text inputs (legacy - may not exist in current HTML) ['line1', 'line2', 'line3', 'line4'].forEach(lineId => { const input = document.getElementById(lineId); if (input) { input.addEventListener('input', updateBillboard); } }); // Font selection const fontSelect = document.getElementById('fontSelect'); if (fontSelect) { fontSelect.addEventListener('change', function() { currentFont = this.value; // Apply to all text lines Object.keys(textSettings).forEach(line => { textSettings[line].fontFamily = currentFont; }); updateBillboard(); }); } // Background color const bgColorPicker = document.getElementById('bgColorPicker'); const bgColorPreview = document.getElementById('bgColorPreview'); const bgColorValue = document.getElementById('bgColorValue'); if (bgColorPicker && bgColorPreview && bgColorValue) { bgColorPicker.addEventListener('input', function() { currentBgColor = this.value; bgColorPreview.style.backgroundColor = currentBgColor; bgColorValue.textContent = currentBgColor; updateBillboard(); }); bgColorPreview.addEventListener('click', function() { bgColorPicker.click(); }); } // Background graphics document.querySelectorAll('.background-graphic-item').forEach(item => { item.addEventListener('click', function() { document.querySelectorAll('.background-graphic-item').forEach(i => i.classList.remove('selected')); this.classList.add('selected'); currentBgGraphic = this.getAttribute('data-bg'); document.getElementById('selectedBackground').value = currentBgGraphic; updateBillboard(); }); }); // Photo upload const photoUpload = document.getElementById('photoUpload'); const photoInput = document.getElementById('photoInput'); if (photoUpload && photoInput) { photoUpload.addEventListener('click', () => photoInput.click()); photoInput.addEventListener('change', handlePhotoUpload); } // Setup color pickers and settings buttons setupColorPickers(); setupSettingsButtons(); // Close dropdowns when clicking outside document.addEventListener('click', function(e) { if (!e.target.closest('.color-picker-dropdown')) { document.querySelectorAll('.color-dropdown').forEach(dropdown => { dropdown.classList.remove('show'); }); } }); } // Setup color pickers for each text line function setupColorPickers() { ['1', '2', '3', '4'].forEach(lineNum => { const colorBtn = document.getElementById(`colorBtn${lineNum}`); const colorDropdown = document.getElementById(`colorDropdown${lineNum}`); const colorPaletteEl = document.getElementById(`colorPalette${lineNum}`); const lineId = `line${lineNum}`; // Check if all elements exist if (!colorBtn || !colorDropdown || !colorPaletteEl) { console.warn(`Missing elements for line ${lineNum}`); return; } // Set initial color const initialColor = textSettings[lineId].color; colorBtn.style.backgroundColor = initialColor; // Create unified color picker createUnifiedColorPicker(colorPaletteEl, colorDropdown, lineId, setTextColor); // Color button click colorBtn.addEventListener('click', (e) => { e.stopPropagation(); // Close other dropdowns document.querySelectorAll('.color-dropdown').forEach(dropdown => { if (dropdown !== colorDropdown) { dropdown.classList.remove('show'); } }); colorDropdown.classList.toggle('show'); }); }); } // Setup settings buttons function setupSettingsButtons() { ['1', '2', '3', '4'].forEach(lineNum => { const settingsBtn = document.getElementById(`settingsBtn${lineNum}`); if (settingsBtn) { settingsBtn.addEventListener('click', () => { openFontModal(`line${lineNum}`); }); } }); } // Photo upload handler function handlePhotoUpload(event) { const file = event.target.files[0]; if (!file) return; // Validate file format const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png']; if (!allowedTypes.includes(file.type.toLowerCase())) { alert('Please upload a JPG or PNG image file only.'); event.target.value = ''; // Clear the input return; } const reader = new FileReader(); reader.onload = function(e) { const img = new Image(); img.onload = function() { // Check image resolution const width = img.naturalWidth; const height = img.naturalHeight; const minRecommendedWidth = 1200; const minRecommendedHeight = 800; let resolutionMessage = ''; if (width < minRecommendedWidth || height < minRecommendedHeight) { resolutionMessage = `\n\nNote: Image resolution is ${width}x${height}px. For best quality, we recommend at least ${minRecommendedWidth}x${minRecommendedHeight}px.`; } uploadedImage = img; updateBillboard(); // Update upload container const photoUpload = document.getElementById('photoUpload'); photoUpload.innerHTML = ` ✅ Image uploaded: ${file.name} Click to change${resolutionMessage ? ' • Low resolution detected' : ''} `; // Show resolution warning if needed if (resolutionMessage) { setTimeout(() => { alert(`Image uploaded successfully!${resolutionMessage}`); }, 100); } }; img.src = e.target.result; }; reader.readAsDataURL(file); } // Set text color for a specific line function setTextColor(lineId, color) { textSettings[lineId].color = color; const colorBtn = document.getElementById(`colorBtn${lineId.slice(-1)}`); colorBtn.style.backgroundColor = color; updateBillboard(); } // Open font modal for specific text line function openFontModal(lineId) { currentEditingLine = lineId; const modal = document.getElementById('fontModal'); const settings = textSettings[lineId]; // Set current values in modal document.getElementById('modalFontSelect').value = settings.fontFamily; document.getElementById('modalFontSize').value = settings.fontSize; document.getElementById('modalShadow').checked = settings.shadow; document.getElementById('modalShadowWidth').value = settings.shadowWidth !== undefined ? settings.shadowWidth : 4; try { modal.showModal(); // Ensure proper centering modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.margin = 'auto'; } catch (error) { // Fallback for browsers that don't support showModal modal.style.display = 'flex'; modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.margin = 'auto'; } } // Make functions globally accessible window.applyFontSettings = function() { if (!currentEditingLine) return; const fontFamily = document.getElementById('modalFontSelect').value; const fontSize = parseInt(document.getElementById('modalFontSize').value); const shadow = document.getElementById('modalShadow').checked; const shadowWidth = parseInt(document.getElementById('modalShadowWidth').value); const applyToAll = document.getElementById('applyToAll').checked; if (applyToAll) { // Apply to all text lines Object.keys(textSettings).forEach(line => { textSettings[line].fontFamily = fontFamily; textSettings[line].fontSize = fontSize; textSettings[line].shadow = shadow; textSettings[line].shadowWidth = shadowWidth; }); } else { // Apply only to current line textSettings[currentEditingLine].fontFamily = fontFamily; textSettings[currentEditingLine].fontSize = fontSize; textSettings[currentEditingLine].shadow = shadow; textSettings[currentEditingLine].shadowWidth = shadowWidth; } updateBillboard(); window.closeFontModal(); }; window.closeFontModal = function() { const modal = document.getElementById('fontModal'); if (modal) { try { modal.close(); } catch (error) { // Fallback for browsers that don't support close modal.style.display = 'none'; } } currentEditingLine = null; const applyToAllCheckbox = document.getElementById('applyToAll'); if (applyToAllCheckbox) { applyToAllCheckbox.checked = false; } }; // Main billboard update function (now primarily for editor canvas) function updateBillboard() { try { // Only update if we're in editor mode and have editor canvas if (isEditorMode && editorCanvas && editorCtx) { updateEditorCanvas(); return; } // For compatibility, save billboard data if needed saveBillboardData(); } catch (error) { console.error('Error updating billboard:', error); } } // Draw background function drawBackground() { const template = getTemplate(currentTemplate); if (template && template.background) { if (template.background.includes('gradient')) { // Parse gradient const gradientMatch = template.background.match(/linear-gradient\(([^)]+)\)/); if (gradientMatch) { const parts = gradientMatch[1].split(',').map(s => s.trim()); const angle = parts[0]; const color1 = parts[1]; const color2 = parts[2]; // Create gradient const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height); gradient.addColorStop(0, color1); gradient.addColorStop(1, color2); ctx.fillStyle = gradient; ctx.fillRect(0, 0, canvas.width, canvas.height); } else { ctx.fillStyle = currentBgColor; ctx.fillRect(0, 0, canvas.width, canvas.height); } } else if (template.background.includes('http')) { // Handle image background const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function() { ctx.drawImage(img, 0, 0, canvas.width, canvas.height); // Redraw text after image loads setTimeout(() => { drawTextLines(); }, 10); }; img.src = template.background; } else { ctx.fillStyle = currentBgColor; ctx.fillRect(0, 0, canvas.width, canvas.height); } } else { ctx.fillStyle = currentBgColor; ctx.fillRect(0, 0, canvas.width, canvas.height); } } // Draw uploaded image function drawUploadedImage() { const maxWidth = canvas.width * 0.3; const maxHeight = canvas.height * 0.4; let drawWidth = uploadedImage.width; let drawHeight = uploadedImage.height; // Scale image to fit if (drawWidth > maxWidth) { drawHeight = (drawHeight * maxWidth) / drawWidth; drawWidth = maxWidth; } if (drawHeight > maxHeight) { drawWidth = (drawWidth * maxHeight) / drawHeight; drawHeight = maxHeight; } // Position image (bottom right) const x = canvas.width - drawWidth - 20; const y = canvas.height - drawHeight - 20; ctx.drawImage(uploadedImage, x, y, drawWidth, drawHeight); } // Draw background graphic function drawBackgroundGraphic() { ctx.save(); ctx.globalAlpha = 0.3; ctx.font = '100px Arial'; ctx.textAlign = 'center'; const graphics = { 'balloons': '🎈', 'stars': '⭐', 'hearts': '❤️', 'confetti': '🎉', 'flowers': '🌸' }; const graphic = graphics[currentBgGraphic]; if (graphic) { // Draw multiple instances for (let i = 0; i { const input = document.getElementById(lineId); if (!input) return; // Skip if input doesn't exist const text = input.value; if (text.trim()) { const settings = textSettings[lineId]; const position = template.textPositions[index]; ctx.save(); // Set font ctx.font = `${settings.fontSize}px ${settings.fontFamily}`; ctx.textAlign = position.align; ctx.fillStyle = settings.color; // Clear any existing shadow settings to prevent accumulation ctx.shadowColor = 'transparent'; ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; // Draw shadow manually if enabled (more reliable than canvas shadow properties) if (settings.shadow) { const shadowWidth = settings.shadowWidth !== undefined ? settings.shadowWidth : 4; // Draw shadow text first ctx.fillStyle = 'rgba(0,0,0,0.7)'; ctx.fillText(text, position.x + shadowWidth / 2, position.y + shadowWidth / 2); } // Draw main text with original color ctx.fillStyle = settings.color; ctx.fillText(text, position.x, position.y); ctx.restore(); } }); } // Professional comprehensive state saving with complete UI restoration data function saveBillboardData() { console.log('saveBillboardData: Starting comprehensive data save with UI state...'); // Get text lines from editor inputs (primary source) and regular inputs (fallback) const textLines = {}; // First, try to get from editor inputs (these are the active ones when in editor mode) const editorInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; let hasEditorData = false; editorInputs.forEach((inputId, index) => { const element = document.getElementById(inputId); if (element && element.value && element.value.trim()) { const lineKey = `line${index + 1}`; textLines[lineKey] = element.value.trim(); hasEditorData = true; console.log(`saveBillboardData: Captured from editor ${inputId} = "${element.value}"`); } }); // If no editor data, fall back to regular inputs if (!hasEditorData) { const regularInputs = ['line1', 'line2', 'line3', 'line4']; regularInputs.forEach(inputId => { const element = document.getElementById(inputId); if (element && element.value && element.value.trim()) { textLines[inputId] = element.value.trim(); console.log(`saveBillboardData: Captured from regular ${inputId} = "${element.value}"`); } }); } // Also save editor-specific mapping for restoration const editorTextLines = {}; editorInputs.forEach(inputId => { const element = document.getElementById(inputId); if (element && element.value && element.value.trim()) { editorTextLines[inputId] = element.value.trim(); } }); // Get current template from multiple sources const currentTemplate = window.editorState?.currentAnniversaryTemplate || window.editorState?.currentBenefitTemplate || window.editorState?.currentChristianTemplate || window.editorState?.currentGraduationTemplate || window.editorState?.currentHolidayTemplate || window.editorState?.currentLocalSchoolTemplate || window.editorState?.currentLoveTemplate || window.editorState?.currentMarryMeTemplate || window.editorState?.currentNewbornTemplate || window.editorState?.currentObituaryTemplate || window.editorState?.currentOtherTemplate || window.editorState?.currentPetTemplate || window.editorState?.currentPrayerTemplate || window.editorState?.currentRetirementTemplate || window.editorState?.currentWeddingTemplate || window.editorState?.currentWelcomeTemplate || localStorage.getItem('currentAnniversaryTemplate') || localStorage.getItem('currentBenefitTemplate') || localStorage.getItem('currentChristianTemplate') || localStorage.getItem('currentGraduationTemplate') || localStorage.getItem('currentHolidayTemplate') || localStorage.getItem('currentLocalSchoolTemplate') || localStorage.getItem('currentLoveTemplate') || localStorage.getItem('currentMarryMeTemplate') || localStorage.getItem('currentNewbornTemplate') || localStorage.getItem('currentObituaryTemplate') || localStorage.getItem('currentOtherTemplate') || localStorage.getItem('currentPetTemplate') || localStorage.getItem('currentPrayerTemplate') || localStorage.getItem('currentRetirementTemplate') || localStorage.getItem('currentWeddingTemplate') || localStorage.getItem('currentWelcomeTemplate') || document.getElementById('selectedTemplate')?.value || 'default'; // Get background settings from multiple sources const bgColor = window.editorState?.selectedBackgroundColor || localStorage.getItem('selectedBackgroundColor') || currentBgColor || '#000000'; const bgGraphic = window.editorState?.selectedAnniversaryBackground || window.editorState?.selectedBenefitBackground || window.editorState?.selectedChristianBackground || window.editorState?.selectedGraduationBackground || window.editorState?.selectedHolidayBackground || window.editorState?.selectedLocalSchoolBackground || window.editorState?.selectedLoveBackground || window.editorState?.selectedMarryMeBackground || window.editorState?.selectedNewbornBackground || window.editorState?.selectedObituaryBackground || window.editorState?.selectedOtherBackground || window.editorState?.selectedPetBackground || window.editorState?.selectedPrayerBackground || window.editorState?.selectedRetirementBackground || window.editorState?.selectedWeddingBackground || window.editorState?.selectedWelcomeBackground || localStorage.getItem('selectedAnniversaryBackground') || localStorage.getItem('selectedBenefitBackground') || localStorage.getItem('selectedChristianBackground') || localStorage.getItem('selectedGraduationBackground') || localStorage.getItem('selectedHolidayBackground') || localStorage.getItem('selectedLocalSchoolBackground') || localStorage.getItem('selectedLoveBackground') || localStorage.getItem('selectedMarryMeBackground') || localStorage.getItem('selectedNewbornBackground') || localStorage.getItem('selectedObituaryBackground') || localStorage.getItem('selectedOtherBackground') || localStorage.getItem('selectedPetBackground') || localStorage.getItem('selectedPrayerBackground') || localStorage.getItem('selectedRetirementBackground') || localStorage.getItem('selectedWeddingBackground') || localStorage.getItem('selectedWelcomeBackground') || currentBgGraphic || 'Anniversary-1'; const bgType = window.editorState?.selectedBackgroundType || localStorage.getItem('selectedBackgroundType') || 'image'; // Capture comprehensive text settings including colors and fonts for each line const comprehensiveTextSettings = {}; ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4'].forEach(lineId => { const colorBtn = document.getElementById(lineId.replace('editorLine', 'editorColorBtn')); const colorValue = colorBtn ? colorBtn.style.backgroundColor : '#ffffff'; comprehensiveTextSettings[lineId] = { color: colorValue || '#ffffff', fontSize: window.editorState?.editorTextSettings?.[lineId]?.fontSize || 50, fontFamily: window.editorState?.editorTextSettings?.[lineId]?.fontFamily || 'Arial', shadow: window.editorState?.editorTextSettings?.[lineId]?.shadow !== false, shadowWidth: window.editorState?.editorTextSettings?.[lineId]?.shadowWidth || 4 }; }); // Capture uploaded image data from multiple sources const uploadedImageData = window.editorState?.editorUploadedImage?.src || (uploadedImage ? uploadedImage.src : null); // Get current canvas state from multiple possible canvases let canvasDataURL = null; const canvasSources = ['billboardCanvas', 'editorCanvas']; for (const canvasId of canvasSources) { const canvas = document.getElementById(canvasId); if (canvas) { try { canvasDataURL = canvas.toDataURL('image/png', 0.9); console.log(`saveBillboardData: Canvas image captured from ${canvasId}`); break; } catch (e) { console.warn(`saveBillboardData: Failed to capture from ${canvasId}:`, e); } } } // Capture color picker button states for restoration const colorPickerStates = {}; ['editorColorBtn1', 'editorColorBtn2', 'editorColorBtn3', 'editorColorBtn4'].forEach(btnId => { const btn = document.getElementById(btnId); if (btn) { colorPickerStates[btnId] = btn.style.backgroundColor || '#ffffff'; } }); // Create comprehensive data object with complete UI restoration data const data = { template: currentTemplate, textLines: textLines, editorTextLines: editorTextLines, // Separate mapping for editor inputs bgColor: bgColor, bgGraphic: bgGraphic, bgType: bgType, textSettings: comprehensiveTextSettings, hasUploadedImage: !!uploadedImageData, uploadedImageData: uploadedImageData, canvasImage: canvasDataURL, timestamp: new Date().toISOString(), // Enhanced UI state with complete restoration data uiState: { selectedTemplate: currentTemplate, selectedBackground: bgGraphic, selectedBackgroundType: bgType, backgroundColor: bgColor, isCustomizing: true, editorWasOpen: document.getElementById('templateEditorContainer')?.classList.contains('active') || false, // Color picker states for visual restoration colorPickerStates: colorPickerStates, // Font settings for each line fontSettings: comprehensiveTextSettings, // Background selection state backgroundSelection: { type: bgType, graphic: bgGraphic, color: bgColor } } }; console.log('saveBillboardData: Saving comprehensive design state with UI restoration data:', data); const billboardDataField = document.getElementById('billboardData'); if (billboardDataField) { billboardDataField.value = JSON.stringify(data); } // Store in multiple localStorage keys for different purposes and easy restoration localStorage.setItem('adDesignData', JSON.stringify(data)); localStorage.setItem('billboardCanvasImage', canvasDataURL || ''); localStorage.setItem('billboardUIState', JSON.stringify(data.uiState)); localStorage.setItem('billboardTextLines', JSON.stringify(data.textLines)); localStorage.setItem('billboardSettings', JSON.stringify({ template: data.template, bgColor: data.bgColor, bgGraphic: data.bgGraphic, bgType: data.bgType, textSettings: data.textSettings })); // Store individual settings for easier restoration localStorage.setItem('editorTextSettings', JSON.stringify(comprehensiveTextSettings)); localStorage.setItem('editorColorStates', JSON.stringify(colorPickerStates)); localStorage.setItem('editorBackgroundState', JSON.stringify(data.uiState.backgroundSelection)); console.log('saveBillboardData: All design data and UI state saved to localStorage'); } // Expose saveBillboardData to global scope for auto-save functionality window.saveBillboardData = saveBillboardData; // Function to proceed to checkout - Modified to show dialog function proceedToCheckout() { try { console.log('proceedToCheckout: Starting checkout process...'); // Force canvas update before saving if (window.updateEditorCanvasGlobal) { window.updateEditorCanvasGlobal(); console.log('proceedToCheckout: Editor canvas updated'); } else if (window.updateCanvas) { window.updateCanvas(); console.log('proceedToCheckout: Canvas updated'); } // Wait a moment for canvas to update, then save setTimeout(() => { // Save current billboard data saveBillboardData(); // Continue with checkout process - show dialog instead of redirect showCheckoutDialog(); }, 300); return; // Exit here, continue in showCheckoutDialog } catch (error) { console.error('proceedToCheckout: Error occurred:', error); alert('An error occurred while preparing checkout. Please try again.'); // Reset button state const button = document.querySelector('.submit-button'); if (button) { button.textContent = 'Continue to Checkout'; button.disabled = false; } } } // Show checkout dialog instead of redirecting function showCheckoutDialog() { try { console.log('showCheckoutDialog: Showing checkout dialog...'); // Save current billboard data again to ensure latest state saveBillboardData(); // Comprehensive data validation const requiredData = { purpose: localStorage.getItem('selectedPurpose'), location: localStorage.getItem('billboardLocation'), dates: localStorage.getItem('runDates'), state: localStorage.getItem('selectedState'), city: localStorage.getItem('selectedCity') }; // Professional validation with detailed checking const missingFields = []; const fieldLabels = { purpose: 'Purpose (Anniversary, Business, etc.)', location: 'Billboard Location', dates: 'Run Dates', state: 'State', city: 'City' }; Object.keys(requiredData).forEach(field => { const value = requiredData[field]; if (!value || value === 'Select a Purpose' || value === 'Not selected' || value.trim() === '' || value === 'undefined' || value === 'null') { missingFields.push(fieldLabels[field] || field); } }); console.log('showCheckoutDialog: Validation check:', { requiredData: requiredData, missingFields: missingFields }); if (missingFields.length > 0) { const message = `Please complete the following required information before proceeding to checkout:\n\n• ${missingFields.join('\n• ')}\n\nPlease go back to the form above and fill in all required fields.`; alert(message); console.warn('showCheckoutDialog: Missing required fields:', missingFields); // Scroll to top to help user see the form window.scrollTo({ top: 0, behavior: 'smooth' }); return; } // Professional canvas image capture with multiple fallbacks let canvasDataURL = null; const canvasSources = ['billboardCanvas', 'editorCanvas']; console.log('showCheckoutDialog: Attempting to capture canvas image...'); for (const canvasId of canvasSources) { const canvas = document.getElementById(canvasId); if (canvas) { try { // Ensure canvas has content before capturing const ctx = canvas.getContext('2d'); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const hasContent = imageData.data.some(pixel => pixel !== 0); if (hasContent) { canvasDataURL = canvas.toDataURL('image/png', 0.9); localStorage.setItem('adPreviewImage', canvasDataURL); localStorage.setItem('billboardCanvasImage', canvasDataURL); console.log(`showCheckoutDialog: Canvas image captured from ${canvasId} (${canvasDataURL.length} bytes)`); break; } else { console.warn(`showCheckoutDialog: Canvas ${canvasId} appears to be empty`); } } catch (canvasError) { console.warn(`showCheckoutDialog: Failed to get image from ${canvasId}:`, canvasError); } } } // If no canvas image, try to generate one from current design data if (!canvasDataURL) { console.log('showCheckoutDialog: No canvas image found, attempting to generate preview...'); canvasDataURL = generatePreviewFromDesignData(); if (canvasDataURL) { localStorage.setItem('adPreviewImage', canvasDataURL); localStorage.setItem('billboardCanvasImage', canvasDataURL); console.log('showCheckoutDialog: Generated preview from design data'); } } if (!canvasDataURL) { console.warn('showCheckoutDialog: No canvas image could be generated - will use design data for preview'); } // Store checkout timestamp for tracking localStorage.setItem('checkoutInitiated', new Date().toISOString()); // Log successful data preparation console.log('showCheckoutDialog: Data validation successful:', { purpose: requiredData.purpose, location: requiredData.location, dates: requiredData.dates, hasCanvasImage: !!canvasDataURL, adDesignData: !!localStorage.getItem('adDesignData') }); // Update dialog content with order summary updateCheckoutDialogContent(requiredData); // Show the dialog - FIXED: Use proper modal display method const dialog = document.getElementById('checkoutDialog'); if (dialog) { try { dialog.showModal(); // Use HTML5 dialog showModal method console.log('showCheckoutDialog: Dialog displayed using showModal()'); } catch (error) { // Fallback for browsers that don't support showModal dialog.style.display = 'flex'; dialog.style.position = 'fixed'; dialog.style.top = '50%'; dialog.style.left = '50%'; dialog.style.transform = 'translate(-50%, -50%)'; dialog.style.zIndex = '999999'; document.body.style.overflow = 'hidden'; console.log('showCheckoutDialog: Dialog displayed using fallback method'); } } else { console.error('showCheckoutDialog: Dialog element not found'); } // Reset button state const button = document.querySelector('.submit-button'); if (button) { button.textContent = 'Continue to Checkout'; button.disabled = false; } } catch (error) { console.error('showCheckoutDialog: Error occurred:', error); alert('An error occurred while preparing checkout. Please try again.'); // Reset button state const button = document.querySelector('.submit-button'); if (button) { button.textContent = 'Continue to Checkout'; button.disabled = false; } } } // Update checkout dialog content with order summary - matches original checkout logic function updateCheckoutDialogContent(requiredData) { try { // Update purpose const purposeElement = document.getElementById('dialogSummaryPurpose'); if (purposeElement) { purposeElement.textContent = requiredData.purpose || 'Not specified'; } // FIXED: Move fullLocation declaration outside if block to avoid ReferenceError // Create full location string like original checkout const fullLocation = [requiredData.location, requiredData.city, requiredData.state] .filter(item => item && item !== 'Not selected' && item !== 'Select State' && item !== 'Select City') .join(', '); // Update location - matches original checkout formatting const locationElement = document.getElementById('dialogSummaryLocation'); if (locationElement) { locationElement.textContent = fullLocation || requiredData.location || 'Not specified'; } // Update dates const datesElement = document.getElementById('dialogSummaryDates'); if (datesElement) { datesElement.textContent = requiredData.dates || 'Not specified'; } // Calculate duration and cost using original checkout logic const days = calculateDays(requiredData.dates); const costCalculation = calculateCost(days); const duration = calculateDuration(requiredData.dates); // Update duration display const durationElement = document.getElementById('dialogSummaryDuration'); if (durationElement) { durationElement.textContent = duration; } // Update cost display const costElement = document.getElementById('dialogSummaryCost'); if (costElement) { costElement.textContent = `$${costCalculation.total.toFixed(2)}`; } console.log('updateCheckoutDialogContent: Dialog content updated with:', { purpose: requiredData.purpose, location: fullLocation, dates: requiredData.dates, days: days, cost: costCalculation.total }); } catch (error) { console.error('updateCheckoutDialogContent: Error updating dialog content:', error); } } // Calculate days from date range - matches original checkout logic function calculateDays(dateRange) { if (!dateRange || dateRange === 'Not selected' || dateRange === 'Not specified') return 7; try { const dates = dateRange.split(' - '); if (dates.length === 2) { const start = new Date(dates[0]); const end = new Date(dates[1]); const diffTime = Math.abs(end - start); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); return diffDays + 1; // Include both start and end dates } } catch (e) { console.error('Error calculating days:', e); } return 7; // Default to 1 week } // Professional cost calculation - matches original checkout logic function calculateCost(days) { const baseCostPerDay = 79; const total = baseCostPerDay * days; return { baseCostPerDay, days, total }; } // Calculate duration display string function calculateDuration(dateString) { const days = calculateDays(dateString); return `${days} day${days !== 1 ? 's' : ''}`; } // Close background modal function closeBackgroundModal() { const dialog = document.getElementById('backgroundGraphicDialog'); if (dialog) { try { dialog.close(); console.log('closeBackgroundModal: Background modal closed using modal method'); } catch (error) { // Fallback for browsers that don't support close dialog.classList.remove('show'); dialog.style.display = 'none'; console.log('closeBackgroundModal: Background modal closed using fallback method'); } } } // Close checkout dialog - FIXED: Use proper modal close method function closeCheckoutDialog() { const dialog = document.getElementById('checkoutDialog'); if (dialog) { try { dialog.close(); // Use HTML5 dialog close method console.log('closeCheckoutDialog: Dialog closed using close()'); } catch (error) { // Fallback for browsers that don't support close dialog.style.display = 'none'; document.body.style.overflow = ''; // Restore background scrolling console.log('closeCheckoutDialog: Dialog closed using fallback method'); } } } // Open terms modal function openTermsModal() { const modal = document.getElementById('termsModal'); if (modal) { try { modal.showModal(); // Ensure proper centering modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.margin = 'auto'; console.log('openTermsModal: Terms modal opened using modal method'); } catch (error) { // Fallback for browsers that don't support showModal modal.style.display = 'block'; modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.margin = 'auto'; console.log('openTermsModal: Terms modal opened using fallback method'); } } } // Close terms modal function closeTermsModal() { const modal = document.getElementById('termsModal'); if (modal) { try { modal.close(); console.log('closeTermsModal: Terms modal closed using modal method'); } catch (error) { // Fallback for browsers that don't support close modal.style.display = 'none'; console.log('closeTermsModal: Terms modal closed using fallback method'); } } } // Accept terms and close modal function acceptTermsAndClose() { // Check the terms agreement checkbox const termsCheckbox = document.querySelector('input[name="dialog_terms_agreement"]'); if (termsCheckbox) { termsCheckbox.checked = true; console.log('acceptTermsAndClose: Terms checkbox checked'); } // Close the terms modal closeTermsModal(); } // Proceed to payment from dialog - matches original checkout functionality function proceedToPayment() { console.log('proceedToPayment: Validating checkout and proceeding to payment...'); // Define required checkboxes with their error messages (matching original) const requiredCheckboxes = [ { name: 'dialog_terms_agreement', message: 'Please agree to the terms and conditions before proceeding.' }, { name: 'dialog_content_compliance', message: 'Please confirm that you have not used inappropriate photos (smoking, drinking, hand symbols, too much skin).' }, { name: 'dialog_business_ad_compliance', message: 'Please confirm that your ad is not a business or promotional ad.' }, { name: 'dialog_ad_preview_confirmation', message: 'Please confirm that the preview below is exactly what your ad will look like.' }, { name: 'dialog_refund_policy_agreement', message: 'Please acknowledge the refund policy before proceeding.' } ]; // Validate all required checkboxes (matching original validation logic) for (const checkbox of requiredCheckboxes) { const element = document.querySelector(`input[name="${checkbox.name}"]`) || document.querySelector(`input[name="${checkbox.name}[]"]`); console.log(`${checkbox.name} checkbox found:`, element); console.log(`${checkbox.name} checkbox checked:`, element ? element.checked : 'not found'); if (!element || !element.checked) { alert(checkbox.message); return false; } } // Store checkout completion timestamp (matching original) localStorage.setItem('checkoutCompleted', new Date().toISOString()); // Store total cost for payment page (get from dialog summary) const totalCostElement = document.getElementById('dialogSummaryCost'); if (totalCostElement) { const totalCost = totalCostElement.textContent.replace('$', ''); localStorage.setItem('totalCost', totalCost); console.log('proceedToPayment: Stored total cost:', totalCost); } // Store email copy preference (matching original) const emailCopyCheckbox = document.querySelector('input[name="dialog_email_copy"]') || document.querySelector('input[name="dialog_email_copy[]"]'); localStorage.setItem('emailCopyRequested', emailCopyCheckbox ? emailCopyCheckbox.checked : false); console.log('proceedToPayment: Validation passed, redirecting to payment page...'); // Show loading state const proceedButton = document.querySelector('.checkout-dialog-btn.proceed'); if (proceedButton) { proceedButton.textContent = 'Redirecting to Payment...'; proceedButton.disabled = true; } // Close dialog closeCheckoutDialog(); // Redirect to payment page (using original URL) setTimeout(() => { window.location.href = 'https://www.borgesmedia.com/billboard-ad-pay/'; }, 500); } // Make functions globally accessible - FIXED: Added missing close functions window.closeBackgroundModal = closeBackgroundModal; window.proceedToCheckout = proceedToCheckout; window.closeCheckoutDialog = closeCheckoutDialog; window.openTermsModal = openTermsModal; window.closeTermsModal = closeTermsModal; window.acceptTermsAndClose = acceptTermsAndClose; window.proceedToPayment = proceedToPayment; // FIXED: Add missing close functions to global window object window.closeFontModal = window.closeFontModal || function() { const modal = document.getElementById('fontModal'); if (modal) { try { modal.close(); console.log('closeFontModal: Modal closed using modal method'); } catch (error) { modal.style.display = 'none'; console.log('closeFontModal: Modal hidden using fallback'); } } }; window.closeEditorFontModal = window.closeEditorFontModal || function() { const modal = document.getElementById('editorFontModal'); if (modal) { try { modal.close(); console.log('closeEditorFontModal: Modal closed using modal method'); } catch (error) { modal.style.display = 'none'; console.log('closeEditorFontModal: Modal hidden using fallback'); } } }; window.cancelImageResize = window.cancelImageResize || function() { const modal = document.getElementById('imageResizeModal'); if (modal) { try { modal.close(); console.log('cancelImageResize: Modal closed using modal method'); } catch (error) { modal.style.display = 'none'; console.log('cancelImageResize: Modal hidden using fallback'); } } }; // Professional debugging function for localStorage data window.debugCheckoutData = function() { console.log('=== CHECKOUT DATA DEBUG ==='); const allData = { selectedPurpose: localStorage.getItem('selectedPurpose'), selectedState: localStorage.getItem('selectedState'), selectedCity: localStorage.getItem('selectedCity'), billboardLocation: localStorage.getItem('billboardLocation'), runDates: localStorage.getItem('runDates'), adDesignData: localStorage.getItem('adDesignData'), adPreviewImage: !!localStorage.getItem('adPreviewImage'), checkoutInitiated: localStorage.getItem('checkoutInitiated') }; console.log('All localStorage data:', allData); const missingRequired = []; ['selectedPurpose', 'billboardLocation', 'runDates'].forEach(key => { if (!allData[key] || allData[key] === 'Select a Purpose' || allData[key] === 'Not selected') { missingRequired.push(key); } }); console.log('Missing required fields:', missingRequired); console.log('Ready for checkout:', missingRequired.length === 0); console.log('=== END DEBUG ==='); return allData; }; // Professional canvas preview generation from design data window.generatePreviewFromDesignData = function() { console.log('generatePreviewFromDesignData: Creating preview from design data...'); try { const designData = localStorage.getItem('adDesignData'); if (!designData) { console.log('generatePreviewFromDesignData: No design data available'); return null; } const data = JSON.parse(designData); console.log('generatePreviewFromDesignData: Using design data:', data); // Create a temporary canvas for preview generation const tempCanvas = document.createElement('canvas'); tempCanvas.width = 800; tempCanvas.height = 400; const ctx = tempCanvas.getContext('2d'); // Set background if (data.bgColor) { ctx.fillStyle = data.bgColor; ctx.fillRect(0, 0, tempCanvas.width, tempCanvas.height); } else { // Default gradient background const gradient = ctx.createLinearGradient(0, 0, tempCanvas.width, tempCanvas.height); gradient.addColorStop(0, '#0D7EE8'); gradient.addColorStop(1, '#0A6AC7'); ctx.fillStyle = gradient; ctx.fillRect(0, 0, tempCanvas.width, tempCanvas.height); } // Add text lines if available if (data.textLines) { // Clear any existing shadow settings to prevent accumulation ctx.shadowColor = 'transparent'; ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.fillStyle = 'white'; ctx.textAlign = 'center'; const lines = Object.values(data.textLines).filter(line => line && line.trim()); const lineHeight = 60; const startY = (tempCanvas.height - (lines.length * lineHeight)) / 2 + 30; lines.forEach((line, index) => { ctx.font = 'bold 48px Arial'; // Draw shadow manually to prevent accumulation ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; ctx.fillText(line, (tempCanvas.width / 2) + 2, (startY + (index * lineHeight)) + 2); // Draw main text ctx.fillStyle = 'white'; ctx.fillText(line, tempCanvas.width / 2, startY + (index * lineHeight)); }); } // Add template indicator if (data.template) { // Clear shadow settings for template indicator ctx.shadowColor = 'transparent'; ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.fillStyle = 'rgba(255, 255, 255, 0.8)'; ctx.font = '16px Arial'; ctx.textAlign = 'right'; ctx.fillText(`Template: ${data.template}`, tempCanvas.width - 20, tempCanvas.height - 20); } const previewDataURL = tempCanvas.toDataURL('image/png', 0.8); console.log('generatePreviewFromDesignData: Preview generated successfully'); return previewDataURL; } catch (error) { console.error('generatePreviewFromDesignData: Error generating preview:', error); return null; } }; // Professional state restoration function window.restoreBillboardDesign = function() { console.log('restoreBillboardDesign: Starting state restoration...'); try { const savedData = localStorage.getItem('adDesignData'); if (!savedData) { console.log('restoreBillboardDesign: No saved design data found'); return false; } const designData = JSON.parse(savedData); console.log('restoreBillboardDesign: Found saved design data:', designData); // Restore text lines to both regular and editor inputs if (designData.textLines) { Object.keys(designData.textLines).forEach(lineKey => { const element = document.getElementById(lineKey); if (element && designData.textLines[lineKey]) { element.value = designData.textLines[lineKey]; console.log(`restoreBillboardDesign: Restored ${lineKey} = "${designData.textLines[lineKey]}"`); } }); } // Restore editor text lines specifically if (designData.editorTextLines) { Object.keys(designData.editorTextLines).forEach(editorLineKey => { const element = document.getElementById(editorLineKey); if (element && designData.editorTextLines[editorLineKey]) { element.value = designData.editorTextLines[editorLineKey]; console.log(`restoreBillboardDesign: Restored editor ${editorLineKey} = "${designData.editorTextLines[editorLineKey]}"`); } }); } else if (designData.textLines) { // Fallback: map regular text lines to editor inputs ['line1', 'line2', 'line3', 'line4'].forEach((lineKey, index) => { if (designData.textLines[lineKey]) { const editorElement = document.getElementById(`editorLine${index + 1}`); if (editorElement) { editorElement.value = designData.textLines[lineKey]; console.log(`restoreBillboardDesign: Mapped ${lineKey} to editorLine${index + 1} = "${designData.textLines[lineKey]}"`); } } }); } // Restore global variables if they exist in scope if (typeof currentTemplate !== 'undefined' && designData.template) { currentTemplate = designData.template; } if (typeof currentBgColor !== 'undefined' && designData.bgColor) { currentBgColor = designData.bgColor; } if (typeof currentBgGraphic !== 'undefined' && designData.bgGraphic) { currentBgGraphic = designData.bgGraphic; } // Note: textSettings is const, so we can't reassign it directly // Instead, we'll update the individual properties or use the global state if (typeof textSettings !== 'undefined' && designData.textSettings) { // Update individual properties of textSettings object Object.keys(designData.textSettings).forEach(lineId => { if (textSettings[lineId]) { Object.assign(textSettings[lineId], designData.textSettings[lineId]); } }); console.log('restoreBillboardDesign: Text settings properties updated'); } if (typeof uploadedImage !== 'undefined' && designData.uploadedImageData) { // Restore uploaded image const img = new Image(); img.onload = function() { uploadedImage = img; console.log('restoreBillboardDesign: Uploaded image restored'); // Redraw canvas after image loads if (window.updateCanvas) { updateCanvas(); } }; img.src = designData.uploadedImageData; } // Restore canvas if available if (designData.canvasImage) { const canvas = document.getElementById('billboardCanvas'); if (canvas) { const ctx = canvas.getContext('2d'); const img = new Image(); img.onload = function() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0); console.log('restoreBillboardDesign: Canvas image restored'); }; img.src = designData.canvasImage; } } // Update hidden fields const selectedTemplateField = document.getElementById('selectedTemplate'); if (selectedTemplateField && designData.template) { selectedTemplateField.value = designData.template; } const billboardDataField = document.getElementById('billboardData'); if (billboardDataField) { billboardDataField.value = JSON.stringify(designData); } // Special handling for all template types with comprehensive UI restoration if (designData.template && (designData.template.includes('anniversary') || designData.template.includes('benefit') || designData.template.includes('christian') || designData.template.includes('graduation') || designData.template.includes('holiday') || designData.template.includes('local-school') || designData.template.includes('love') || designData.template.includes('marry-me') || designData.template.includes('newborn') || designData.template.includes('obituary') || designData.template.includes('other') || designData.template.includes('pet') || designData.template.includes('prayer') || designData.template.includes('retirement'))) { console.log('restoreBillboardDesign: Detected template, restoring complete editor state...', designData.template); // Restore template editor state - BOTH global and local variables if (window.editorState) { // Set global state based on template type if (designData.template.includes('anniversary')) { window.editorState.currentAnniversaryTemplate = designData.template; window.editorState.selectedAnniversaryBackground = designData.bgGraphic || 'Anniversary-1'; } else if (designData.template.includes('benefit')) { window.editorState.currentBenefitTemplate = designData.template; window.editorState.selectedBenefitBackground = designData.bgGraphic || 'Benefit-3'; } else if (designData.template.includes('christian')) { window.editorState.currentChristianTemplate = designData.template; window.editorState.selectedChristianBackground = designData.bgGraphic || 'Christian-1'; } else if (designData.template.includes('graduation')) { window.editorState.currentGraduationTemplate = designData.template; window.editorState.selectedGraduationBackground = designData.bgGraphic || 'Graduation-1'; } else if (designData.template.includes('holiday')) { window.editorState.currentHolidayTemplate = designData.template; window.editorState.selectedHolidayBackground = designData.bgGraphic || 'Holiday-1'; } else if (designData.template.includes('local-school')) { window.editorState.currentLocalSchoolTemplate = designData.template; window.editorState.selectedLocalSchoolBackground = designData.bgGraphic || 'Local-Schools-1'; } else if (designData.template.includes('love')) { window.editorState.currentLoveTemplate = designData.template; window.editorState.selectedLoveBackground = designData.bgGraphic || 'Love-6'; } else if (designData.template.includes('marry-me')) { window.editorState.currentMarryMeTemplate = designData.template; window.editorState.selectedMarryMeBackground = designData.bgGraphic || 'Marry-Me-5'; } else if (designData.template.includes('newborn')) { window.editorState.currentNewbornTemplate = designData.template; window.editorState.selectedNewbornBackground = designData.bgGraphic || 'New-Born-1'; } else if (designData.template.includes('obituary')) { window.editorState.currentObituaryTemplate = designData.template; window.editorState.selectedObituaryBackground = designData.bgGraphic || 'Obituary-11'; } else if (designData.template.includes('other')) { window.editorState.currentOtherTemplate = designData.template; window.editorState.selectedOtherBackground = designData.bgGraphic || 'Other-2'; } else if (designData.template.includes('pet')) { window.editorState.currentPetTemplate = designData.template; window.editorState.selectedPetBackground = designData.bgGraphic || 'Pet-11'; } else if (designData.template.includes('prayer')) { window.editorState.currentPrayerTemplate = designData.template; window.editorState.selectedPrayerBackground = designData.bgGraphic || 'Prayer-2'; } else if (designData.template.includes('retirement')) { window.editorState.currentRetirementTemplate = designData.template; window.editorState.selectedRetirementBackground = designData.bgGraphic || 'Retirement-9'; } else if (designData.template.includes('wedding')) { window.editorState.currentWeddingTemplate = designData.template; window.editorState.selectedWeddingBackground = designData.bgGraphic || 'Wedding-10'; } else if (designData.template.includes('welcome')) { window.editorState.currentWelcomeTemplate = designData.template; window.editorState.selectedWelcomeBackground = designData.bgGraphic || 'Welcome-10'; } window.editorState.selectedBackgroundType = designData.bgType || 'image'; window.editorState.selectedBackgroundColor = designData.bgColor || '#ff0000'; window.editorState.isEditorMode = true; // CRITICAL: Also set local variables that the canvas functions depend on if (designData.template.includes('anniversary')) { if (typeof currentAnniversaryTemplate !== 'undefined') { currentAnniversaryTemplate = designData.template; } if (typeof selectedAnniversaryBackground !== 'undefined') { selectedAnniversaryBackground = designData.bgGraphic || 'Anniversary-1'; } } else if (designData.template.includes('benefit')) { if (typeof currentBenefitTemplate !== 'undefined') { currentBenefitTemplate = designData.template; } if (typeof selectedBenefitBackground !== 'undefined') { selectedBenefitBackground = designData.bgGraphic || 'Benefit-3'; } } else if (designData.template.includes('christian')) { if (typeof currentChristianTemplate !== 'undefined') { currentChristianTemplate = designData.template; } if (typeof selectedChristianBackground !== 'undefined') { selectedChristianBackground = designData.bgGraphic || 'Christian-1'; } } else if (designData.template.includes('graduation')) { if (typeof currentGraduationTemplate !== 'undefined') { currentGraduationTemplate = designData.template; } if (typeof selectedGraduationBackground !== 'undefined') { selectedGraduationBackground = designData.bgGraphic || 'Graduation-1'; } } else if (designData.template.includes('holiday')) { if (typeof currentHolidayTemplate !== 'undefined') { currentHolidayTemplate = designData.template; } if (typeof selectedHolidayBackground !== 'undefined') { selectedHolidayBackground = designData.bgGraphic || 'Holiday-1'; } } else if (designData.template.includes('local-school')) { if (typeof currentLocalSchoolTemplate !== 'undefined') { currentLocalSchoolTemplate = designData.template; } if (typeof selectedLocalSchoolBackground !== 'undefined') { selectedLocalSchoolBackground = designData.bgGraphic || 'Local-Schools-1'; } } else if (designData.template.includes('love')) { if (typeof currentLoveTemplate !== 'undefined') { currentLoveTemplate = designData.template; } if (typeof selectedLoveBackground !== 'undefined') { selectedLoveBackground = designData.bgGraphic || 'Love-6'; } } else if (designData.template.includes('marry-me')) { if (typeof currentMarryMeTemplate !== 'undefined') { currentMarryMeTemplate = designData.template; } if (typeof selectedMarryMeBackground !== 'undefined') { selectedMarryMeBackground = designData.bgGraphic || 'Marry-Me-5'; } } else if (designData.template.includes('newborn')) { if (typeof currentNewbornTemplate !== 'undefined') { currentNewbornTemplate = designData.template; } if (typeof selectedNewbornBackground !== 'undefined') { selectedNewbornBackground = designData.bgGraphic || 'New-Born-1'; } } else if (designData.template.includes('obituary')) { if (typeof currentObituaryTemplate !== 'undefined') { currentObituaryTemplate = designData.template; } if (typeof selectedObituaryBackground !== 'undefined') { selectedObituaryBackground = designData.bgGraphic || 'Obituary-11'; } } else if (designData.template.includes('other')) { if (typeof currentOtherTemplate !== 'undefined') { currentOtherTemplate = designData.template; } if (typeof selectedOtherBackground !== 'undefined') { selectedOtherBackground = designData.bgGraphic || 'Other-2'; } } else if (designData.template.includes('pet')) { if (typeof currentPetTemplate !== 'undefined') { currentPetTemplate = designData.template; } if (typeof selectedPetBackground !== 'undefined') { selectedPetBackground = designData.bgGraphic || 'Pet-11'; } } else if (designData.template.includes('prayer')) { if (typeof currentPrayerTemplate !== 'undefined') { currentPrayerTemplate = designData.template; } if (typeof selectedPrayerBackground !== 'undefined') { selectedPrayerBackground = designData.bgGraphic || 'Prayer-2'; } } else if (designData.template.includes('retirement')) { if (typeof currentRetirementTemplate !== 'undefined') { currentRetirementTemplate = designData.template; } if (typeof selectedRetirementBackground !== 'undefined') { selectedRetirementBackground = designData.bgGraphic || 'Retirement-9'; } } else if (designData.template.includes('wedding')) { if (typeof currentWeddingTemplate !== 'undefined') { currentWeddingTemplate = designData.template; } if (typeof selectedWeddingBackground !== 'undefined') { selectedWeddingBackground = designData.bgGraphic || 'Wedding-10'; } } else if (designData.template.includes('welcome')) { if (typeof currentWelcomeTemplate !== 'undefined') { currentWelcomeTemplate = designData.template; } if (typeof selectedWelcomeBackground !== 'undefined') { selectedWelcomeBackground = designData.bgGraphic || 'Welcome-10'; } } if (typeof selectedBackgroundType !== 'undefined') { selectedBackgroundType = designData.bgType || 'image'; } if (typeof selectedBackgroundColor !== 'undefined') { selectedBackgroundColor = designData.bgColor || '#ff0000'; } if (typeof isEditorMode !== 'undefined') { isEditorMode = true; } console.log('restoreBillboardDesign: Both global and local editor state restored'); // Force restore local variables using the global function if (window.forceRestoreLocalVariables) { window.forceRestoreLocalVariables(designData); } // Restore editor text lines if (designData.textLines) { ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4'].forEach((editorId, index) => { const lineKey = `line${index + 1}`; const editorElement = document.getElementById(editorId); if (editorElement && designData.textLines[lineKey]) { editorElement.value = designData.textLines[lineKey]; console.log(`restoreBillboardDesign: Restored ${editorId} = "${designData.textLines[lineKey]}"`); } }); } // Restore color picker button states if (designData.uiState && designData.uiState.colorPickerStates) { Object.keys(designData.uiState.colorPickerStates).forEach(btnId => { const btn = document.getElementById(btnId); if (btn) { btn.style.backgroundColor = designData.uiState.colorPickerStates[btnId]; console.log(`restoreBillboardDesign: Restored color picker ${btnId} = ${designData.uiState.colorPickerStates[btnId]}`); } }); } // Restore text settings to global state and apply to UI if (designData.textSettings) { window.editorState.editorTextSettings = designData.textSettings; // Apply text settings to color picker buttons Object.keys(designData.textSettings).forEach(lineId => { const settings = designData.textSettings[lineId]; const lineNum = lineId.replace('editorLine', ''); const colorBtn = document.getElementById(`editorColorBtn${lineNum}`); if (colorBtn && settings.color) { colorBtn.style.backgroundColor = settings.color; console.log(`restoreBillboardDesign: Restored color picker ${lineId} = ${settings.color}`); } }); console.log('restoreBillboardDesign: Restored text settings to global state and UI'); } // Restore background selection visual state if (designData.bgGraphic) { // Mark the correct background as selected setTimeout(() => { const backgroundOptions = document.querySelectorAll('.stockImage-bg-option'); backgroundOptions.forEach(option => { option.classList.remove('selected'); if (option.dataset.background === designData.bgGraphic) { option.classList.add('selected'); console.log(`restoreBillboardDesign: Selected background graphic ${designData.bgGraphic}`); } }); }, 200); } // Restore background type selection if (designData.bgType) { setTimeout(() => { const typeButtons = document.querySelectorAll('.background-type-btn'); typeButtons.forEach(btn => { btn.classList.remove('active'); if (btn.dataset.type === designData.bgType) { btn.classList.add('active'); console.log(`restoreBillboardDesign: Selected background type ${designData.bgType}`); } }); }, 200); } // Restore uploaded image if available - ENHANCED VERSION if (designData.uploadedImageData) { console.log('restoreBillboardDesign: Starting uploaded image restoration...'); const img = new Image(); img.crossOrigin = 'anonymous'; // Handle CORS issues img.onload = function() { // Set in global state window.editorState.editorUploadedImage = img; // Also set in local variable if accessible if (typeof editorUploadedImage !== 'undefined') { editorUploadedImage = img; } console.log('restoreBillboardDesign: Uploaded image loaded and set in both global and local state'); // Update upload container visual state const uploadContainer = document.getElementById('editorPhotoUpload'); if (uploadContainer) { uploadContainer.style.border = '2px solid #28a745'; uploadContainer.style.backgroundColor = '#d4edda'; const uploadText = uploadContainer.querySelector('.upload-text'); if (uploadText) { uploadText.textContent = 'Photo uploaded ✓ Click to change'; uploadText.style.color = '#155724'; } } // Force sync editor state if (window.syncEditorState) { window.syncEditorState(); } // Update canvas after image loads with multiple attempts setTimeout(() => { if (window.updateEditorCanvasGlobal) { window.updateEditorCanvasGlobal(); console.log('restoreBillboardDesign: Canvas updated after image load (attempt 1)'); } }, 100); setTimeout(() => { if (window.updateEditorCanvasGlobal) { window.updateEditorCanvasGlobal(); console.log('restoreBillboardDesign: Canvas updated after image load (attempt 2)'); } }, 300); }; img.onerror = function() { console.error('restoreBillboardDesign: Failed to load uploaded image:', designData.uploadedImageData.substring(0, 100) + '...'); }; img.src = designData.uploadedImageData; } // Restore template selection visual state if (designData.template) { setTimeout(() => { let templateSelector = '.anniversary-template-card'; if (designData.template.includes('benefit')) { templateSelector = '.benefit-template-card'; } else if (designData.template.includes('christian')) { templateSelector = '.christian-template-card'; } else if (designData.template.includes('graduation')) { templateSelector = '.graduation-template-card'; } else if (designData.template.includes('holiday')) { templateSelector = '.holiday-template-card'; } else if (designData.template.includes('local-school')) { templateSelector = '.local-school-template-card'; } else if (designData.template.includes('love')) { templateSelector = '.love-template-card'; } else if (designData.template.includes('marry-me')) { templateSelector = '.marry-me-template-card'; } else if (designData.template.includes('newborn')) { templateSelector = '.newborn-template-card'; } else if (designData.template.includes('obituary')) { templateSelector = '.obituary-template-card'; } else if (designData.template.includes('other')) { templateSelector = '.other-template-card'; } else if (designData.template.includes('pet')) { templateSelector = '.pet-template-card'; } else if (designData.template.includes('prayer')) { templateSelector = '.prayer-template-card'; } else if (designData.template.includes('retirement')) { templateSelector = '.retirement-template-card'; } else if (designData.template.includes('wedding')) { templateSelector = '.wedding-template-card'; } const templateCards = document.querySelectorAll(templateSelector); templateCards.forEach(card => { card.classList.remove('selected'); if (card.dataset.template === designData.template) { card.classList.add('selected'); console.log(`restoreBillboardDesign: Selected template ${designData.template}`); } }); }, 200); } // Force canvas update with multiple attempts to ensure rendering const forceCanvasUpdate = () => { console.log('restoreBillboardDesign: Forcing canvas update...'); // Sync editor state first if (window.syncEditorState) { window.syncEditorState(); } // Try multiple canvas update methods if (window.updateEditorCanvasGlobal) { window.updateEditorCanvasGlobal(); console.log('restoreBillboardDesign: Called updateEditorCanvasGlobal'); } if (window.updateEditorCanvas) { window.updateEditorCanvas(); console.log('restoreBillboardDesign: Called updateEditorCanvas'); } if (window.updateCanvas) { window.updateCanvas(); console.log('restoreBillboardDesign: Called updateCanvas'); } // Direct canvas update as fallback - ENHANCED VERSION const canvas = document.getElementById('editorCanvas'); if (canvas && window.editorState) { const ctx = canvas.getContext('2d'); if (ctx) { console.log('restoreBillboardDesign: Starting direct canvas update fallback'); // Set canvas size to match container const container = canvas.parentElement; if (container) { const containerRect = container.getBoundingClientRect(); canvas.width = containerRect.width; canvas.height = containerRect.height; } // Clear and redraw ctx.clearRect(0, 0, canvas.width, canvas.height); // Get template information based on template type let template = null; if (window.editorState.currentAnniversaryTemplate) { template = window.editorState.anniversaryTemplates && window.editorState.anniversaryTemplates[window.editorState.currentAnniversaryTemplate]; } else if (window.editorState.currentBenefitTemplate) { template = window.editorState.benefitTemplates && window.editorState.benefitTemplates[window.editorState.currentBenefitTemplate]; } else if (window.editorState.currentChristianTemplate) { template = window.editorState.christianTemplates && window.editorState.christianTemplates[window.editorState.currentChristianTemplate]; } else if (window.editorState.currentGraduationTemplate) { template = window.editorState.graduationTemplates && window.editorState.graduationTemplates[window.editorState.currentGraduationTemplate]; } else if (window.editorState.currentHolidayTemplate) { template = window.editorState.holidayTemplates && window.editorState.holidayTemplates[window.editorState.currentHolidayTemplate]; } else if (window.editorState.currentLocalSchoolTemplate) { template = window.editorState.localSchoolTemplates && window.editorState.localSchoolTemplates[window.editorState.currentLocalSchoolTemplate]; } else if (window.editorState.currentLoveTemplate) { template = window.editorState.loveTemplates && window.editorState.loveTemplates[window.editorState.currentLoveTemplate]; } else if (window.editorState.currentMarryMeTemplate) { template = window.editorState.marryMeTemplates && window.editorState.marryMeTemplates[window.editorState.currentMarryMeTemplate]; } else if (window.editorState.currentNewbornTemplate) { template = window.editorState.newbornTemplates && window.editorState.newbornTemplates[window.editorState.currentNewbornTemplate]; } else if (window.editorState.currentObituaryTemplate) { template = window.editorState.obituaryTemplates && window.editorState.obituaryTemplates[window.editorState.currentObituaryTemplate]; } else if (window.editorState.currentOtherTemplate) { template = window.editorState.otherTemplates && window.editorState.otherTemplates[window.editorState.currentOtherTemplate]; } else if (window.editorState.currentPetTemplate) { template = window.editorState.petTemplates && window.editorState.petTemplates[window.editorState.currentPetTemplate]; } else if (window.editorState.currentPrayerTemplate) { template = window.editorState.prayerTemplates && window.editorState.prayerTemplates[window.editorState.currentPrayerTemplate]; } else if (window.editorState.currentRetirementTemplate) { template = window.editorState.retirementTemplates && window.editorState.retirementTemplates[window.editorState.currentRetirementTemplate]; } else if (window.editorState.currentWeddingTemplate) { template = window.editorState.weddingTemplates && window.editorState.weddingTemplates[window.editorState.currentWeddingTemplate]; } else if (window.editorState.currentWelcomeTemplate) { template = window.editorState.welcomeTemplates && window.editorState.welcomeTemplates[window.editorState.currentWelcomeTemplate]; } // Draw background if (window.editorState.selectedBackgroundType === 'color') { ctx.fillStyle = window.editorState.selectedBackgroundColor; ctx.fillRect(0, 0, canvas.width, canvas.height); console.log('restoreBillboardDesign: Color background drawn'); // Draw text and uploaded image immediately for color background drawEditorTextDirect(ctx, canvas); drawEditorImageDirect(ctx, canvas, template); } else if (window.editorState.selectedAnniversaryBackground || window.editorState.selectedBenefitBackground || window.editorState.selectedChristianBackground || window.editorState.selectedGraduationBackground || window.editorState.selectedHolidayBackground || window.editorState.selectedLocalSchoolBackground || window.editorState.selectedLoveBackground || window.editorState.selectedMarryMeBackground || window.editorState.selectedNewbornBackground || window.editorState.selectedObituaryBackground || window.editorState.selectedOtherBackground || window.editorState.selectedPetBackground || window.editorState.selectedPrayerBackground || window.editorState.selectedRetirementBackground || window.editorState.selectedWeddingBackground || window.editorState.selectedWelcomeBackground) { // Try to load and draw background image const bgImg = new Image(); bgImg.crossOrigin = 'anonymous'; bgImg.onload = function() { ctx.drawImage(bgImg, 0, 0, canvas.width, canvas.height); console.log('restoreBillboardDesign: Background image drawn'); // Draw text and uploaded image after background loads drawEditorTextDirect(ctx, canvas); drawEditorImageDirect(ctx, canvas, template); }; bgImg.onerror = function() { console.error('restoreBillboardDesign: Failed to load background image, drawing text anyway'); // Still draw text and uploaded image even if background fails drawEditorTextDirect(ctx, canvas); drawEditorImageDirect(ctx, canvas, template); }; // Try multiple possible paths for background image const currentBg = window.editorState.selectedAnniversaryBackground || window.editorState.selectedBenefitBackground || window.editorState.selectedChristianBackground || window.editorState.selectedGraduationBackground || window.editorState.selectedHolidayBackground || window.editorState.selectedLocalSchoolBackground || window.editorState.selectedLoveBackground || window.editorState.selectedMarryMeBackground || window.editorState.selectedNewbornBackground || window.editorState.selectedObituaryBackground || window.editorState.selectedOtherBackground || window.editorState.selectedPetBackground || window.editorState.selectedPrayerBackground || window.editorState.selectedRetirementBackground || window.editorState.selectedWeddingBackground || window.editorState.selectedWelcomeBackground; const bgPaths = [ `https://www.borgesmedia.com/wp-content/uploads/2025/06/${currentBg}.png`, `/wp-content/uploads/2024/12/${currentBg}.jpg`, `/wp-content/uploads/2025/06/${currentBg}.png` ]; let pathIndex = 0; const tryNextPath = () => { if (pathIndex { console.warn(`restoreBillboardDesign: Failed to load background from ${bgImg.src}`); if (pathIndex { console.log('restoreBillboardDesign: Final comprehensive canvas update'); // Force local variable restoration one more time if (window.forceRestoreLocalVariables) { window.forceRestoreLocalVariables(designData); } // Force canvas update forceCanvasUpdate(); // Comprehensive restoration verification const canvas = document.getElementById('editorCanvas'); if (canvas) { const ctx = canvas.getContext('2d'); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const isBlank = imageData.data.every((value, index) => index % 4 === 3 || value === 0); // Verify text restoration const textRestored = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4'].some(lineId => { const input = document.getElementById(lineId); return input && input.value && input.value.trim(); }); // Verify image restoration const imageRestored = window.editorState && window.editorState.editorUploadedImage; const uploadContainerUpdated = document.getElementById('editorPhotoUpload') && document.getElementById('editorPhotoUpload').style.border.includes('28a745'); console.log('restoreBillboardDesign: Restoration verification:', { canvasBlank: isBlank, textRestored: textRestored, imageRestored: !!imageRestored, uploadContainerUpdated: uploadContainerUpdated, hasUploadedImageData: !!designData.uploadedImageData }); if (isBlank) { console.warn('restoreBillboardDesign: Canvas appears blank, attempting emergency restoration'); // Emergency restoration attempt setTimeout(() => { if (window.updateEditorCanvasGlobal) { window.updateEditorCanvasGlobal(); } // If still blank after emergency restoration, try direct drawing setTimeout(() => { const canvas2 = document.getElementById('editorCanvas'); if (canvas2) { const ctx2 = canvas2.getContext('2d'); const imageData2 = ctx2.getImageData(0, 0, canvas2.width, canvas2.height); const stillBlank = imageData2.data.every((value, index) => index % 4 === 3 || value === 0); if (stillBlank) { console.warn('restoreBillboardDesign: Emergency restoration failed, attempting direct drawing'); drawEditorTextDirect(ctx2, canvas2); if (window.editorState.editorUploadedImage) { let template = null; if (window.editorState.currentAnniversaryTemplate) { template = window.editorState.anniversaryTemplates && window.editorState.anniversaryTemplates[window.editorState.currentAnniversaryTemplate]; } else if (window.editorState.currentBenefitTemplate) { template = window.editorState.benefitTemplates && window.editorState.benefitTemplates[window.editorState.currentBenefitTemplate]; } else if (window.editorState.currentChristianTemplate) { template = window.editorState.christianTemplates && window.editorState.christianTemplates[window.editorState.currentChristianTemplate]; } else if (window.editorState.currentGraduationTemplate) { template = window.editorState.graduationTemplates && window.editorState.graduationTemplates[window.editorState.currentGraduationTemplate]; } else if (window.editorState.currentHolidayTemplate) { template = window.editorState.holidayTemplates && window.editorState.holidayTemplates[window.editorState.currentHolidayTemplate]; } else if (window.editorState.currentLocalSchoolTemplate) { template = window.editorState.localSchoolTemplates && window.editorState.localSchoolTemplates[window.editorState.currentLocalSchoolTemplate]; } else if (window.editorState.currentLoveTemplate) { template = window.editorState.loveTemplates && window.editorState.loveTemplates[window.editorState.currentLoveTemplate]; } else if (window.editorState.currentMarryMeTemplate) { template = window.editorState.marryMeTemplates && window.editorState.marryMeTemplates[window.editorState.currentMarryMeTemplate]; } else if (window.editorState.currentNewbornTemplate) { template = window.editorState.newbornTemplates && window.editorState.newbornTemplates[window.editorState.currentNewbornTemplate]; } else if (window.editorState.currentObituaryTemplate) { template = window.editorState.obituaryTemplates && window.editorState.obituaryTemplates[window.editorState.currentObituaryTemplate]; } else if (window.editorState.currentOtherTemplate) { template = window.editorState.otherTemplates && window.editorState.otherTemplates[window.editorState.currentOtherTemplate]; } else if (window.editorState.currentPetTemplate) { template = window.editorState.petTemplates && window.editorState.petTemplates[window.editorState.currentPetTemplate]; } else if (window.editorState.currentPrayerTemplate) { template = window.editorState.prayerTemplates && window.editorState.prayerTemplates[window.editorState.currentPrayerTemplate]; } else if (window.editorState.currentRetirementTemplate) { template = window.editorState.retirementTemplates && window.editorState.retirementTemplates[window.editorState.currentRetirementTemplate]; } else if (window.editorState.currentWeddingTemplate) { template = window.editorState.weddingTemplates && window.editorState.weddingTemplates[window.editorState.currentWeddingTemplate]; } else if (window.editorState.currentWelcomeTemplate) { template = window.editorState.welcomeTemplates && window.editorState.welcomeTemplates[window.editorState.currentWelcomeTemplate]; } drawEditorImageDirect(ctx2, canvas2, template); } } } }, 300); }, 200); } else { console.log('restoreBillboardDesign: Canvas restoration successful - content detected'); // Additional verification for image restoration if (designData.uploadedImageData && !imageRestored) { console.warn('restoreBillboardDesign: Image data exists but image not restored, attempting image restoration'); // Retry image restoration const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function() { window.editorState.editorUploadedImage = img; if (window.syncEditorState) { window.syncEditorState(); } if (window.updateEditorCanvasGlobal) { window.updateEditorCanvasGlobal(); } console.log('restoreBillboardDesign: Image restoration retry completed'); }; img.src = designData.uploadedImageData; } } } }, 2000); } } console.log('restoreBillboardDesign: State restoration completed successfully'); return true; } catch (error) { console.error('restoreBillboardDesign: Error during restoration:', error); return false; } }; // Helper function to draw editor text on canvas function drawEditorText(ctx, canvas) { if (!window.editorState || !window.editorState.editorTextSettings) return; const textSettings = window.editorState.editorTextSettings; const lineHeight = 60; const startY = 100; ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4'].forEach((lineId, index) => { const input = document.getElementById(lineId); const settings = textSettings[lineId]; if (input && input.value && settings) { const text = input.value; const y = startY + (index * lineHeight); // Set font ctx.font = `${settings.fontSize}px ${settings.fontFamily}`; ctx.textAlign = 'center'; // Draw shadow if enabled if (settings.shadow) { ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; ctx.fillText(text, canvas.width / 2 + settings.shadowWidth, y + settings.shadowWidth); } // Draw main text ctx.fillStyle = settings.color; ctx.fillText(text, canvas.width / 2, y); } }); // Draw uploaded image if available if (window.editorState.editorUploadedImage) { const img = window.editorState.editorUploadedImage; const imgWidth = 200; const imgHeight = 150; const imgX = canvas.width - imgWidth - 20; const imgY = canvas.height - imgHeight - 20; ctx.drawImage(img, imgX, imgY, imgWidth, imgHeight); } } // Direct text drawing function for fallback canvas updates function drawEditorTextDirect(ctx, canvas) { if (!window.editorState || !window.editorState.editorTextSettings) { console.log('drawEditorTextDirect: No editor state or text settings available'); return; } const textSettings = window.editorState.editorTextSettings; console.log('drawEditorTextDirect: Drawing text with settings:', textSettings); ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4'].forEach((lineId, index) => { const input = document.getElementById(lineId); const settings = textSettings[lineId]; if (input && input.value && input.value.trim() && settings) { const text = input.value.trim(); // Use template positioning if available, otherwise use simple positioning const template = window.editorState.anniversaryTemplates && window.editorState.anniversaryTemplates[window.editorState.currentAnniversaryTemplate]; let x, y; if (template && template.textPositions && template.textPositions[index]) { const pos = template.textPositions[index]; const scaleX = canvas.width / 800; const scaleY = canvas.height / 400; x = pos.x * scaleX; y = pos.y * scaleY; ctx.textAlign = pos.align || 'center'; } else { // Fallback positioning x = canvas.width / 2; y = 100 + (index * 60); ctx.textAlign = 'center'; } // Scale font size const scaledFontSize = settings.fontSize * (canvas.width / 800); ctx.font = `${scaledFontSize}px ${settings.fontFamily}`; // Draw shadow if enabled if (settings.shadow) { const shadowWidth = settings.shadowWidth || 4; const scaledShadowWidth = shadowWidth * (canvas.width / 800); ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'; ctx.fillText(text, x + scaledShadowWidth, y + scaledShadowWidth); } // Draw main text ctx.fillStyle = settings.color; ctx.fillText(text, x, y); console.log(`drawEditorTextDirect: Drew text "${text}" at (${x}, ${y}) with color ${settings.color}`); } }); } // Direct image drawing function for fallback canvas updates function drawEditorImageDirect(ctx, canvas, template) { if (!window.editorState.editorUploadedImage) { console.log('drawEditorImageDirect: No uploaded image available'); return; } const img = window.editorState.editorUploadedImage; console.log('drawEditorImageDirect: Drawing uploaded image'); if (template && template.imagePosition) { // Use template positioning const pos = template.imagePosition; const scaleX = canvas.width / 800; const scaleY = canvas.height / 400; const x = pos.x * scaleX; const y = pos.y * scaleY; const width = pos.width * scaleX; const height = pos.height * scaleY; if (template.type === 'centered-image') { // Draw circular image ctx.save(); ctx.beginPath(); ctx.arc(x + width/2, y + height/2, width/2, 0, 2 * Math.PI); ctx.clip(); ctx.drawImage(img, x, y, width, height); ctx.restore(); // Draw white border ctx.beginPath(); ctx.arc(x + width/2, y + height/2, width/2, 0, 2 * Math.PI); ctx.strokeStyle = 'white'; ctx.lineWidth = 6 * (canvas.width / 800); ctx.stroke(); } else { // Draw rectangular image ctx.drawImage(img, x, y, width, height); } console.log(`drawEditorImageDirect: Drew image at (${x}, ${y}) with size ${width}x${height}`); } else { // Fallback positioning - bottom right corner const imgWidth = 200 * (canvas.width / 800); const imgHeight = 150 * (canvas.height / 400); const imgX = canvas.width - imgWidth - 20; const imgY = canvas.height - imgHeight - 20; ctx.drawImage(img, imgX, imgY, imgWidth, imgHeight); console.log(`drawEditorImageDirect: Drew image at fallback position (${imgX}, ${imgY})`); } } // Professional comprehensive UI restoration function window.restoreCompleteUIState = function() { console.log('restoreCompleteUIState: Starting comprehensive UI restoration...'); try { const savedData = localStorage.getItem('adDesignData'); if (!savedData) { console.log('restoreCompleteUIState: No saved design data found'); return false; } const designData = JSON.parse(savedData); console.log('restoreCompleteUIState: Restoring UI from data:', designData); // Restore background graphic selection visual state if (designData.bgGraphic) { const backgroundOptions = document.querySelectorAll('.stockImage-bg-option'); backgroundOptions.forEach(option => { option.classList.remove('selected'); if (option.dataset.background === designData.bgGraphic) { option.classList.add('selected'); console.log(`restoreCompleteUIState: Selected background graphic ${designData.bgGraphic}`); } }); } // Restore background type selection if (designData.bgType) { const typeButtons = document.querySelectorAll('.background-type-btn'); typeButtons.forEach(btn => { btn.classList.remove('active'); if (btn.dataset.type === designData.bgType) { btn.classList.add('active'); console.log(`restoreCompleteUIState: Selected background type ${designData.bgType}`); } }); // Show/hide appropriate background sections const imageSection = document.getElementById('imageBackgroundSection'); const colorSection = document.getElementById('colorBackgroundSection'); if (imageSection && colorSection) { if (designData.bgType === 'image') { imageSection.style.display = 'block'; colorSection.style.display = 'none'; } else { imageSection.style.display = 'none'; colorSection.style.display = 'block'; } } } // Restore anniversary template selection visual state if (designData.template) { const templateCards = document.querySelectorAll('.anniversary-template-card'); templateCards.forEach(card => { card.classList.remove('selected'); if (card.dataset.template === designData.template) { card.classList.add('selected'); console.log(`restoreCompleteUIState: Selected template ${designData.template}`); } }); } // Restore color picker visual states if (designData.uiState && designData.uiState.colorPickerStates) { Object.keys(designData.uiState.colorPickerStates).forEach(btnId => { const btn = document.getElementById(btnId); if (btn) { btn.style.backgroundColor = designData.uiState.colorPickerStates[btnId]; console.log(`restoreCompleteUIState: Restored color picker ${btnId} visual state`); } }); } // Restore font settings to UI elements (if font modal exists) if (designData.textSettings) { // Store text settings for font modal restoration localStorage.setItem('editorTextSettings', JSON.stringify(designData.textSettings)); // Apply text settings to color picker buttons immediately Object.keys(designData.textSettings).forEach(lineId => { const settings = designData.textSettings[lineId]; const lineNum = lineId.replace('editorLine', ''); const colorBtn = document.getElementById(`editorColorBtn${lineNum}`); if (colorBtn && settings.color) { colorBtn.style.backgroundColor = settings.color; console.log(`restoreCompleteUIState: Applied text color ${settings.color} to ${lineId}`); } }); console.log('restoreCompleteUIState: Text settings restored and applied to UI'); } // Restore uploaded image visual indicator if (designData.uploadedImageData) { const uploadContainer = document.getElementById('editorPhotoUpload'); if (uploadContainer) { // Update upload container to show image is uploaded uploadContainer.style.border = '2px solid #28a745'; uploadContainer.style.backgroundColor = '#d4edda'; const uploadText = uploadContainer.querySelector('.upload-text'); if (uploadText) { uploadText.textContent = 'Photo uploaded ✓ Click to change'; uploadText.style.color = '#155724'; } console.log('restoreCompleteUIState: Upload container updated to show uploaded image'); } } // Ensure editor container is visible and active const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer) { editorContainer.classList.add('active'); console.log('restoreCompleteUIState: Editor container ensured to be active'); } // Restore global editor state if (window.editorState) { window.editorState.currentAnniversaryTemplate = designData.template; window.editorState.selectedAnniversaryBackground = designData.bgGraphic || 'Anniversary-1'; window.editorState.selectedBackgroundType = designData.bgType || 'image'; window.editorState.selectedBackgroundColor = designData.bgColor || '#ff0000'; window.editorState.isEditorMode = true; if (designData.textSettings) { window.editorState.editorTextSettings = designData.textSettings; } console.log('restoreCompleteUIState: Global editor state synchronized'); } console.log('restoreCompleteUIState: Comprehensive UI restoration completed successfully'); return true; } catch (error) { console.error('restoreCompleteUIState: Error during UI restoration:', error); return false; } }; // Communication with Dropdown Menu form window.addEventListener('message', function(event) { if (event.origin !== window.location.origin) return; if (event.data.type === 'purposeSelected' && event.data.purpose) { console.log('Purpose selected via message:', event.data.purpose); handlePurposeChange(event.data.purpose); } }); document.addEventListener('purposeSelected', function(event) { if (event.detail && event.detail.purpose) { console.log('Purpose selected via event:', event.detail.purpose); handlePurposeChange(event.detail.purpose); } }); // Also listen for storage changes (in case purpose is set from another tab/window) window.addEventListener('storage', function(event) { if (event.key === 'selectedPurpose' && event.newValue) { console.log('Purpose selected via storage:', event.newValue); handlePurposeChange(event.newValue); } }); // Handle purpose change with proper cleanup function handlePurposeChange(newPurpose) { // Close any open editor const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer && editorContainer.classList.contains('active')) { backToTemplateSelection(); } // Close any open modals const fontModal = document.getElementById('editorFontModal'); if (fontModal && fontModal.style.display === 'flex') { window.closeEditorFontModal(); } const bgDialog = document.getElementById('backgroundGraphicDialog'); if (bgDialog && bgDialog.classList.contains('show')) { bgDialog.classList.remove('show'); } // Reset template selections currentAnniversaryTemplate = null; currentBenefitTemplate = null; currentChristianTemplate = null; currentGraduationTemplate = null; currentHolidayTemplate = null; currentLocalSchoolTemplate = null; currentLoveTemplate = null; currentMarryMeTemplate = null; editorUploadedImage = null; syncEditorState(); // Update purpose currentPurpose = newPurpose; localStorage.setItem('selectedPurpose', newPurpose); updatePurposeField(newPurpose); displayPurpose(newPurpose); } // Template Variables - Make them globally accessible window.editorState = { currentAnniversaryTemplate: null, selectedAnniversaryBackground: 'Anniversary-1', currentBenefitTemplate: null, selectedBenefitBackground: 'Benefit-3', currentChristianTemplate: null, selectedChristianBackground: 'Christian-1', currentGraduationTemplate: null, selectedGraduationBackground: 'Graduation-9', currentHolidayTemplate: null, selectedHolidayBackground: 'Holiday-1', currentLocalSchoolTemplate: null, selectedLocalSchoolBackground: 'Local-Schools-1', currentLoveTemplate: null, selectedLoveBackground: 'Love-6', currentMarryMeTemplate: null, selectedMarryMeBackground: 'Marry-Me-5', currentNewbornTemplate: null, selectedNewbornBackground: 'New-Born-1', currentObituaryTemplate: null, selectedObituaryBackground: 'Obituary-11', currentOtherTemplate: null, selectedOtherBackground: 'Other-2', selectedBackgroundType: 'image', selectedBackgroundColor: '#ff0000', editorCanvas: null, editorCtx: null, editorUploadedImage: null, isEditorMode: false, anniversaryTemplates: anniversaryTemplates, // Pass the templates benefitTemplates: benefitTemplates, // Pass the benefit templates christianTemplates: christianTemplates, // Pass the christian templates graduationTemplates: graduationTemplates, // Pass the graduation templates holidayTemplates: holidayTemplates, // Pass the holiday templates localSchoolTemplates: localSchoolTemplates, // Pass the local school templates loveTemplates: loveTemplates, // Pass the love templates marryMeTemplates: marryMeTemplates, // Pass the marry me templates newbornTemplates: newbornTemplates, // Pass the newborn templates obituaryTemplates: obituaryTemplates, // Pass the obituary templates otherTemplates: otherTemplates, // Pass the other templates editorTextSettings: null }; // Initialize global debugging window.debugEditorState = function() { console.log('Current Editor State:', window.editorState); console.log('Local variables:', { currentAnniversaryTemplate, selectedAnniversaryBackground, selectedBackgroundType, selectedBackgroundColor, isEditorMode }); }; // Helper function to sync global state - make it globally accessible function syncEditorState() { // Ensure canvas elements are initialized if (!editorCanvas) { editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); } } window.editorState.currentAnniversaryTemplate = currentAnniversaryTemplate; window.editorState.selectedAnniversaryBackground = selectedAnniversaryBackground; window.editorState.currentBenefitTemplate = currentBenefitTemplate; window.editorState.selectedBenefitBackground = selectedBenefitBackground; window.editorState.currentChristianTemplate = currentChristianTemplate; window.editorState.selectedChristianBackground = selectedChristianBackground; window.editorState.currentGraduationTemplate = currentGraduationTemplate; window.editorState.selectedGraduationBackground = selectedGraduationBackground; window.editorState.currentHolidayTemplate = currentHolidayTemplate; window.editorState.selectedHolidayBackground = selectedHolidayBackground; window.editorState.currentLocalSchoolTemplate = currentLocalSchoolTemplate; window.editorState.selectedLocalSchoolBackground = selectedLocalSchoolBackground; window.editorState.currentLoveTemplate = currentLoveTemplate; window.editorState.selectedLoveBackground = selectedLoveBackground; window.editorState.currentMarryMeTemplate = currentMarryMeTemplate; window.editorState.selectedMarryMeBackground = selectedMarryMeBackground; window.editorState.currentNewbornTemplate = currentNewbornTemplate; window.editorState.selectedNewbornBackground = selectedNewbornBackground; window.editorState.currentObituaryTemplate = currentObituaryTemplate; window.editorState.selectedObituaryBackground = selectedObituaryBackground; window.editorState.currentOtherTemplate = currentOtherTemplate; window.editorState.selectedOtherBackground = selectedOtherBackground; window.editorState.currentPetTemplate = currentPetTemplate; window.editorState.selectedPetBackground = selectedPetBackground; window.editorState.currentPrayerTemplate = currentPrayerTemplate; window.editorState.selectedPrayerBackground = selectedPrayerBackground; window.editorState.currentRetirementTemplate = currentRetirementTemplate; window.editorState.selectedRetirementBackground = selectedRetirementBackground; window.editorState.currentWeddingTemplate = currentWeddingTemplate; window.editorState.selectedWeddingBackground = selectedWeddingBackground; window.editorState.currentWelcomeTemplate = currentWelcomeTemplate; window.editorState.selectedWelcomeBackground = selectedWelcomeBackground; window.editorState.selectedBackgroundType = selectedBackgroundType; window.editorState.selectedBackgroundColor = selectedBackgroundColor; window.editorState.editorCanvas = editorCanvas; window.editorState.editorCtx = editorCtx; window.editorState.editorUploadedImage = editorUploadedImage || window.editorState.editorUploadedImage; window.editorState.isEditorMode = isEditorMode; window.editorState.anniversaryTemplates = anniversaryTemplates; window.editorState.benefitTemplates = benefitTemplates; window.editorState.christianTemplates = christianTemplates; window.editorState.graduationTemplates = graduationTemplates; window.editorState.holidayTemplates = holidayTemplates; window.editorState.localSchoolTemplates = localSchoolTemplates; window.editorState.loveTemplates = loveTemplates; window.editorState.marryMeTemplates = marryMeTemplates; window.editorState.newbornTemplates = newbornTemplates; window.editorState.obituaryTemplates = obituaryTemplates; window.editorState.otherTemplates = otherTemplates; window.editorState.petTemplates = petTemplates; window.editorState.prayerTemplates = prayerTemplates; window.editorState.retirementTemplates = retirementTemplates; window.editorState.weddingTemplates = weddingTemplates; window.editorState.welcomeTemplates = welcomeTemplates; window.editorState.editorTextSettings = editorTextSettings; // Also sync back from global to local to ensure consistency editorUploadedImage = window.editorState.editorUploadedImage; console.log('syncEditorState: State synchronized, canvas available:', !!editorCanvas); } // Make syncEditorState globally accessible window.syncEditorState = syncEditorState; // Global function to force restore local variables from saved data window.forceRestoreLocalVariables = function(designData) { console.log('forceRestoreLocalVariables: Restoring local variables from design data'); if (designData.template) { currentAnniversaryTemplate = designData.template; console.log('forceRestoreLocalVariables: Set currentAnniversaryTemplate =', currentAnniversaryTemplate); } if (designData.bgGraphic) { selectedAnniversaryBackground = designData.bgGraphic; console.log('forceRestoreLocalVariables: Set selectedAnniversaryBackground =', selectedAnniversaryBackground); } if (designData.bgType) { selectedBackgroundType = designData.bgType; console.log('forceRestoreLocalVariables: Set selectedBackgroundType =', selectedBackgroundType); } if (designData.bgColor) { selectedBackgroundColor = designData.bgColor; console.log('forceRestoreLocalVariables: Set selectedBackgroundColor =', selectedBackgroundColor); } isEditorMode = true; // Restore text settings if (designData.textSettings) { Object.keys(designData.textSettings).forEach(lineId => { if (editorTextSettings[lineId]) { editorTextSettings[lineId] = { ...editorTextSettings[lineId], ...designData.textSettings[lineId] }; } }); console.log('forceRestoreLocalVariables: Text settings restored'); } // Restore uploaded image to local variable if (designData.uploadedImageData && window.editorState.editorUploadedImage) { editorUploadedImage = window.editorState.editorUploadedImage; console.log('forceRestoreLocalVariables: Uploaded image restored to local variable'); } // Ensure canvas is initialized if (!editorCanvas) { editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); console.log('forceRestoreLocalVariables: Canvas initialized'); } } // Sync to global state syncEditorState(); console.log('forceRestoreLocalVariables: Local variables restoration completed'); }; // Local variables for easier access within this scope let currentAnniversaryTemplate = null; let selectedAnniversaryBackground = 'Anniversary-1'; let currentBenefitTemplate = null; let selectedBenefitBackground = 'Benefit-3'; let currentChristianTemplate = null; let selectedChristianBackground = 'Christian-1'; let currentGraduationTemplate = null; let selectedGraduationBackground = 'Graduation-1'; let currentHolidayTemplate = null; let selectedHolidayBackground = 'Holiday-1'; let currentLocalSchoolTemplate = null; let selectedLocalSchoolBackground = 'Local-Schools-1'; let currentLoveTemplate = null; let selectedLoveBackground = 'Love-6'; let currentMarryMeTemplate = null; let selectedMarryMeBackground = 'Marry-Me-5'; let currentNewbornTemplate = null; let selectedNewbornBackground = 'New-Born-1'; let currentObituaryTemplate = null; let selectedObituaryBackground = 'Obituary-11'; let currentOtherTemplate = null; let selectedOtherBackground = 'Other-2'; let currentPetTemplate = null; let selectedPetBackground = 'Pet-11'; let currentPrayerTemplate = null; let selectedPrayerBackground = 'Prayer-2'; let currentRetirementTemplate = null; let selectedRetirementBackground = 'Retirement-9'; let currentWeddingTemplate = null; let selectedWeddingBackground = 'Wedding-10'; let currentWelcomeTemplate = null; let selectedWelcomeBackground = 'Welcome-10'; let selectedBackgroundType = 'image'; // 'image' or 'color' let selectedBackgroundColor = '#ff0000'; let editorCanvas = null; let editorCtx = null; let editorUploadedImage = null; let isEditorMode = false; // Template Text Settings (changeable based on selected template) let editorTextSettings = { editorLine1: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 }, editorLine2: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 }, editorLine3: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 }, editorLine4: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 } }; // Initial sync to set up global state syncEditorState(); // Initialize Anniversary Templates function initAnniversaryTemplates() { const templateCards = document.querySelectorAll('.anniversary-template-card'); templateCards.forEach(card => { card.addEventListener('click', function() { const templateId = this.dataset.template; selectAnniversaryTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); } syncEditorState(); // Background graphic button const bgGraphicBtn = document.getElementById('backgroundGraphicBtn'); if (bgGraphicBtn) { bgGraphicBtn.addEventListener('click', showBackgroundGraphicDialog); } // Editor photo upload (prevent duplicate listeners) const editorPhotoUpload = document.getElementById('editorPhotoUpload'); const editorPhotoInput = document.getElementById('editorPhotoInput'); if (editorPhotoUpload && editorPhotoInput && !editorPhotoUpload.hasAttribute('data-listener-added')) { editorPhotoUpload.addEventListener('click', () => editorPhotoInput.click()); editorPhotoInput.addEventListener('change', handleEditorPhotoUpload); editorPhotoUpload.setAttribute('data-listener-added', 'true'); } // Editor text inputs with validation const editorTextInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; editorTextInputs.forEach(inputId => { const input = document.getElementById(inputId); if (input) { input.addEventListener('input', function() { validateTextInput(this); updateEditorCanvas(); }); // Initialize character counter validateTextInput(input); } }); // Note: Back to templates button and Confirm template button now use onclick attributes // No need for addEventListener to prevent duplicate calls console.log('Anniversary template buttons configured with onclick attributes'); // Initialize anniversary backgrounds initAnniversaryBackgrounds(); // Setup editor color pickers and settings buttons setupEditorColorPickers(); setupEditorSettingsButtons(); // Add resize listener for responsive canvas window.addEventListener('resize', function() { if (isEditorMode && editorCanvas) { setTimeout(updateEditorCanvas, 100); } }); // Setup image resize modal buttons const cancelResizeBtn = document.getElementById('cancelResizeBtn'); const confirmResizeBtn = document.getElementById('confirmResizeBtn'); if (cancelResizeBtn) { cancelResizeBtn.addEventListener('click', function() { cancelImageResize(); }); } if (confirmResizeBtn) { confirmResizeBtn.addEventListener('click', function() { confirmImageResize(); }); } } // Initialize Benefit Templates function initBenefitTemplates() { const templateCards = document.querySelectorAll('.benefit-template-card'); templateCards.forEach(card => { card.addEventListener('click', function() { const templateId = this.dataset.template; selectBenefitTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); } syncEditorState(); // Background graphic button const bgGraphicBtn = document.getElementById('backgroundGraphicBtn'); if (bgGraphicBtn) { bgGraphicBtn.addEventListener('click', showBackgroundGraphicDialog); } // Editor photo upload (prevent duplicate listeners) const editorPhotoUpload = document.getElementById('editorPhotoUpload'); const editorPhotoInput = document.getElementById('editorPhotoInput'); if (editorPhotoUpload && editorPhotoInput && !editorPhotoUpload.hasAttribute('data-listener-added')) { editorPhotoUpload.addEventListener('click', () => editorPhotoInput.click()); editorPhotoInput.addEventListener('change', handleEditorPhotoUpload); editorPhotoUpload.setAttribute('data-listener-added', 'true'); } // Editor text inputs with validation const editorTextInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; editorTextInputs.forEach(inputId => { const input = document.getElementById(inputId); if (input) { input.addEventListener('input', function() { validateTextInput(this); updateEditorCanvas(); }); // Initialize character counter validateTextInput(input); } }); // Note: Back to templates button and Confirm template button now use onclick attributes // No need for addEventListener to prevent duplicate calls console.log('Benefit template buttons configured with onclick attributes'); // Initialize benefit backgrounds initBenefitBackgrounds(); // Setup editor color pickers and settings buttons setupEditorColorPickers(); setupEditorSettingsButtons(); // Add resize listener for responsive canvas window.addEventListener('resize', function() { if (isEditorMode && editorCanvas) { setTimeout(updateEditorCanvas, 100); } }); // Setup image resize modal buttons const cancelResizeBtn = document.getElementById('cancelResizeBtn'); const confirmResizeBtn = document.getElementById('confirmResizeBtn'); if (cancelResizeBtn) { cancelResizeBtn.addEventListener('click', function() { cancelImageResize(); }); } if (confirmResizeBtn) { confirmResizeBtn.addEventListener('click', function() { confirmImageResize(); }); } } // Initialize Christian Templates function initChristianTemplates() { const templateCards = document.querySelectorAll('.christian-template-card'); templateCards.forEach(card => { card.addEventListener('click', function() { const templateId = this.dataset.template; selectChristianTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); } syncEditorState(); // Background graphic button const bgGraphicBtn = document.getElementById('backgroundGraphicBtn'); if (bgGraphicBtn) { bgGraphicBtn.addEventListener('click', showBackgroundGraphicDialog); } // Editor photo upload (prevent duplicate listeners) const editorPhotoUpload = document.getElementById('editorPhotoUpload'); const editorPhotoInput = document.getElementById('editorPhotoInput'); if (editorPhotoUpload && editorPhotoInput && !editorPhotoUpload.hasAttribute('data-listener-added')) { editorPhotoUpload.addEventListener('click', () => editorPhotoInput.click()); editorPhotoInput.addEventListener('change', handleEditorPhotoUpload); editorPhotoUpload.setAttribute('data-listener-added', 'true'); } // Editor text inputs with validation const editorTextInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; editorTextInputs.forEach(inputId => { const input = document.getElementById(inputId); if (input) { input.addEventListener('input', function() { validateTextInput(this); updateEditorCanvas(); }); // Initialize character counter validateTextInput(input); } }); // Note: Back to templates button and Confirm template button now use onclick attributes // No need for addEventListener to prevent duplicate calls console.log('Christian template buttons configured with onclick attributes'); // Initialize christian backgrounds initChristianBackgrounds(); // Setup editor color pickers and settings buttons setupEditorColorPickers(); setupEditorSettingsButtons(); // Add resize listener for responsive canvas window.addEventListener('resize', function() { if (editorCanvas && currentChristianTemplate) { updateEditorCanvas(); } }); // Setup image resize modal buttons const cancelResizeBtn = document.getElementById('cancelResizeBtn'); const confirmResizeBtn = document.getElementById('confirmResizeBtn'); if (cancelResizeBtn) { cancelResizeBtn.addEventListener('click', function() { cancelImageResize(); }); } if (confirmResizeBtn) { confirmResizeBtn.addEventListener('click', function() { confirmImageResize(); }); } } // Initialize Graduation Templates function initGraduationTemplates() { const templateCards = document.querySelectorAll('.graduation-template-card'); templateCards.forEach(card => { card.addEventListener('click', function() { const templateId = this.dataset.template; selectGraduationTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); } syncEditorState(); // Background graphic button const bgGraphicBtn = document.getElementById('backgroundGraphicBtn'); if (bgGraphicBtn) { bgGraphicBtn.addEventListener('click', showBackgroundGraphicDialog); } // Editor photo upload (prevent duplicate listeners) const editorPhotoUpload = document.getElementById('editorPhotoUpload'); const editorPhotoInput = document.getElementById('editorPhotoInput'); if (editorPhotoUpload && editorPhotoInput && !editorPhotoUpload.hasAttribute('data-listener-added')) { editorPhotoUpload.addEventListener('click', () => editorPhotoInput.click()); editorPhotoInput.addEventListener('change', handleEditorPhotoUpload); editorPhotoUpload.setAttribute('data-listener-added', 'true'); } // Editor text inputs with validation const editorTextInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; editorTextInputs.forEach(inputId => { const input = document.getElementById(inputId); if (input) { input.addEventListener('input', function() { validateTextInput(this); updateEditorCanvas(); }); // Initialize character counter validateTextInput(input); } }); // Note: Back to templates button and Confirm template button now use onclick attributes // No need for addEventListener to prevent duplicate calls console.log('Graduation template buttons configured with onclick attributes'); // Initialize graduation backgrounds initGraduationBackgrounds(); // Setup editor color pickers and settings buttons setupEditorColorPickers(); setupEditorSettingsButtons(); // Add resize listener for responsive canvas window.addEventListener('resize', function() { if (editorCanvas && currentGraduationTemplate) { updateEditorCanvas(); } }); // Setup image resize modal buttons const cancelResizeBtn = document.getElementById('cancelResizeBtn'); const confirmResizeBtn = document.getElementById('confirmResizeBtn'); if (cancelResizeBtn) { cancelResizeBtn.addEventListener('click', function() { cancelImageResize(); }); } if (confirmResizeBtn) { confirmResizeBtn.addEventListener('click', function() { confirmImageResize(); }); } } // Initialize Holiday Templates function initHolidayTemplates() { const templateCards = document.querySelectorAll('.holiday-template-card'); templateCards.forEach(card => { card.addEventListener('click', function() { const templateId = this.dataset.template; selectHolidayTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); } syncEditorState(); // Background graphic button const bgGraphicBtn = document.getElementById('backgroundGraphicBtn'); if (bgGraphicBtn) { bgGraphicBtn.addEventListener('click', showBackgroundGraphicDialog); } // Editor photo upload (prevent duplicate listeners) const editorPhotoUpload = document.getElementById('editorPhotoUpload'); const editorPhotoInput = document.getElementById('editorPhotoInput'); if (editorPhotoUpload && editorPhotoInput && !editorPhotoUpload.hasAttribute('data-listener-added')) { editorPhotoUpload.addEventListener('click', () => editorPhotoInput.click()); editorPhotoInput.addEventListener('change', handleEditorPhotoUpload); editorPhotoUpload.setAttribute('data-listener-added', 'true'); } // Editor text inputs with validation const editorTextInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; editorTextInputs.forEach(inputId => { const input = document.getElementById(inputId); if (input) { input.addEventListener('input', function() { validateTextInput(this); updateEditorCanvas(); }); // Initialize character counter validateTextInput(input); } }); // Color picker buttons ['editorColorBtn1', 'editorColorBtn2', 'editorColorBtn3', 'editorColorBtn4'].forEach(btnId => { const btn = document.getElementById(btnId); if (btn) { btn.addEventListener('click', function() { const lineNumber = btnId.replace('editorColorBtn', ''); showEditorColorPicker(lineNumber); }); } }); // Settings buttons ['editorSettingsBtn1', 'editorSettingsBtn2', 'editorSettingsBtn3', 'editorSettingsBtn4'].forEach(btnId => { const btn = document.getElementById(btnId); if (btn) { btn.addEventListener('click', function() { const lineNumber = btnId.replace('editorSettingsBtn', ''); showEditorFontModal(lineNumber); }); } }); // Image resize confirmation button const confirmResizeBtn = document.getElementById('confirmImageResize'); if (confirmResizeBtn) { confirmResizeBtn.addEventListener('click', function() { confirmImageResize(); }); } } // Initialize Local School Templates function initLocalSchoolTemplates() { const templateCards = document.querySelectorAll('.local-school-template-card'); templateCards.forEach(card => { card.addEventListener('click', function() { const templateId = this.dataset.template; selectLocalSchoolTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); console.log('initLocalSchoolTemplates: Editor canvas initialized'); } else { console.error('initLocalSchoolTemplates: Editor canvas not found'); } // Initialize text input event listeners for (let i = 1; i <= 4; i++) { const input = document.getElementById(`editorLine${i}`); if (input) { input.addEventListener('input', function() { console.log(`initLocalSchoolTemplates: Text input ${i} changed:`, this.value); updateEditorCanvas(); }); } else { console.error(`initLocalSchoolTemplates: Text input ${i} not found`); } } // Initialize color picker buttons for (let i = 1; i <= 4; i++) { const colorBtn = document.getElementById(`editorColorBtn${i}`); if (colorBtn) { colorBtn.addEventListener('click', function() { console.log(`initLocalSchoolTemplates: Color button ${i} clicked`); openColorPicker(i); }); } else { console.error(`initLocalSchoolTemplates: Color button ${i} not found`); } } // Initialize font size inputs for (let i = 1; i { card.addEventListener('click', function() { const templateId = this.dataset.template; selectLoveTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); console.log('initLoveTemplates: Editor canvas initialized'); } else { console.error('initLoveTemplates: Editor canvas not found'); } // Initialize text input event listeners for (let i = 1; i <= 4; i++) { const input = document.getElementById(`editorLine${i}`); if (input) { input.addEventListener('input', function() { console.log(`initLoveTemplates: Text input ${i} changed:`, this.value); updateEditorCanvas(); }); } else { console.error(`initLoveTemplates: Text input ${i} not found`); } } // Initialize color picker buttons for (let i = 1; i <= 4; i++) { const colorBtn = document.getElementById(`editorColorBtn${i}`); if (colorBtn) { colorBtn.addEventListener('click', function() { console.log(`initLoveTemplates: Color button ${i} clicked`); openColorPicker(i); }); } else { console.error(`initLoveTemplates: Color button ${i} not found`); } } // Initialize font size inputs for (let i = 1; i { card.addEventListener('click', function() { const templateId = this.dataset.template; selectMarryMeTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); console.log('initMarryMeTemplates: Editor canvas initialized'); } else { console.error('initMarryMeTemplates: Editor canvas not found'); } // Initialize text input event listeners for (let i = 1; i <= 4; i++) { const input = document.getElementById(`editorLine${i}`); if (input) { input.addEventListener('input', function() { console.log(`initMarryMeTemplates: Text input ${i} changed:`, this.value); updateEditorCanvas(); }); } else { console.error(`initMarryMeTemplates: Text input ${i} not found`); } } // Initialize color picker buttons for (let i = 1; i <= 4; i++) { const colorBtn = document.getElementById(`editorColorBtn${i}`); if (colorBtn) { colorBtn.addEventListener('click', function() { console.log(`initMarryMeTemplates: Color button ${i} clicked`); openColorPicker(i); }); } else { console.error(`initMarryMeTemplates: Color button ${i} not found`); } } // Initialize font size inputs for (let i = 1; i { card.addEventListener('click', function() { const templateId = this.dataset.template; selectNewbornTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); console.log('initNewbornTemplates: Editor canvas initialized'); } else { console.error('initNewbornTemplates: Editor canvas not found'); } // Initialize text input event listeners for (let i = 1; i <= 4; i++) { const input = document.getElementById(`editorLine${i}`); if (input) { input.addEventListener('input', function() { console.log(`initNewbornTemplates: Text input ${i} changed:`, this.value); updateEditorCanvas(); }); } else { console.error(`initNewbornTemplates: Text input ${i} not found`); } } // Initialize color picker buttons for (let i = 1; i <= 4; i++) { const colorBtn = document.getElementById(`editorColorBtn${i}`); if (colorBtn) { colorBtn.addEventListener('click', function() { console.log(`initNewbornTemplates: Color button ${i} clicked`); openColorPicker(i); }); } else { console.error(`initNewbornTemplates: Color button ${i} not found`); } } // Initialize font size inputs for (let i = 1; i { card.addEventListener('click', function() { const templateId = this.dataset.template; selectObituaryTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); console.log('initObituaryTemplates: Editor canvas initialized'); } else { console.error('initObituaryTemplates: Editor canvas not found'); } // Initialize text input event listeners for (let i = 1; i <= 4; i++) { const input = document.getElementById(`editorLine${i}`); if (input) { input.addEventListener('input', function() { console.log(`initObituaryTemplates: Text input ${i} changed:`, this.value); updateEditorCanvas(); }); } else { console.error(`initObituaryTemplates: Text input ${i} not found`); } } // Initialize color picker buttons for (let i = 1; i <= 4; i++) { const colorBtn = document.getElementById(`editorColorBtn${i}`); if (colorBtn) { colorBtn.addEventListener('click', function() { console.log(`initObituaryTemplates: Color button ${i} clicked`); openColorPicker(i); }); } else { console.error(`initObituaryTemplates: Color button ${i} not found`); } } // Initialize font size inputs for (let i = 1; i { card.addEventListener('click', function() { const templateId = this.dataset.template; selectOtherTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); console.log('initOtherTemplates: Editor canvas initialized'); } else { console.error('initOtherTemplates: Editor canvas not found'); } // Initialize text input event listeners for (let i = 1; i <= 4; i++) { const input = document.getElementById(`editorLine${i}`); if (input) { input.addEventListener('input', function() { console.log(`initOtherTemplates: Text input ${i} changed:`, this.value); updateEditorCanvas(); }); } else { console.error(`initOtherTemplates: Text input ${i} not found`); } } // Initialize color picker buttons for (let i = 1; i <= 4; i++) { const colorBtn = document.getElementById(`editorColorBtn${i}`); if (colorBtn) { colorBtn.addEventListener('click', function() { console.log(`initOtherTemplates: Color button ${i} clicked`); openColorPicker(i); }); } else { console.error(`initOtherTemplates: Color button ${i} not found`); } } // Initialize font size inputs for (let i = 1; i { card.addEventListener('click', function() { const templateId = this.dataset.template; selectPetTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); console.log('initPetTemplates: Editor canvas initialized'); } else { console.error('initPetTemplates: Editor canvas not found'); } // Initialize text input event listeners for (let i = 1; i <= 4; i++) { const input = document.getElementById(`editorLine${i}`); if (input) { input.addEventListener('input', function() { console.log(`initPetTemplates: Text input ${i} changed:`, this.value); updateEditorCanvas(); }); } else { console.error(`initPetTemplates: Text input ${i} not found`); } } // Initialize color picker buttons for (let i = 1; i <= 4; i++) { const colorBtn = document.getElementById(`editorColorBtn${i}`); if (colorBtn) { colorBtn.addEventListener('click', function() { console.log(`initPetTemplates: Color button ${i} clicked`); openColorPicker(i); }); } else { console.error(`initPetTemplates: Color button ${i} not found`); } } // Initialize font size inputs for (let i = 1; i { card.addEventListener('click', function() { const templateId = this.dataset.template; selectRetirementTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); } syncEditorState(); // Background graphic button const bgGraphicBtn = document.getElementById('backgroundGraphicBtn'); if (bgGraphicBtn) { bgGraphicBtn.addEventListener('click', showBackgroundGraphicDialog); } // Editor photo upload (prevent duplicate listeners) const editorPhotoUpload = document.getElementById('editorPhotoUpload'); const editorPhotoInput = document.getElementById('editorPhotoInput'); if (editorPhotoUpload && editorPhotoInput && !editorPhotoUpload.hasAttribute('data-listener-added')) { editorPhotoUpload.addEventListener('click', () => editorPhotoInput.click()); editorPhotoInput.addEventListener('change', handleEditorPhotoUpload); editorPhotoUpload.setAttribute('data-listener-added', 'true'); } // Editor text inputs with validation const editorTextInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; editorTextInputs.forEach(inputId => { const input = document.getElementById(inputId); if (input) { input.addEventListener('input', function() { validateTextInput(this); updateEditorCanvas(); }); // Initialize character counter validateTextInput(input); } }); // Initialize retirement backgrounds initRetirementBackgrounds(); } // Initialize Prayer Templates function initPrayerTemplates() { const templateCards = document.querySelectorAll('.prayer-template-card'); templateCards.forEach(card => { card.addEventListener('click', function() { const templateId = this.dataset.template; console.log('initPrayerTemplates: Template card clicked:', templateId); selectPrayerTemplate(templateId); }); }); // Initialize text input event listeners for (let i = 1; i <= 4; i++) { const input = document.getElementById(`editorLine${i}`); if (input) { input.addEventListener('input', function() { console.log(`initPrayerTemplates: Text input ${i} changed:`, this.value); updateEditorCanvas(); }); } else { console.error(`initPrayerTemplates: Text input ${i} not found`); } } // Initialize color picker buttons for (let i = 1; i <= 4; i++) { const colorBtn = document.getElementById(`editorColorBtn${i}`); if (colorBtn) { colorBtn.addEventListener('click', function() { console.log(`initPrayerTemplates: Color button ${i} clicked`); openColorPicker(i); }); } else { console.error(`initPrayerTemplates: Color button ${i} not found`); } } // Initialize font size controls for (let i = 1; i { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } currentAnniversaryTemplate = templateId; // Set default background based on template switch(templateId) { case 'anniversary-template-1': selectedAnniversaryBackground = 'Anniversary-1'; break; case 'anniversary-template-2': selectedAnniversaryBackground = 'Anniversary-2'; break; case 'anniversary-template-3': selectedAnniversaryBackground = 'Anniversary-3'; break; default: selectedAnniversaryBackground = 'Anniversary-1'; } syncEditorState(); // Populate text fields with default values and initialize editor text settings const template = anniversaryTemplates[templateId]; if (template && template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; input.placeholder = text; } }); } // Initialize editor text settings with template textStyles as defaults if (template && template.textStyles) { template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Show editor showTemplateEditor(); } // Select Benefit Template function selectBenefitTemplate(templateId) { // Remove previous selection document.querySelectorAll('.benefit-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } currentBenefitTemplate = templateId; // Clear any uploaded image when selecting a new template to show default image editorUploadedImage = null; if (window.editorState) { window.editorState.editorUploadedImage = null; } // Set default background based on template switch(templateId) { case 'benefit-template-1': selectedBenefitBackground = 'Benefit-3'; selectedBackgroundType = 'image'; break; case 'benefit-template-2': // Template 2 uses black background by default, but user can change it selectedBackgroundType = 'color'; selectedBackgroundColor = '#000000'; selectedBenefitBackground = 'Benefit-4'; // fallback for image mode break; case 'benefit-template-3': selectedBenefitBackground = 'Benefit-5'; selectedBackgroundType = 'image'; break; default: selectedBenefitBackground = 'Benefit-3'; selectedBackgroundType = 'image'; } syncEditorState(); // Populate text fields with default values and initialize editor text settings const template = benefitTemplates[templateId]; if (template && template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; input.placeholder = text; } }); } // Initialize editor text settings with template textStyles as defaults if (template && template.textStyles) { template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Show editor showTemplateEditor(); } // Select Christian Template function selectChristianTemplate(templateId) { // Remove previous selection document.querySelectorAll('.christian-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } currentChristianTemplate = templateId; // Clear any uploaded image when selecting a new template to show default image editorUploadedImage = null; if (window.editorState) { window.editorState.editorUploadedImage = null; } // Set default background based on template switch(templateId) { case 'christian-template-1': // Template 1 uses black background by default, but user can change it selectedBackgroundType = 'color'; selectedBackgroundColor = '#000000'; selectedChristianBackground = 'Christian-1'; // fallback for image mode break; case 'christian-template-2': selectedChristianBackground = 'Christian-15'; selectedBackgroundType = 'image'; break; case 'christian-template-3': selectedChristianBackground = 'Christian-12'; selectedBackgroundType = 'image'; break; default: selectedBackgroundType = 'color'; selectedBackgroundColor = '#000000'; selectedChristianBackground = 'Christian-1'; } syncEditorState(); // Populate text fields with default values and initialize editor text settings const template = christianTemplates[templateId]; if (template && template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; input.placeholder = text; } }); } // Initialize editor text settings with template textStyles as defaults if (template && template.textStyles) { editorTextSettings = template.textStyles.map(style => ({...style})); // Update global state if (window.editorState) { window.editorState.editorTextSettings = editorTextSettings; } // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Show editor showTemplateEditor(); } // Select Graduation Template function selectGraduationTemplate(templateId) { console.log('selectGraduationTemplate: Starting with templateId:', templateId); // Remove previous selection document.querySelectorAll('.graduation-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); console.log('selectGraduationTemplate: Template card selected'); } else { console.error('selectGraduationTemplate: Template card not found for:', templateId); } currentGraduationTemplate = templateId; console.log('selectGraduationTemplate: currentGraduationTemplate set to:', currentGraduationTemplate); // Clear any uploaded image when selecting a new template to show default image editorUploadedImage = null; if (window.editorState) { window.editorState.editorUploadedImage = null; } // Set default background based on template switch(templateId) { case 'graduation-template-1': selectedGraduationBackground = 'Graduation-9'; break; case 'graduation-template-2': selectedGraduationBackground = 'Graduation-14'; break; case 'graduation-template-3': selectedGraduationBackground = 'Graduation-3'; break; default: selectedGraduationBackground = 'Graduation-9'; } syncEditorState(); // Populate text fields with default values and initialize editor text settings const template = graduationTemplates[templateId]; console.log('selectGraduationTemplate: Template found:', !!template, template); if (template && template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; input.placeholder = text; } }); } // Initialize editor text settings with template textStyles as defaults if (template && template.textStyles) { editorTextSettings = template.textStyles.map(style => ({...style})); // Update global state if (window.editorState) { window.editorState.editorTextSettings = editorTextSettings; } // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Show editor showTemplateEditor(); // Force canvas update after a short delay to ensure everything is initialized setTimeout(() => { updateEditorCanvas(); }, 100); } // Select Holiday Template function selectHolidayTemplate(templateId) { console.log('selectHolidayTemplate: Starting with templateId:', templateId); // Remove previous selection document.querySelectorAll('.holiday-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); console.log('selectHolidayTemplate: Template card selected'); } else { console.error('selectHolidayTemplate: Template card not found for:', templateId); } currentHolidayTemplate = templateId; console.log('selectHolidayTemplate: currentHolidayTemplate set to:', currentHolidayTemplate); // Clear any uploaded image when selecting a new template to show default image editorUploadedImage = null; // Get template data const template = holidayTemplates[templateId]; if (!template) { console.error('selectHolidayTemplate: Template not found:', templateId); return; } console.log('selectHolidayTemplate: Template data:', template); console.log('selectHolidayTemplate: Template type:', template.type, 'imagePosition:', template.imagePosition, 'defaultImage:', template.defaultImage); // Set default background based on template switch(templateId) { case 'holiday-template-1': selectedHolidayBackground = 'Holiday-1'; selectedBackgroundType = 'image'; break; case 'holiday-template-2': selectedHolidayBackground = 'Holiday-8'; selectedBackgroundType = 'image'; break; case 'holiday-template-3': selectedHolidayBackground = 'Holiday-4'; selectedBackgroundType = 'image'; break; default: selectedHolidayBackground = 'Holiday-1'; selectedBackgroundType = 'image'; } syncEditorState(); // Populate text fields with default values if (template && template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; input.placeholder = text; } }); } // Initialize editor text settings with template textStyles as defaults if (template && template.textStyles) { template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Show editor showTemplateEditor(); } // Select Local School Template function selectLocalSchoolTemplate(templateId) { console.log('selectLocalSchoolTemplate: Starting with templateId:', templateId); // Remove previous selection document.querySelectorAll('.local-school-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); console.log('selectLocalSchoolTemplate: Template card selected'); } else { console.error('selectLocalSchoolTemplate: Template card not found for:', templateId); } currentLocalSchoolTemplate = templateId; console.log('selectLocalSchoolTemplate: currentLocalSchoolTemplate set to:', currentLocalSchoolTemplate); // Clear any uploaded image when selecting a new template to show default image editorUploadedImage = null; // Get template data const template = localSchoolTemplates[templateId]; if (!template) { console.error('selectLocalSchoolTemplate: Template not found:', templateId); return; } console.log('selectLocalSchoolTemplate: Template data:', template); console.log('selectLocalSchoolTemplate: Template type:', template.type, 'background:', template.background); // Set default background based on template switch(templateId) { case 'local-school-template-1': selectedLocalSchoolBackground = 'Local-Schools-3'; selectedBackgroundType = 'image'; break; case 'local-school-template-2': selectedLocalSchoolBackground = 'Local-Schools-7'; selectedBackgroundType = 'image'; break; case 'local-school-template-3': selectedLocalSchoolBackground = 'Local-Schools-5'; selectedBackgroundType = 'image'; break; default: selectedLocalSchoolBackground = 'Local-Schools-1'; selectedBackgroundType = 'image'; } syncEditorState(); // Populate text fields with default values if (template && template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; input.placeholder = text; } }); } // Initialize editor text settings with template textStyles as defaults if (template && template.textStyles) { template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Show editor showTemplateEditor(); } // Select Love Template function selectLoveTemplate(templateId) { console.log('selectLoveTemplate: Starting with templateId:', templateId); // Remove previous selection document.querySelectorAll('.love-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); console.log('selectLoveTemplate: Template card selected'); } else { console.error('selectLoveTemplate: Template card not found for:', templateId); } currentLoveTemplate = templateId; console.log('selectLoveTemplate: currentLoveTemplate set to:', currentLoveTemplate); // Clear any uploaded image when selecting a new template to show default image editorUploadedImage = null; // Get template data const template = loveTemplates[templateId]; if (!template) { console.error('selectLoveTemplate: Template not found:', templateId); return; } console.log('selectLoveTemplate: Template data:', template); console.log('selectLoveTemplate: Template type:', template.type, 'background:', template.background); // Set default background based on template switch(templateId) { case 'love-template-1': selectedLoveBackground = 'Love-6'; selectedBackgroundType = 'image'; break; case 'love-template-2': selectedLoveBackground = 'Love-14'; selectedBackgroundType = 'image'; break; case 'love-template-3': selectedLoveBackground = 'Love-3'; selectedBackgroundType = 'image'; break; default: selectedLoveBackground = 'Love-6'; selectedBackgroundType = 'image'; } console.log('selectLoveTemplate: Background set to:', selectedLoveBackground); syncEditorState(); // Set default texts if (template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; console.log(`selectLoveTemplate: Set line ${index + 1} to:`, text); } }); } // Set text styles for editor controls if (template.textStyles) { template.textStyles.forEach((style, index) => { console.log(`selectLoveTemplate: Setting style for line ${index + 1}:`, style); // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Force canvas update to ensure Love template is drawn setTimeout(() => { console.log('selectLoveTemplate: Forcing canvas update'); updateEditorCanvas(); }, 50); // Show editor showTemplateEditor(); } // Select Marry Me Template function selectMarryMeTemplate(templateId) { console.log('selectMarryMeTemplate: Starting with templateId:', templateId); // Remove previous selection document.querySelectorAll('.marry-me-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); console.log('selectMarryMeTemplate: Template card selected'); } else { console.error('selectMarryMeTemplate: Template card not found for:', templateId); } currentMarryMeTemplate = templateId; console.log('selectMarryMeTemplate: currentMarryMeTemplate set to:', currentMarryMeTemplate); // Clear any uploaded image when selecting a new template to show default image editorUploadedImage = null; console.log('selectMarryMeTemplate: Cleared uploaded image'); const template = marryMeTemplates[templateId]; if (!template) { console.error('selectMarryMeTemplate: Template not found:', templateId); return; } console.log('selectMarryMeTemplate: Template found:', template); // Set default background based on template switch(templateId) { case 'marry-me-template-1': selectedMarryMeBackground = 'Marry-Me-5'; selectedBackgroundType = 'image'; break; case 'marry-me-template-2': selectedMarryMeBackground = 'Marry-Me-11'; selectedBackgroundType = 'image'; break; case 'marry-me-template-3': selectedMarryMeBackground = 'Marry-Me-1'; selectedBackgroundType = 'image'; break; default: selectedMarryMeBackground = 'Marry-Me-5'; selectedBackgroundType = 'image'; } console.log('selectMarryMeTemplate: Background set to:', selectedMarryMeBackground); // Set current template for global access window.editorState = window.editorState || {}; window.editorState.currentMarryMeTemplate = templateId; window.editorState.marryMeTemplates = marryMeTemplates; syncEditorState(); // Set default texts if (template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; console.log(`selectMarryMeTemplate: Set line ${index + 1} to:`, text); } }); } // Set text styles for editor controls if (template.textStyles) { template.textStyles.forEach((style, index) => { console.log(`selectMarryMeTemplate: Setting style for line ${index + 1}:`, style); // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Force canvas update to ensure Marry Me template is drawn setTimeout(() => { console.log('selectMarryMeTemplate: Forcing canvas update'); updateEditorCanvas(); }, 50); // Show editor showTemplateEditor(); } // Select Newborn Template function selectNewbornTemplate(templateId) { console.log('selectNewbornTemplate: Starting with templateId:', templateId); // Remove previous selection document.querySelectorAll('.newborn-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); console.log('selectNewbornTemplate: Template card selected'); } else { console.error('selectNewbornTemplate: Template card not found for:', templateId); } currentNewbornTemplate = templateId; console.log('selectNewbornTemplate: currentNewbornTemplate set to:', currentNewbornTemplate); // Clear any uploaded image when selecting a new template to show default image editorUploadedImage = null; console.log('selectNewbornTemplate: Cleared uploaded image'); const template = newbornTemplates[templateId]; if (!template) { console.error('selectNewbornTemplate: Template not found:', templateId); return; } console.log('selectNewbornTemplate: Template found:', template); // Set default background based on template switch(templateId) { case 'newborn-template-1': selectedNewbornBackground = 'New-Born-1'; selectedBackgroundType = 'image'; break; case 'newborn-template-2': selectedNewbornBackground = 'New-Born-12'; selectedBackgroundType = 'image'; break; case 'newborn-template-3': selectedNewbornBackground = 'New-Born-7'; selectedBackgroundType = 'image'; break; default: selectedNewbornBackground = 'New-Born-1'; selectedBackgroundType = 'image'; } console.log('selectNewbornTemplate: Background set to:', selectedNewbornBackground); // Set current template for global access window.editorState = window.editorState || {}; window.editorState.currentNewbornTemplate = templateId; window.editorState.newbornTemplates = newbornTemplates; syncEditorState(); // Set default texts in editor inputs if (template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; console.log(`selectNewbornTemplate: Set line ${index + 1} to:`, text); } }); } // Set text styles for editor controls if (template.textStyles) { template.textStyles.forEach((style, index) => { console.log(`selectNewbornTemplate: Setting style for line ${index + 1}:`, style); // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Force canvas update to ensure Newborn template is drawn setTimeout(() => { console.log('selectNewbornTemplate: Forcing canvas update'); updateEditorCanvas(); }, 50); // Show editor showTemplateEditor(); } // Select Obituary Template function selectObituaryTemplate(templateId) { console.log('selectObituaryTemplate: Starting with templateId:', templateId); // Remove previous selection document.querySelectorAll('.obituary-template-card').forEach(card => { card.classList.remove('selected'); }); // Add selection to current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } const template = obituaryTemplates[templateId]; if (!template) { console.error('selectObituaryTemplate: Template not found:', templateId); return; } console.log('selectObituaryTemplate: Template found:', template); // Set current template currentObituaryTemplate = templateId; // Set background based on template switch(templateId) { case 'obituary-template-1': selectedObituaryBackground = 'Obituary-11'; break; case 'obituary-template-2': selectedObituaryBackground = 'Obituary-8'; break; case 'obituary-template-3': selectedObituaryBackground = 'Obituary-2'; break; default: selectedObituaryBackground = 'Obituary-11'; } console.log('selectObituaryTemplate: Background set to:', selectedObituaryBackground); // Set current template for global access window.editorState = window.editorState || {}; window.editorState.currentObituaryTemplate = templateId; window.editorState.obituaryTemplates = obituaryTemplates; syncEditorState(); // Set default texts in editor inputs if (template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; console.log(`selectObituaryTemplate: Set line ${index + 1} to:`, text); } }); } // Set text styles for editor controls if (template.textStyles) { template.textStyles.forEach((style, index) => { console.log(`selectObituaryTemplate: Setting style for line ${index + 1}:`, style); // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Force canvas update to ensure Obituary template is drawn setTimeout(() => { console.log('selectObituaryTemplate: Forcing canvas update'); updateEditorCanvas(); }, 50); // Show editor showTemplateEditor(); } // Select Other Template function selectOtherTemplate(templateId) { console.log('selectOtherTemplate: Starting with templateId:', templateId); // Remove previous selection document.querySelectorAll('.other-template-card').forEach(card => { card.classList.remove('selected'); }); // Add selection to current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } const template = otherTemplates[templateId]; if (!template) { console.error('selectOtherTemplate: Template not found:', templateId); return; } console.log('selectOtherTemplate: Template found:', template); // Set current template currentOtherTemplate = templateId; // Set current purpose for Other templates currentPurpose = 'Other'; console.log('selectOtherTemplate: Set currentPurpose to:', currentPurpose); // Set background based on template switch(templateId) { case 'other-template-1': selectedOtherBackground = 'Other-2'; break; case 'other-template-2': selectedOtherBackground = 'Other-5'; break; case 'other-template-3': selectedOtherBackground = 'Other-1'; break; default: selectedOtherBackground = 'Other-2'; } console.log('selectOtherTemplate: Background set to:', selectedOtherBackground); // Set current template for global access window.editorState = window.editorState || {}; window.editorState.currentOtherTemplate = templateId; window.editorState.otherTemplates = otherTemplates; syncEditorState(); // Set default texts in editor inputs if (template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; console.log(`selectOtherTemplate: Set line ${index + 1} to:`, text); } }); } // Set text styles for editor controls if (template.textStyles) { template.textStyles.forEach((style, index) => { console.log(`selectOtherTemplate: Setting style for line ${index + 1}:`, style); // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Force canvas update to ensure Other template is drawn setTimeout(() => { console.log('selectOtherTemplate: Forcing canvas update'); updateEditorCanvas(); }, 50); // Show editor showTemplateEditor(); } // Select Pet Template function selectPetTemplate(templateId) { console.log('selectPetTemplate: Starting with templateId:', templateId); // Remove previous selection document.querySelectorAll('.pet-template-card').forEach(card => { card.classList.remove('selected'); }); // Add selection to current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } const template = petTemplates[templateId]; if (!template) { console.error('selectPetTemplate: Template not found:', templateId); return; } console.log('selectPetTemplate: Template found:', template); // Set current template currentPetTemplate = templateId; // Set current purpose for Pet templates currentPurpose = 'Pet'; console.log('selectPetTemplate: Set currentPurpose to:', currentPurpose); // Set background based on template switch(templateId) { case 'pet-template-1': selectedPetBackground = 'Pet-11'; break; case 'pet-template-2': selectedPetBackground = 'Pet-4'; break; case 'pet-template-3': selectedPetBackground = 'Pet-10'; break; default: selectedPetBackground = 'Pet-11'; } console.log('selectPetTemplate: Background set to:', selectedPetBackground); // Set current template for global access window.editorState = window.editorState || {}; window.editorState.currentPetTemplate = templateId; window.editorState.petTemplates = petTemplates; syncEditorState(); // Set default texts in editor inputs if (template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; console.log(`selectPetTemplate: Set line ${index + 1} to:`, text); } }); } // Set text styles for editor controls if (template.textStyles) { template.textStyles.forEach((style, index) => { console.log(`selectPetTemplate: Setting style for line ${index + 1}:`, style); // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Force canvas update to ensure Pet template is drawn setTimeout(() => { console.log('selectPetTemplate: Forcing canvas update'); updateEditorCanvas(); }, 50); // Show editor showTemplateEditor(); } // Select Retirement Template function selectRetirementTemplate(templateId) { // Remove previous selection document.querySelectorAll('.retirement-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } currentRetirementTemplate = templateId; // Set default background based on template switch(templateId) { case 'retirement-template-1': selectedRetirementBackground = 'Retirement-9'; break; case 'retirement-template-2': selectedRetirementBackground = 'Retirement-10'; break; case 'retirement-template-3': selectedRetirementBackground = 'Retirement-4'; break; default: selectedRetirementBackground = 'Retirement-9'; } console.log('selectRetirementTemplate: Background set to:', selectedRetirementBackground); // Set current template for global access window.editorState = window.editorState || {}; window.editorState.currentRetirementTemplate = templateId; window.editorState.retirementTemplates = retirementTemplates; syncEditorState(); // Populate text fields with default values and initialize editor text settings const template = retirementTemplates[templateId]; if (template && template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; input.placeholder = text; } }); } // Initialize editor text settings with template textStyles as defaults if (template && template.textStyles) { template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', fontWeight: style.fontWeight || 'bold', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || '0px' }; } }); } // Update canvas updateEditorCanvas(); // Show editor showTemplateEditor(); } // Select Prayer Template function selectPrayerTemplate(templateId) { console.log('selectPrayerTemplate: Starting with templateId:', templateId); // Remove previous selection document.querySelectorAll('.prayer-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } currentPrayerTemplate = templateId; const template = prayerTemplates[templateId]; if (!template) { console.error('selectPrayerTemplate: Template not found:', templateId); return; } console.log('selectPrayerTemplate: Template found:', template); // Set background based on template switch (templateId) { case 'prayer-template-1': selectedPrayerBackground = 'Prayer-2'; break; case 'prayer-template-2': selectedPrayerBackground = 'Prayer-9'; break; case 'prayer-template-3': selectedPrayerBackground = 'Prayer-10'; break; default: selectedPrayerBackground = 'Prayer-2'; } console.log('selectPrayerTemplate: Background set to:', selectedPrayerBackground); // Set current template for global access window.editorState = window.editorState || {}; window.editorState.currentPrayerTemplate = templateId; window.editorState.prayerTemplates = prayerTemplates; syncEditorState(); // Set default texts in editor inputs if (template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; console.log(`selectPrayerTemplate: Set line ${index + 1} to:`, text); } }); } // Set text styles from template if (template.textStyles) { template.textStyles.forEach((style, index) => { console.log(`selectPrayerTemplate: Setting style for line ${index + 1}:`, style); // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); // Initialize individual line settings for editor controls template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Update background selection in dialog updateBackgroundSelection(); // Force canvas update to ensure Prayer template is drawn setTimeout(() => { console.log('selectPrayerTemplate: Forcing canvas update'); updateEditorCanvas(); }, 50); // Show editor showTemplateEditor(); } // Show Template Editor function showTemplateEditor() { // Find the appropriate templates container based on current purpose let templatesContainer = null; if (currentPurpose === 'Anniversary') { templatesContainer = document.querySelector('.anniversary-templates-container').parentElement; } else if (currentPurpose === 'Benefit') { templatesContainer = document.querySelector('.benefit-templates-container').parentElement; } else if (currentPurpose === 'Christian') { templatesContainer = document.querySelector('.christian-templates-container').parentElement; } else if (currentPurpose === 'Graduation') { templatesContainer = document.querySelector('.graduation-templates-container').parentElement; } else if (currentPurpose === 'Holiday') { templatesContainer = document.querySelector('.holiday-templates-container').parentElement; } else if (currentPurpose === 'Local School') { templatesContainer = document.querySelector('.local-school-templates-container').parentElement; } else if (currentPurpose === 'Love') { templatesContainer = document.querySelector('.love-templates-container').parentElement; } else if (currentPurpose === 'Marry Me') { templatesContainer = document.querySelector('.marry-me-templates-container').parentElement; } else if (currentPurpose === 'New Born') { templatesContainer = document.querySelector('.newborn-templates-container').parentElement; } else if (currentPurpose === 'Obituary') { templatesContainer = document.querySelector('.obituary-templates-container').parentElement; } else if (currentPurpose === 'Other') { templatesContainer = document.querySelector('.other-templates-container').parentElement; } else if (currentPurpose === 'Pet') { templatesContainer = document.querySelector('.pet-templates-container').parentElement; } else if (currentPurpose === 'Prayer') { templatesContainer = document.querySelector('.prayer-templates-container').parentElement; } else if (currentPurpose === 'Retirement') { templatesContainer = document.querySelector('.retirement-templates-container').parentElement; } else if (currentPurpose === 'Wedding') { templatesContainer = document.querySelector('.wedding-templates-container').parentElement; } else if (currentPurpose === 'Welcome') { templatesContainer = document.querySelector('.welcome-templates-container').parentElement; } const editorContainer = document.getElementById('templateEditorContainer'); if (templatesContainer && editorContainer) { templatesContainer.style.display = 'none'; editorContainer.classList.add('active'); isEditorMode = true; syncEditorState(); // Update editor title based on current purpose const editorTitle = editorContainer.querySelector('.design-section-title'); if (editorTitle && currentPurpose) { editorTitle.textContent = `Customize Your ${currentPurpose} Billboard`; } // Initialize editor controls using professional manager EditorControlsManager.init(); // Initialize editor canvas setTimeout(() => { updateEditorCanvas(); updateBackgroundSelection(); }, 100); } } // Back to Template Selection function backToTemplateSelection() { const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer) { editorContainer.classList.remove('active'); isEditorMode = false; syncEditorState(); } // Show the appropriate template section based on current purpose if (currentPurpose) { showTemplatesForPurpose(currentPurpose); } else { showDefaultTemplateState(); } } // Helper function to scale positions based on canvas size function getScaledPosition(originalPos, canvasWidth, canvasHeight) { // Original canvas design size is 800x400 const originalWidth = 800; const originalHeight = 400; const scaleX = canvasWidth / originalWidth; const scaleY = canvasHeight / originalHeight; return { x: originalPos.x * scaleX, y: originalPos.y * scaleY, width: originalPos.width ? originalPos.width * scaleX : undefined, height: originalPos.height ? originalPos.height * scaleY : undefined, align: originalPos.align }; } // Update Editor Canvas function updateEditorCanvas() { // Sync local state to global state before updating syncEditorState(); // Always use the global version to ensure consistency if (window.updateEditorCanvasGlobal) { console.log('updateEditorCanvas: Delegating to global version'); window.updateEditorCanvasGlobal(); return; } // Fallback to local version if global not available if (!editorCanvas || !editorCtx || (!currentAnniversaryTemplate && !currentBenefitTemplate && !currentChristianTemplate && !currentGraduationTemplate && !currentHolidayTemplate && !currentLocalSchoolTemplate && !currentLoveTemplate && !currentMarryMeTemplate && !currentNewbornTemplate && !currentObituaryTemplate && !currentOtherTemplate && !currentPetTemplate && !currentPrayerTemplate && !currentRetirementTemplate && !currentWeddingTemplate && !currentWelcomeTemplate)) { console.log('updateEditorCanvas: Missing required elements'); return; } let template = null; if (currentAnniversaryTemplate) { template = anniversaryTemplates[currentAnniversaryTemplate]; } else if (currentBenefitTemplate) { template = benefitTemplates[currentBenefitTemplate]; } else if (currentChristianTemplate) { template = christianTemplates[currentChristianTemplate]; } else if (currentGraduationTemplate) { template = graduationTemplates[currentGraduationTemplate]; console.log('updateEditorCanvas: Using graduation template:', currentGraduationTemplate, template); } else if (currentHolidayTemplate) { template = holidayTemplates[currentHolidayTemplate]; console.log('updateEditorCanvas: Using holiday template:', currentHolidayTemplate, template); } else if (currentLocalSchoolTemplate) { template = localSchoolTemplates[currentLocalSchoolTemplate]; console.log('updateEditorCanvas: Using local school template:', currentLocalSchoolTemplate, template); } else if (currentLoveTemplate) { template = loveTemplates[currentLoveTemplate]; console.log('updateEditorCanvas: Using love template:', currentLoveTemplate, template); } else if (currentMarryMeTemplate) { template = marryMeTemplates[currentMarryMeTemplate]; console.log('updateEditorCanvas: Using marry me template:', currentMarryMeTemplate, template); } else if (currentNewbornTemplate) { template = newbornTemplates[currentNewbornTemplate]; console.log('updateEditorCanvas: Using newborn template:', currentNewbornTemplate, template); } else if (currentObituaryTemplate) { template = obituaryTemplates[currentObituaryTemplate]; console.log('updateEditorCanvas: Using obituary template:', currentObituaryTemplate, template); } else if (currentOtherTemplate) { template = otherTemplates[currentOtherTemplate]; console.log('updateEditorCanvas: Using other template:', currentOtherTemplate, template); } else if (currentPetTemplate) { template = petTemplates[currentPetTemplate]; console.log('updateEditorCanvas: Using pet template:', currentPetTemplate, template); } else if (currentPrayerTemplate) { template = prayerTemplates[currentPrayerTemplate]; console.log('updateEditorCanvas: Using prayer template:', currentPrayerTemplate, template); } else if (currentRetirementTemplate) { template = retirementTemplates[currentRetirementTemplate]; console.log('updateEditorCanvas: Using retirement template:', currentRetirementTemplate, template); } else if (currentWeddingTemplate) { template = weddingTemplates[currentWeddingTemplate]; console.log('updateEditorCanvas: Using wedding template:', currentWeddingTemplate, template); } else if (currentWelcomeTemplate) { template = welcomeTemplates[currentWelcomeTemplate]; console.log('updateEditorCanvas: Using welcome template:', currentWelcomeTemplate, template); } if (!template) { console.log('updateEditorCanvas: Template not found. Current templates:', { anniversary: currentAnniversaryTemplate, benefit: currentBenefitTemplate, christian: currentChristianTemplate, graduation: currentGraduationTemplate, holiday: currentHolidayTemplate, localSchool: currentLocalSchoolTemplate, love: currentLoveTemplate, marryMe: currentMarryMeTemplate, newborn: currentNewbornTemplate, obituary: currentObituaryTemplate, other: currentOtherTemplate, pet: currentPetTemplate, prayer: currentPrayerTemplate, retirement: currentRetirementTemplate, wedding: currentWeddingTemplate, welcome: currentWelcomeTemplate }); return; } console.log('updateEditorCanvas: Starting canvas update, uploaded image exists:', !!editorUploadedImage); // Set canvas size to match container const container = editorCanvas.parentElement; const containerRect = container.getBoundingClientRect(); editorCanvas.width = containerRect.width; editorCanvas.height = containerRect.height; // Clear canvas editorCtx.clearRect(0, 0, editorCanvas.width, editorCanvas.height); // Draw background drawEditorBackground(template); } // Make updateEditorCanvas globally accessible with debouncing let updateCanvasTimeout = null; window.updateEditorCanvas = function() { // Debounce canvas updates to prevent excessive calls if (updateCanvasTimeout) { clearTimeout(updateCanvasTimeout); } updateCanvasTimeout = setTimeout(() => { updateEditorCanvas(); }, 50); }; // Create a global version that uses global state with debouncing window.updateEditorCanvasGlobal = function() { const state = window.editorState; console.log('updateEditorCanvasGlobal: State check:', { hasState: !!state, hasCanvas: !!(state && state.editorCanvas), hasCtx: !!(state && state.editorCtx), currentTemplates: state ? { anniversary: state.currentAnniversaryTemplate, benefit: state.currentBenefitTemplate, christian: state.currentChristianTemplate, graduation: state.currentGraduationTemplate, holiday: state.currentHolidayTemplate, localSchool: state.currentLocalSchoolTemplate, love: state.currentLoveTemplate, marryMe: state.currentMarryMeTemplate, newborn: state.currentNewbornTemplate, obituary: state.currentObituaryTemplate, other: state.currentOtherTemplate, pet: state.currentPetTemplate, prayer: state.currentPrayerTemplate, retirement: state.currentRetirementTemplate, wedding: state.currentWeddingTemplate, welcome: state.currentWelcomeTemplate } : null }); if (!state || !state.editorCanvas || !state.editorCtx || (!state.currentAnniversaryTemplate && !state.currentBenefitTemplate && !state.currentChristianTemplate && !state.currentGraduationTemplate && !state.currentHolidayTemplate && !state.currentLocalSchoolTemplate && !state.currentLoveTemplate && !state.currentMarryMeTemplate && !state.currentNewbornTemplate && !state.currentObituaryTemplate && !state.currentOtherTemplate && !state.currentPetTemplate && !state.currentPrayerTemplate && !state.currentRetirementTemplate && !state.currentWeddingTemplate && !state.currentWelcomeTemplate)) { console.log('updateEditorCanvasGlobal: Missing required elements in global state'); return; } let template = null; if (state.currentAnniversaryTemplate) { template = state.anniversaryTemplates[state.currentAnniversaryTemplate]; } else if (state.currentBenefitTemplate) { template = state.benefitTemplates[state.currentBenefitTemplate]; } else if (state.currentChristianTemplate) { template = state.christianTemplates[state.currentChristianTemplate]; } else if (state.currentGraduationTemplate) { template = state.graduationTemplates[state.currentGraduationTemplate]; console.log('updateEditorCanvasGlobal: Using graduation template:', state.currentGraduationTemplate, template); } else if (state.currentHolidayTemplate) { template = state.holidayTemplates[state.currentHolidayTemplate]; console.log('updateEditorCanvasGlobal: Using holiday template:', state.currentHolidayTemplate, template); } else if (state.currentLocalSchoolTemplate) { template = state.localSchoolTemplates[state.currentLocalSchoolTemplate]; console.log('updateEditorCanvasGlobal: Using local school template:', state.currentLocalSchoolTemplate, template); } else if (state.currentLoveTemplate) { template = state.loveTemplates[state.currentLoveTemplate]; console.log('updateEditorCanvasGlobal: Using love template:', state.currentLoveTemplate, template); } else if (state.currentMarryMeTemplate) { template = state.marryMeTemplates[state.currentMarryMeTemplate]; console.log('updateEditorCanvasGlobal: Using marry me template:', state.currentMarryMeTemplate, template); } else if (state.currentNewbornTemplate) { template = state.newbornTemplates[state.currentNewbornTemplate]; console.log('updateEditorCanvasGlobal: Using newborn template:', state.currentNewbornTemplate, template); } else if (state.currentObituaryTemplate) { template = state.obituaryTemplates[state.currentObituaryTemplate]; console.log('updateEditorCanvasGlobal: Using obituary template:', state.currentObituaryTemplate, template); } else if (state.currentOtherTemplate) { template = state.otherTemplates[state.currentOtherTemplate]; console.log('updateEditorCanvasGlobal: Using other template:', state.currentOtherTemplate, template); } else if (state.currentPetTemplate) { template = state.petTemplates[state.currentPetTemplate]; console.log('updateEditorCanvasGlobal: Using pet template:', state.currentPetTemplate, template); } else if (state.currentPrayerTemplate) { template = state.prayerTemplates[state.currentPrayerTemplate]; console.log('updateEditorCanvasGlobal: Using prayer template:', state.currentPrayerTemplate, template); } else if (state.currentRetirementTemplate) { template = state.retirementTemplates[state.currentRetirementTemplate]; console.log('updateEditorCanvasGlobal: Using retirement template:', state.currentRetirementTemplate, template); } else if (state.currentWeddingTemplate) { template = state.weddingTemplates[state.currentWeddingTemplate]; console.log('updateEditorCanvasGlobal: Using wedding template:', state.currentWeddingTemplate, template); } else if (state.currentWelcomeTemplate) { template = state.welcomeTemplates[state.currentWelcomeTemplate]; console.log('updateEditorCanvasGlobal: Using welcome template:', state.currentWelcomeTemplate, template); } if (!template) { console.log('updateEditorCanvasGlobal: Template not found in global state. Available templates:', { anniversaryTemplates: state.anniversaryTemplates ? Object.keys(state.anniversaryTemplates) : 'undefined', benefitTemplates: state.benefitTemplates ? Object.keys(state.benefitTemplates) : 'undefined', christianTemplates: state.christianTemplates ? Object.keys(state.christianTemplates) : 'undefined', graduationTemplates: state.graduationTemplates ? Object.keys(state.graduationTemplates) : 'undefined', holidayTemplates: state.holidayTemplates ? Object.keys(state.holidayTemplates) : 'undefined', localSchoolTemplates: state.localSchoolTemplates ? Object.keys(state.localSchoolTemplates) : 'undefined', loveTemplates: state.loveTemplates ? Object.keys(state.loveTemplates) : 'undefined', marryMeTemplates: state.marryMeTemplates ? Object.keys(state.marryMeTemplates) : 'undefined', newbornTemplates: state.newbornTemplates ? Object.keys(state.newbornTemplates) : 'undefined', obituaryTemplates: state.obituaryTemplates ? Object.keys(state.obituaryTemplates) : 'undefined', otherTemplates: state.otherTemplates ? Object.keys(state.otherTemplates) : 'undefined', petTemplates: state.petTemplates ? Object.keys(state.petTemplates) : 'undefined', prayerTemplates: state.prayerTemplates ? Object.keys(state.prayerTemplates) : 'undefined', retirementTemplates: state.retirementTemplates ? Object.keys(state.retirementTemplates) : 'undefined', weddingTemplates: state.weddingTemplates ? Object.keys(state.weddingTemplates) : 'undefined' }); return; } console.log('updateEditorCanvasGlobal: Starting canvas update, uploaded image exists:', !!state.editorUploadedImage); // Set canvas size to match container const container = state.editorCanvas.parentElement; const containerRect = container.getBoundingClientRect(); state.editorCanvas.width = containerRect.width; state.editorCanvas.height = containerRect.height; // Clear canvas state.editorCtx.clearRect(0, 0, state.editorCanvas.width, state.editorCanvas.height); // Draw background using global state drawEditorBackgroundGlobal(template, state); }; // Global version of drawEditorBackground function drawEditorBackgroundGlobal(template, state) { // Priority: User-selected background > Template default background if (state.selectedBackgroundType === 'color') { // Draw user-selected solid color background state.editorCtx.fillStyle = state.selectedBackgroundColor; state.editorCtx.fillRect(0, 0, state.editorCanvas.width, state.editorCanvas.height); console.log('Color background drawn (global):', state.selectedBackgroundColor); // Draw text and image after background setTimeout(() => { drawEditorTextGlobal(template, state); drawEditorImageGlobal(template, state); console.log('Text and image drawing completed (global)'); }, 20); } else if (state.selectedBackgroundType === 'image') { // Draw image background - determine which background to use based on current template let backgroundName = null; if (state.currentAnniversaryTemplate) { backgroundName = state.selectedAnniversaryBackground; } else if (state.currentBenefitTemplate) { backgroundName = state.selectedBenefitBackground; } else if (state.currentChristianTemplate) { backgroundName = state.selectedChristianBackground; } else if (state.currentGraduationTemplate) { backgroundName = state.selectedGraduationBackground; console.log('drawEditorBackgroundGlobal: Using graduation background:', backgroundName); } else if (state.currentHolidayTemplate) { backgroundName = state.selectedHolidayBackground; console.log('drawEditorBackgroundGlobal: Using holiday background:', backgroundName); } else if (state.currentLocalSchoolTemplate) { backgroundName = state.selectedLocalSchoolBackground; console.log('drawEditorBackgroundGlobal: Using local school background:', backgroundName); } else if (state.currentLoveTemplate) { backgroundName = state.selectedLoveBackground; console.log('drawEditorBackgroundGlobal: Using love background:', backgroundName); } else if (state.currentMarryMeTemplate) { backgroundName = state.selectedMarryMeBackground; console.log('drawEditorBackgroundGlobal: Using marry me background:', backgroundName); } else if (state.currentNewbornTemplate) { backgroundName = state.selectedNewbornBackground; console.log('drawEditorBackgroundGlobal: Using newborn background:', backgroundName); } else if (state.currentObituaryTemplate) { backgroundName = state.selectedObituaryBackground; console.log('drawEditorBackgroundGlobal: Using obituary background:', backgroundName); } else if (state.currentOtherTemplate) { backgroundName = state.selectedOtherBackground; console.log('drawEditorBackgroundGlobal: Using other background:', backgroundName); } else if (state.currentPetTemplate) { backgroundName = state.selectedPetBackground; console.log('drawEditorBackgroundGlobal: Using pet background:', backgroundName); } else if (state.currentPrayerTemplate) { backgroundName = state.selectedPrayerBackground; console.log('drawEditorBackgroundGlobal: Using prayer background:', backgroundName); } else if (state.currentRetirementTemplate) { backgroundName = state.selectedRetirementBackground; console.log('drawEditorBackgroundGlobal: Using retirement background:', backgroundName); } else if (state.currentWeddingTemplate) { backgroundName = state.selectedWeddingBackground; console.log('drawEditorBackgroundGlobal: Using wedding background:', backgroundName); } else if (state.currentWelcomeTemplate) { backgroundName = state.selectedWelcomeBackground; console.log('drawEditorBackgroundGlobal: Using welcome background:', backgroundName); } if (!backgroundName) { console.error('No background name found in global state. Current state:', { currentAnniversaryTemplate: state.currentAnniversaryTemplate, currentBenefitTemplate: state.currentBenefitTemplate, currentChristianTemplate: state.currentChristianTemplate, currentGraduationTemplate: state.currentGraduationTemplate, currentHolidayTemplate: state.currentHolidayTemplate, currentLocalSchoolTemplate: state.currentLocalSchoolTemplate, currentLoveTemplate: state.currentLoveTemplate, currentMarryMeTemplate: state.currentMarryMeTemplate, currentNewbornTemplate: state.currentNewbornTemplate, currentObituaryTemplate: state.currentObituaryTemplate, currentOtherTemplate: state.currentOtherTemplate, currentPetTemplate: state.currentPetTemplate, selectedAnniversaryBackground: state.selectedAnniversaryBackground, selectedBenefitBackground: state.selectedBenefitBackground, selectedChristianBackground: state.selectedChristianBackground, selectedGraduationBackground: state.selectedGraduationBackground, selectedHolidayBackground: state.selectedHolidayBackground, selectedLocalSchoolBackground: state.selectedLocalSchoolBackground, selectedLoveBackground: state.selectedLoveBackground, selectedMarryMeBackground: state.selectedMarryMeBackground, selectedNewbornBackground: state.selectedNewbornBackground, selectedObituaryBackground: state.selectedObituaryBackground, selectedOtherBackground: state.selectedOtherBackground, selectedPetBackground: state.selectedPetBackground }); return; } // Use 2025/07 for Holiday and Local School images, 2025/06 for others including Pet const urlPath = (backgroundName.startsWith('Holiday-') || backgroundName.startsWith('Local-Schools-')) ? '2025/07' : '2025/06'; const backgroundUrl = `https://www.borgesmedia.com/wp-content/uploads/${urlPath}/${backgroundName}.png`; const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function() { state.editorCtx.drawImage(img, 0, 0, state.editorCanvas.width, state.editorCanvas.height); console.log('Background image loaded and drawn (global)'); // Draw text and image after background loads setTimeout(() => { drawEditorTextGlobal(template, state); drawEditorImageGlobal(template, state); console.log('Text and image drawing completed (global)'); }, 20); }; img.onerror = function() { console.error('Failed to load background image (global):', backgroundUrl); // Draw template default background color as fallback if (template && template.defaultBackground && template.defaultBackground.startsWith('#')) { state.editorCtx.fillStyle = template.defaultBackground; state.editorCtx.fillRect(0, 0, state.editorCanvas.width, state.editorCanvas.height); console.log('Template default background drawn after image load failure (global):', template.defaultBackground); } else { // Final fallback: white background state.editorCtx.fillStyle = '#ffffff'; state.editorCtx.fillRect(0, 0, state.editorCanvas.width, state.editorCanvas.height); console.log('White background drawn after image load failure (global)'); } // Still try to draw text and image even if background fails setTimeout(() => { drawEditorTextGlobal(template, state); drawEditorImageGlobal(template, state); }, 20); }; img.src = backgroundUrl; } else if (template && template.defaultBackground && template.defaultBackground.startsWith('#')) { // Fallback: Draw template default color background if no user selection state.editorCtx.fillStyle = template.defaultBackground; state.editorCtx.fillRect(0, 0, state.editorCanvas.width, state.editorCanvas.height); console.log('Template default color background drawn as fallback (global):', template.defaultBackground); // Draw text and image after background setTimeout(() => { drawEditorTextGlobal(template, state); drawEditorImageGlobal(template, state); console.log('Text and image drawing completed (global)'); }, 20); } else { // Final fallback: Draw a default background color to prevent black screen state.editorCtx.fillStyle = '#ffffff'; state.editorCtx.fillRect(0, 0, state.editorCanvas.width, state.editorCanvas.height); console.log('Final fallback: White background drawn (global)'); // Draw text and image after background setTimeout(() => { drawEditorTextGlobal(template, state); drawEditorImageGlobal(template, state); console.log('Text and image drawing completed (global)'); }, 20); } } // Global version of drawEditorImage function drawEditorImageGlobal(template, state) { // Skip image drawing for text-only templates if (!template.imagePosition || template.type === 'text-only') return; console.log('Drawing editor image (global), template type:', template.type, 'defaultImage:', template.defaultImage, 'editorUploadedImage exists:', !!state.editorUploadedImage); const originalPos = template.imagePosition; const scaledPos = getScaledPositionGlobal(originalPos, state.editorCanvas.width, state.editorCanvas.height); if (template.type === 'full-image') { // Template 1: Full-size image const imageToUse = state.editorUploadedImage || template.defaultImage; if (imageToUse) { if (typeof imageToUse === 'string') { // Use preloaded image for instant display const preloadedImg = preloadedImages[imageToUse]; if (preloadedImg && preloadedImg.complete && preloadedImg.naturalWidth > 0) { try { state.editorCtx.drawImage(preloadedImg, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); console.log('Preloaded image drawn instantly (global):', imageToUse, 'at position:', scaledPos); } catch (error) { console.error('Error drawing preloaded image (global):', error); } } else { // Fallback to loading image if not preloaded const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function() { try { state.editorCtx.drawImage(img, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); console.log('Default image loaded and drawn (global):', imageToUse, 'at position:', scaledPos); } catch (error) { console.error('Error drawing default image (global):', error); } }; img.onerror = function() { console.error('Failed to load default image (global):', imageToUse); // Try fallback image const fallbackImg = preloadedImages['https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg']; if (fallbackImg && fallbackImg.complete && fallbackImg.naturalWidth > 0) { try { state.editorCtx.drawImage(fallbackImg, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); console.log('Fallback image drawn instantly (global)'); } catch (error) { console.error('Error drawing fallback image (global):', error); } } }; img.src = imageToUse; } } else { // Draw uploaded image try { state.editorCtx.drawImage(imageToUse, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); console.log('Uploaded image drawn for full-image template (global)'); } catch (error) { console.error('Error drawing uploaded image (global):', error); } } } } else if (template.type === 'placeholder-space') { // Template 2: Placeholder space if (state.editorUploadedImage) { try { state.editorCtx.drawImage(state.editorUploadedImage, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); console.log('Uploaded image drawn for placeholder-space template (global)'); } catch (error) { console.error('Error drawing uploaded image for placeholder (global):', error); } } else { // Draw placeholder with scaled dimensions state.editorCtx.save(); state.editorCtx.strokeStyle = '#ddd'; const scaledDash = 10 * (state.editorCanvas.width / 800); state.editorCtx.setLineDash([scaledDash, scaledDash / 2]); state.editorCtx.lineWidth = 2 * (state.editorCanvas.width / 800); state.editorCtx.strokeRect(scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); // Placeholder text with scaled font state.editorCtx.fillStyle = '#666'; const scaledFontSize = 16 * (state.editorCanvas.width / 800); state.editorCtx.font = `${scaledFontSize}px Arial`; state.editorCtx.textAlign = 'center'; //state.editorCtx.fillText(template.placeholderText, scaledPos.x + scaledPos.width/2, scaledPos.y + scaledPos.height/2); state.editorCtx.restore(); console.log('Placeholder drawn for placeholder-space template (global)'); } } else if (template.type === 'centered-image') { // Template 3: Centered smaller image const imageToUse = state.editorUploadedImage || template.defaultImage; if (imageToUse) { if (typeof imageToUse === 'string') { // Load default image const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function() { // Draw circular image with scaled dimensions state.editorCtx.save(); state.editorCtx.beginPath(); state.editorCtx.arc(scaledPos.x + scaledPos.width/2, scaledPos.y + scaledPos.height/2, scaledPos.width/2, 0, 2 * Math.PI); state.editorCtx.clip(); state.editorCtx.drawImage(img, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); state.editorCtx.restore(); // Draw white border with scaled width state.editorCtx.beginPath(); state.editorCtx.arc(scaledPos.x + scaledPos.width/2, scaledPos.y + scaledPos.height/2, scaledPos.width/2, 0, 2 * Math.PI); state.editorCtx.strokeStyle = 'white'; state.editorCtx.lineWidth = 6 * (state.editorCanvas.width / 800); state.editorCtx.stroke(); console.log('Default image drawn for centered-image template (global)'); }; img.src = imageToUse; } else { // Draw uploaded image (circular) with scaled dimensions try { state.editorCtx.save(); state.editorCtx.beginPath(); state.editorCtx.arc(scaledPos.x + scaledPos.width/2, scaledPos.y + scaledPos.height/2, scaledPos.width/2, 0, 2 * Math.PI); state.editorCtx.clip(); state.editorCtx.drawImage(state.editorUploadedImage, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); state.editorCtx.restore(); // Draw white border with scaled width state.editorCtx.beginPath(); state.editorCtx.arc(scaledPos.x + scaledPos.width/2, scaledPos.y + scaledPos.height/2, scaledPos.width/2, 0, 2 * Math.PI); state.editorCtx.strokeStyle = 'white'; state.editorCtx.lineWidth = 6 * (state.editorCanvas.width / 800); state.editorCtx.stroke(); console.log('Uploaded image drawn for centered-image template (global)'); } catch (error) { console.error('Error drawing uploaded image for centered template (global):', error); } } } } } // Global version of drawEditorText function drawEditorTextGlobal(template, state) { const textInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; textInputs.forEach((lineId, index) => { const input = document.getElementById(lineId); const text = input ? input.value : ''; if (text.trim()) { // Use editor settings (which may have been initialized from template styles) let settings = state.editorTextSettings[lineId]; const originalPosition = template.textPositions[index]; const scaledPosition = getScaledPositionGlobal(originalPosition, state.editorCanvas.width, state.editorCanvas.height); state.editorCtx.save(); // Scale font size proportionally const fontSize = parseInt(settings.fontSize) || settings.fontSize; const scaledFontSize = fontSize * (state.editorCanvas.width / 800); // Build font string with weight and style let fontString = ''; if (settings.fontWeight) fontString += settings.fontWeight + ' '; if (settings.fontStyle) fontString += settings.fontStyle + ' '; fontString += `${scaledFontSize}px ${settings.fontFamily}`; state.editorCtx.font = fontString; state.editorCtx.textAlign = scaledPosition.align; state.editorCtx.fillStyle = settings.color; // Add letter spacing if specified if (settings.letterSpacing) { state.editorCtx.letterSpacing = settings.letterSpacing; } // Clear any existing shadow settings to prevent accumulation state.editorCtx.shadowColor = 'transparent'; state.editorCtx.shadowBlur = 0; state.editorCtx.shadowOffsetX = 0; state.editorCtx.shadowOffsetY = 0; // Draw shadow manually if enabled (more reliable than canvas shadow properties) if (settings.shadow) { const shadowWidth = settings.shadowWidth !== undefined ? settings.shadowWidth : 4; const scaledShadowWidth = shadowWidth * (state.editorCanvas.width / 800); // Draw shadow text first state.editorCtx.fillStyle = 'rgba(0,0,0,0.7)'; state.editorCtx.fillText(text, scaledPosition.x + scaledShadowWidth / 2, scaledPosition.y + scaledShadowWidth / 2); } // Draw main text with original color state.editorCtx.fillStyle = settings.color; state.editorCtx.fillText(text, scaledPosition.x, scaledPosition.y); state.editorCtx.restore(); } }); } // Global version of getScaledPosition function getScaledPositionGlobal(originalPos, canvasWidth, canvasHeight) { const scaleX = canvasWidth / 800; const scaleY = canvasHeight / 400; return { x: originalPos.x * scaleX, y: originalPos.y * scaleY, width: originalPos.width ? originalPos.width * scaleX : undefined, height: originalPos.height ? originalPos.height * scaleY : undefined, align: originalPos.align }; } // Universal Editor Canvas Update - Works for any purpose function updateUniversalEditorCanvas() { const state = window.editorState; if (!state || !state.currentTemplate || !state.currentPurpose) { console.log('updateUniversalEditorCanvas: Missing required state'); return; } // Get canvas elements const editorCanvas = document.getElementById('editorCanvas'); const editorCtx = editorCanvas ? editorCanvas.getContext('2d') : null; if (!editorCanvas || !editorCtx) { console.log('updateUniversalEditorCanvas: Canvas not found'); return; } // Set canvas size to match container const container = editorCanvas.parentElement; const containerRect = container.getBoundingClientRect(); editorCanvas.width = containerRect.width; editorCanvas.height = containerRect.height; // Clear canvas editorCtx.clearRect(0, 0, editorCanvas.width, editorCanvas.height); // Get template configuration const template = state.templateConfig; const purposeConfig = state.purposeConfig; if (!template || !purposeConfig) { console.log('updateUniversalEditorCanvas: Template configuration not found'); return; } // Draw background if (template.backgroundImage) { // Draw background image (for Anniversary templates) const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function() { editorCtx.drawImage(img, 0, 0, editorCanvas.width, editorCanvas.height); // Draw text after background loads setTimeout(() => { drawUniversalEditorText(editorCanvas, editorCtx, template, purposeConfig); }, 20); }; img.onerror = function() { console.warn('Failed to load background image, using fallback'); // Fallback to solid color editorCtx.fillStyle = '#000000'; editorCtx.fillRect(0, 0, editorCanvas.width, editorCanvas.height); drawUniversalEditorText(editorCanvas, editorCtx, template, purposeConfig); }; img.src = template.backgroundImage; } else if (template.backgroundColor) { // Draw solid color background editorCtx.fillStyle = template.backgroundColor; editorCtx.fillRect(0, 0, editorCanvas.width, editorCanvas.height); // Draw text immediately drawUniversalEditorText(editorCanvas, editorCtx, template, purposeConfig); } else { // No background, just draw text drawUniversalEditorText(editorCanvas, editorCtx, template, purposeConfig); } } // Draw text for universal templates function drawUniversalEditorText(canvas, ctx, template, purposeConfig) { if (!template.textPositions || !template.textStyles) return; // Get current text values from inputs const textInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; textInputs.forEach((inputId, index) => { const input = document.getElementById(inputId); if (!input || !input.value.trim()) return; const text = input.value.trim(); const position = template.textPositions[index]; const style = template.textStyles[index]; if (!position || !style) return; // Scale position for canvas size const scaleX = canvas.width / 800; const scaleY = canvas.height / 400; const x = position.x * scaleX; const y = position.y * scaleY; // Apply text style ctx.save(); ctx.fillStyle = style.color || '#ffffff'; ctx.textAlign = position.align || 'center'; ctx.textBaseline = 'middle'; // Build font string let fontString = ''; if (style.fontStyle) fontString += style.fontStyle + ' '; if (style.fontWeight) fontString += style.fontWeight + ' '; const fontSize = parseInt(style.fontSize) || 24; const scaledFontSize = fontSize * Math.min(scaleX, scaleY); fontString += scaledFontSize + 'px '; fontString += style.fontFamily || 'Arial'; ctx.font = fontString; // Apply letter spacing if specified if (style.letterSpacing && style.letterSpacing !== 'normal') { // For letter spacing, we need to draw each character separately const spacing = parseFloat(style.letterSpacing) || 0; let currentX = x - (ctx.measureText(text).width / 2); for (let i = 0; i Template default background if (selectedBackgroundType === 'color') { // Draw user-selected solid color background editorCtx.fillStyle = selectedBackgroundColor; editorCtx.fillRect(0, 0, editorCanvas.width, editorCanvas.height); console.log('Color background drawn:', selectedBackgroundColor); // Draw text and image after background setTimeout(() => { drawEditorText(template); drawEditorImage(template); console.log('Text and image drawing completed'); }, 20); } else if (selectedBackgroundType === 'image') { // Draw image background - determine which background to use based on purpose let backgroundName = null; if (currentPurpose === 'Anniversary') { backgroundName = selectedAnniversaryBackground; } else if (currentPurpose === 'Benefit') { backgroundName = selectedBenefitBackground; } else if (currentPurpose === 'Christian') { backgroundName = selectedChristianBackground; } else if (currentPurpose === 'Graduation') { backgroundName = selectedGraduationBackground; } else if (currentPurpose === 'Holiday') { backgroundName = selectedHolidayBackground; } else if (currentPurpose === 'Local School') { backgroundName = selectedLocalSchoolBackground; } else if (currentPurpose === 'Love') { backgroundName = selectedLoveBackground; } else if (currentPurpose === 'Marry Me') { backgroundName = selectedMarryMeBackground; } else if (currentPurpose === 'New Born') { backgroundName = selectedNewbornBackground; } else if (currentPurpose === 'Obituary') { backgroundName = selectedObituaryBackground; } else if (currentPurpose === 'Other') { backgroundName = selectedOtherBackground; } else if (currentPurpose === 'Pet') { backgroundName = selectedPetBackground; } else if (currentPurpose === 'Prayer') { backgroundName = selectedPrayerBackground; } else if (currentPurpose === 'Retirement') { backgroundName = selectedRetirementBackground; } else if (currentPurpose === 'Wedding') { backgroundName = selectedWeddingBackground; } else if (currentPurpose === 'Welcome') { backgroundName = selectedWelcomeBackground; } if (!backgroundName) { console.error('No background name found for purpose:', currentPurpose); return; } // Use 2025/07 for Holiday and Local School images, 2025/06 for others const urlPath = (backgroundName.startsWith('Holiday-') || backgroundName.startsWith('Local-Schools-')) ? '2025/07' : '2025/06'; const backgroundUrl = `https://www.borgesmedia.com/wp-content/uploads/${urlPath}/${backgroundName}.png`; const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function() { editorCtx.drawImage(img, 0, 0, editorCanvas.width, editorCanvas.height); console.log('Background image loaded and drawn'); // Draw text and image after background loads setTimeout(() => { drawEditorText(template); drawEditorImage(template); console.log('Text and image drawing completed'); }, 20); }; img.onerror = function() { console.error('Failed to load background image:', backgroundUrl); // Draw template default background color as fallback if (template && template.defaultBackground && template.defaultBackground.startsWith('#')) { editorCtx.fillStyle = template.defaultBackground; editorCtx.fillRect(0, 0, editorCanvas.width, editorCanvas.height); console.log('Template default background drawn after image load failure:', template.defaultBackground); } else { // Final fallback: white background editorCtx.fillStyle = '#ffffff'; editorCtx.fillRect(0, 0, editorCanvas.width, editorCanvas.height); console.log('White background drawn after image load failure'); } // Still try to draw text and image even if background fails setTimeout(() => { drawEditorText(template); drawEditorImage(template); }, 20); }; img.src = backgroundUrl; } else if (template && template.defaultBackground && template.defaultBackground.startsWith('#')) { // Fallback: Draw template default color background if no user selection editorCtx.fillStyle = template.defaultBackground; editorCtx.fillRect(0, 0, editorCanvas.width, editorCanvas.height); console.log('Template default color background drawn as fallback:', template.defaultBackground); // Draw text and image after background setTimeout(() => { drawEditorText(template); drawEditorImage(template); console.log('Text and image drawing completed'); }, 20); } else { // Final fallback: Draw a default background color to prevent black screen editorCtx.fillStyle = '#ffffff'; editorCtx.fillRect(0, 0, editorCanvas.width, editorCanvas.height); console.log('Final fallback: White background drawn'); // Draw text and image after background setTimeout(() => { drawEditorText(template); drawEditorImage(template); console.log('Text and image drawing completed'); }, 20); } } // Draw Editor Text function drawEditorText(template) { const textInputs = ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4']; textInputs.forEach((lineId, index) => { const input = document.getElementById(lineId); const text = input ? input.value : ''; if (text.trim()) { // Use editor settings (which may have been initialized from template styles) let settings; if (window.editorState && window.editorState.editorTextSettings && window.editorState.editorTextSettings[lineId]) { settings = window.editorState.editorTextSettings[lineId]; } else { settings = editorTextSettings[lineId]; } const originalPosition = template.textPositions[index]; const scaledPosition = getScaledPosition(originalPosition, editorCanvas.width, editorCanvas.height); editorCtx.save(); // Scale font size proportionally const fontSize = parseInt(settings.fontSize) || settings.fontSize; const scaledFontSize = fontSize * (editorCanvas.width / 800); // Build font string with weight and style let fontString = ''; if (settings.fontWeight) fontString += settings.fontWeight + ' '; if (settings.fontStyle) fontString += settings.fontStyle + ' '; fontString += `${scaledFontSize}px ${settings.fontFamily}`; editorCtx.font = fontString; editorCtx.textAlign = scaledPosition.align; editorCtx.fillStyle = settings.color; // Add letter spacing if specified if (settings.letterSpacing) { editorCtx.letterSpacing = settings.letterSpacing; } // Clear any existing shadow settings to prevent accumulation editorCtx.shadowColor = 'transparent'; editorCtx.shadowBlur = 0; editorCtx.shadowOffsetX = 0; editorCtx.shadowOffsetY = 0; // Draw shadow manually if enabled (more reliable than canvas shadow properties) if (settings.shadow) { const shadowWidth = settings.shadowWidth !== undefined ? settings.shadowWidth : 4; const scaledShadowWidth = shadowWidth * (editorCanvas.width / 800); // Draw shadow text first editorCtx.fillStyle = 'rgba(0,0,0,0.7)'; editorCtx.fillText(text, scaledPosition.x + scaledShadowWidth / 2, scaledPosition.y + scaledShadowWidth / 2); } // Draw main text with original color editorCtx.fillStyle = settings.color; editorCtx.fillText(text, scaledPosition.x, scaledPosition.y); editorCtx.restore(); } }); } // Draw Editor Image function drawEditorImage(template) { // Skip image drawing for text-only templates if (!template.imagePosition || template.type === 'text-only') return; // Check both local and global state for uploaded image const globalUploadedImage = window.editorState ? window.editorState.editorUploadedImage : null; const imageFromState = editorUploadedImage || globalUploadedImage; console.log('Drawing editor image, template type:', template.type, 'defaultImage:', template.defaultImage, 'local image exists:', !!editorUploadedImage, 'global image exists:', !!globalUploadedImage); const originalPos = template.imagePosition; const scaledPos = getScaledPosition(originalPos, editorCanvas.width, editorCanvas.height); if (template.type === 'full-image') { // Template 1: Full-size image const imageToUse = imageFromState || template.defaultImage; if (imageToUse) { if (typeof imageToUse === 'string') { // Use preloaded image for instant display const preloadedImg = preloadedImages[imageToUse]; if (preloadedImg && preloadedImg.complete && preloadedImg.naturalWidth > 0) { try { editorCtx.drawImage(preloadedImg, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); console.log('Preloaded image drawn instantly:', imageToUse, 'at position:', scaledPos); } catch (error) { console.error('Error drawing preloaded image:', error); } } else { // Fallback to loading image if not preloaded const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function() { try { editorCtx.drawImage(img, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); console.log('Default image loaded and drawn:', imageToUse, 'at position:', scaledPos); } catch (error) { console.error('Error drawing default image:', error); } }; img.onerror = function() { console.error('Failed to load default image:', imageToUse); // Try fallback image const fallbackImg = preloadedImages['https://www.borgesmedia.com/wp-content/uploads/2025/06/default-image-person.jpg']; if (fallbackImg && fallbackImg.complete && fallbackImg.naturalWidth > 0) { try { editorCtx.drawImage(fallbackImg, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); console.log('Fallback image drawn instantly'); } catch (error) { console.error('Error drawing fallback image:', error); } } }; img.src = imageToUse; } } else { // Draw uploaded image try { editorCtx.drawImage(imageToUse, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); console.log('Uploaded image drawn for full-image template'); } catch (error) { console.error('Error drawing uploaded image:', error); } } } } else if (template.type === 'placeholder-space') { // Template 2: Placeholder space if (imageFromState) { try { editorCtx.drawImage(imageFromState, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); console.log('Uploaded image drawn for placeholder-space template'); } catch (error) { console.error('Error drawing uploaded image for placeholder:', error); } } else { // Draw placeholder with scaled dimensions editorCtx.save(); editorCtx.strokeStyle = '#ddd'; const scaledDash = 10 * (editorCanvas.width / 800); editorCtx.setLineDash([scaledDash, scaledDash / 2]); editorCtx.lineWidth = 2 * (editorCanvas.width / 800); editorCtx.strokeRect(scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); // Placeholder text with scaled font editorCtx.fillStyle = '#666'; const scaledFontSize = 16 * (editorCanvas.width / 800); editorCtx.font = `${scaledFontSize}px Arial`; editorCtx.textAlign = 'center'; //editorCtx.fillText(template.placeholderText, scaledPos.x + scaledPos.width/2, scaledPos.y + scaledPos.height/2); editorCtx.restore(); console.log('Placeholder drawn for placeholder-space template'); } } else if (template.type === 'centered-image') { // Template 3: Centered smaller image const imageToUse = imageFromState || template.defaultImage; if (imageToUse) { if (typeof imageToUse === 'string') { // Load default image const img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function() { // Draw circular image with scaled dimensions editorCtx.save(); editorCtx.beginPath(); editorCtx.arc(scaledPos.x + scaledPos.width/2, scaledPos.y + scaledPos.height/2, scaledPos.width/2, 0, 2 * Math.PI); editorCtx.clip(); editorCtx.drawImage(img, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); editorCtx.restore(); // Draw white border with scaled width editorCtx.beginPath(); editorCtx.arc(scaledPos.x + scaledPos.width/2, scaledPos.y + scaledPos.height/2, scaledPos.width/2, 0, 2 * Math.PI); editorCtx.strokeStyle = 'white'; editorCtx.lineWidth = 6 * (editorCanvas.width / 800); editorCtx.stroke(); console.log('Default image drawn for centered-image template'); }; img.src = imageToUse; } else { // Draw uploaded image (circular) with scaled dimensions try { editorCtx.save(); editorCtx.beginPath(); editorCtx.arc(scaledPos.x + scaledPos.width/2, scaledPos.y + scaledPos.height/2, scaledPos.width/2, 0, 2 * Math.PI); editorCtx.clip(); editorCtx.drawImage(imageFromState, scaledPos.x, scaledPos.y, scaledPos.width, scaledPos.height); editorCtx.restore(); // Draw white border with scaled width editorCtx.beginPath(); editorCtx.arc(scaledPos.x + scaledPos.width/2, scaledPos.y + scaledPos.height/2, scaledPos.width/2, 0, 2 * Math.PI); editorCtx.strokeStyle = 'white'; editorCtx.lineWidth = 6 * (editorCanvas.width / 800); editorCtx.stroke(); console.log('Uploaded image drawn for centered-image template'); } catch (error) { console.error('Error drawing uploaded image for centered template:', error); } } } } } // Handle Editor Photo Upload function handleEditorPhotoUpload(event) { const file = event.target.files[0]; const validationDiv = document.getElementById('editorPhotoValidation'); if (!file) { if (validationDiv) { validationDiv.style.display = 'none'; } return; } // Validate file format const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png']; if (!allowedTypes.includes(file.type.toLowerCase())) { showPhotoValidation('error', 'Please upload a JPG or PNG image file only.'); event.target.value = ''; // Clear the input return; } // Show success message for correct format showPhotoValidation('success', 'File format accepted. Processing image...'); if (file && file.type.startsWith('image/')) { const reader = new FileReader(); reader.onload = function(e) { const img = new Image(); img.onload = function() { // Check image resolution const width = img.naturalWidth; const height = img.naturalHeight; const minRecommendedWidth = 1200; const minRecommendedHeight = 800; if (width < minRecommendedWidth || height = maxLength * 0.9) { // 90% of limit counter.classList.add('error'); } else if (currentLength >= maxLength * 0.8) { // 80% of limit counter.classList.add('warning'); } } } // Show Background Graphic Dialog with state restoration function showBackgroundGraphicDialog() { const dialog = document.getElementById('backgroundGraphicDialog'); if (dialog) { // Update dialog title based on current purpose const dialogTitle = dialog.querySelector('h3'); if (dialogTitle) { if (currentPurpose === 'Anniversary') { dialogTitle.textContent = 'Select Anniversary Background'; } else if (currentPurpose === 'Benefit') { dialogTitle.textContent = 'Select Benefit Background'; } else if (currentPurpose === 'Christian') { dialogTitle.textContent = 'Select Christian Background'; } else if (currentPurpose === 'Graduation') { dialogTitle.textContent = 'Select Graduation Background'; } else if (currentPurpose === 'Holiday') { dialogTitle.textContent = 'Select Holiday Background'; } else if (currentPurpose === 'Local School') { dialogTitle.textContent = 'Select Local School Background'; } else if (currentPurpose === 'Love') { dialogTitle.textContent = 'Select Love Background'; } else if (currentPurpose === 'Marry Me') { dialogTitle.textContent = 'Select Marry Me Background'; } else if (currentPurpose === 'New Born') { dialogTitle.textContent = 'Select Newborn Background'; } else if (currentPurpose === 'Obituary') { dialogTitle.textContent = 'Select Obituary Background'; } else if (currentPurpose === 'Other') { dialogTitle.textContent = 'Select Other Background'; } else if (currentPurpose === 'Pet') { dialogTitle.textContent = 'Select Pet Background'; } else if (currentPurpose === 'Prayer') { dialogTitle.textContent = 'Select Prayer Background'; } else if (currentPurpose === 'Retirement') { dialogTitle.textContent = 'Select Retirement Background'; } else if (currentPurpose === 'Wedding') { dialogTitle.textContent = 'Select Wedding Background'; } else if (currentPurpose === 'Welcome') { dialogTitle.textContent = 'Select Welcome Background'; } else { dialogTitle.textContent = 'Select Background'; } } // Initialize the appropriate backgrounds based on current purpose if (currentPurpose === 'Anniversary') { initAnniversaryBackgrounds(); } else if (currentPurpose === 'Benefit') { initBenefitBackgrounds(); } else if (currentPurpose === 'Christian') { initChristianBackgrounds(); } else if (currentPurpose === 'Graduation') { initGraduationBackgrounds(); } else if (currentPurpose === 'Holiday') { initHolidayBackgrounds(); } else if (currentPurpose === 'Local School') { initLocalSchoolBackgrounds(); } else if (currentPurpose === 'Love') { initLoveBackgrounds(); } else if (currentPurpose === 'Marry Me') { initMarryMeBackgrounds(); } else if (currentPurpose === 'New Born') { initNewbornBackgrounds(); } else if (currentPurpose === 'Obituary') { initObituaryBackgrounds(); } else if (currentPurpose === 'Other') { initOtherBackgrounds(); } else if (currentPurpose === 'Pet') { initPetBackgrounds(); } else if (currentPurpose === 'Prayer') { initPrayerBackgrounds(); } else if (currentPurpose === 'Retirement') { initRetirementBackgrounds(); } else if (currentPurpose === 'Wedding') { initWeddingBackgrounds(); } else if (currentPurpose === 'Welcome') { initWelcomeBackgrounds(); } else { // Default to Anniversary if no purpose is set initAnniversaryBackgrounds(); } // CRITICAL FIX: Set initial background type state before showing dialog // This ensures the correct background type is selected when dialog opens const imageBtn = document.getElementById('imageBackgroundBtn'); const colorBtn = document.getElementById('colorBackgroundBtn'); const imageSection = document.getElementById('imageBackgroundSection'); const colorSection = document.getElementById('colorBackgroundSection'); if (imageBtn && colorBtn && imageSection && colorSection) { // Update button states based on current background type if (selectedBackgroundType === 'color') { colorBtn.classList.add('active'); imageBtn.classList.remove('active'); imageSection.style.display = 'none'; colorSection.style.display = 'block'; } else { imageBtn.classList.add('active'); colorBtn.classList.remove('active'); imageSection.style.display = 'block'; colorSection.style.display = 'none'; } console.log('showBackgroundGraphicDialog: Background type state set to:', selectedBackgroundType); } try { dialog.showModal(); // Ensure proper centering dialog.style.top = '50%'; dialog.style.left = '50%'; dialog.style.transform = 'translate(-50%, -50%)'; dialog.style.margin = 'auto'; console.log('Background graphic dialog opened using modal method'); } catch (error) { // Fallback for browsers that don't support showModal dialog.classList.add('show'); dialog.style.top = '50%'; dialog.style.left = '50%'; dialog.style.transform = 'translate(-50%, -50%)'; dialog.style.margin = 'auto'; console.log('Background graphic dialog opened using fallback method'); } // Restore background selection state when dialog opens setTimeout(() => { restoreBackgroundDialogState(); }, 100); } } // Restore background dialog state from saved data function restoreBackgroundDialogState() { console.log('restoreBackgroundDialogState: Restoring background dialog state...'); try { // Get saved background state const savedBackgroundState = localStorage.getItem('editorBackgroundState'); if (savedBackgroundState) { const backgroundState = JSON.parse(savedBackgroundState); console.log('restoreBackgroundDialogState: Found saved background state:', backgroundState); // Restore background type selection if (backgroundState.type) { const typeButtons = document.querySelectorAll('.background-type-btn'); typeButtons.forEach(btn => { btn.classList.remove('active'); if (btn.dataset.type === backgroundState.type) { btn.classList.add('active'); } }); // Show/hide appropriate sections const imageSection = document.getElementById('imageBackgroundSection'); const colorSection = document.getElementById('colorBackgroundSection'); if (imageSection && colorSection) { if (backgroundState.type === 'image') { imageSection.style.display = 'block'; colorSection.style.display = 'none'; } else { imageSection.style.display = 'none'; colorSection.style.display = 'block'; } } } // Restore graphic selection if (backgroundState.graphic) { const backgroundOptions = document.querySelectorAll('.stockImage-bg-option'); backgroundOptions.forEach(option => { option.classList.remove('selected'); if (option.dataset.background === backgroundState.graphic) { option.classList.add('selected'); } }); } // Update global state based on current purpose if (window.editorState) { window.editorState.selectedBackgroundType = backgroundState.type || 'image'; window.editorState.selectedBackgroundColor = backgroundState.color || '#ff0000'; // Set the appropriate background based on current purpose if (currentPurpose === 'Anniversary') { window.editorState.selectedAnniversaryBackground = backgroundState.graphic || 'Anniversary-1'; } else if (currentPurpose === 'Benefit') { window.editorState.selectedBenefitBackground = backgroundState.graphic || 'Benefit-3'; } else if (currentPurpose === 'Christian') { window.editorState.selectedChristianBackground = backgroundState.graphic || 'Christian-1'; } else if (currentPurpose === 'Graduation') { window.editorState.selectedGraduationBackground = backgroundState.graphic || 'Graduation-1'; } else if (currentPurpose === 'Holiday') { window.editorState.selectedHolidayBackground = backgroundState.graphic || 'Holiday-1'; } else if (currentPurpose === 'Local School') { window.editorState.selectedLocalSchoolBackground = backgroundState.graphic || 'Local-Schools-1'; } else if (currentPurpose === 'Love') { window.editorState.selectedLoveBackground = backgroundState.graphic || 'Love-6'; } else if (currentPurpose === 'Marry Me') { window.editorState.selectedMarryMeBackground = backgroundState.graphic || 'Marry-Me-5'; } else if (currentPurpose === 'New Born') { window.editorState.selectedNewbornBackground = backgroundState.graphic || 'New-Born-1'; } else if (currentPurpose === 'Obituary') { window.editorState.selectedObituaryBackground = backgroundState.graphic || 'Obituary-11'; } else if (currentPurpose === 'Other') { window.editorState.selectedOtherBackground = backgroundState.graphic || 'Other-2'; } else if (currentPurpose === 'Pet') { window.editorState.selectedPetBackground = backgroundState.graphic || 'Pet-11'; } else if (currentPurpose === 'Prayer') { window.editorState.selectedPrayerBackground = backgroundState.graphic || 'Prayer-2'; } else if (currentPurpose === 'Retirement') { window.editorState.selectedRetirementBackground = backgroundState.graphic || 'Retirement-9'; } else if (currentPurpose === 'Wedding') { window.editorState.selectedWeddingBackground = backgroundState.graphic || 'Wedding-10'; } else if (currentPurpose === 'Welcome') { window.editorState.selectedWelcomeBackground = backgroundState.graphic || 'Welcome-10'; } } } console.log('restoreBackgroundDialogState: Background dialog state restored'); } catch (error) { console.error('restoreBackgroundDialogState: Error restoring background state:', error); } } // Update Background Selection in Dialog function updateBackgroundSelection() { const grid = document.getElementById('stockImageBackgroundsGrid'); if (!grid) return; // Remove previous selection grid.querySelectorAll('.stockImage-bg-option').forEach(opt => { opt.classList.remove('selected'); }); // Select current background based on purpose let currentBackground = null; if (currentPurpose === 'Anniversary') { currentBackground = selectedAnniversaryBackground; } else if (currentPurpose === 'Benefit') { currentBackground = selectedBenefitBackground; } else if (currentPurpose === 'Christian') { currentBackground = selectedChristianBackground; } else if (currentPurpose === 'Graduation') { currentBackground = selectedGraduationBackground; } else if (currentPurpose === 'Holiday') { currentBackground = selectedHolidayBackground; } else if (currentPurpose === 'Local School') { currentBackground = selectedLocalSchoolBackground; } else if (currentPurpose === 'Love') { currentBackground = selectedLoveBackground; } else if (currentPurpose === 'Marry Me') { currentBackground = selectedMarryMeBackground; } else if (currentPurpose === 'New Born') { currentBackground = selectedNewbornBackground; } else if (currentPurpose === 'Obituary') { currentBackground = selectedObituaryBackground; } else if (currentPurpose === 'Other') { currentBackground = selectedOtherBackground; } else if (currentPurpose === 'Pet') { currentBackground = selectedPetBackground; } else if (currentPurpose === 'Prayer') { currentBackground = selectedPrayerBackground; } else if (currentPurpose === 'Retirement') { currentBackground = selectedRetirementBackground; } else if (currentPurpose === 'Wedding') { currentBackground = selectedWeddingBackground; } else if (currentPurpose === 'Welcome') { currentBackground = selectedWelcomeBackground; } if (currentBackground) { const currentOption = grid.querySelector(`[data-background="${currentBackground}"]`); if (currentOption) { currentOption.classList.add('selected'); } } } // Initialize Anniversary Backgrounds function initAnniversaryBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create anniversary background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedAnniversaryBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); // CRITICAL FIX: Save background state when image is selected saveBackgroundDialogState(); console.log('Anniversary background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); }); } // Set initial selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Benefit Backgrounds function initBenefitBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create benefit background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedBenefitBackground = this.dataset.background; // CRITICAL FIX: Switch to image background type when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Benefit background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); // Force immediate canvas update to test setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after benefit background selection'); } }, 50); }); } // Set initial selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Christian Backgrounds function initChristianBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create christian background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedChristianBackground = this.dataset.background; // CRITICAL FIX: Switch to image background type when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Christian background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); // Force immediate canvas update to test setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after christian background selection'); } }, 50); }); } // Set initial selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Graduation Backgrounds function initGraduationBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create graduation background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedGraduationBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Graduation background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); }); } // Set initial selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Holiday Backgrounds function initHolidayBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create holiday background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedHolidayBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Holiday background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); // Force immediate canvas update to test setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after holiday background selection'); } }, 50); }); } // Update background selection to show current selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Love Backgrounds function initLoveBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create love background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedLoveBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Love background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); // Force immediate canvas update to test setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after love background selection'); } }, 50); }); } // Update background selection to show current selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Marry Me Backgrounds function initMarryMeBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create marry me background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedMarryMeBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Marry Me background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); // Force immediate canvas update to test setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after marry me background selection'); } }, 50); }); } // Set initial selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Newborn Backgrounds function initNewbornBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create newborn background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedNewbornBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Newborn background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); // Force immediate canvas update to test setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after newborn background selection'); } }, 50); }); } // Set initial selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Obituary Backgrounds function initObituaryBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create obituary background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedObituaryBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Obituary background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); // Force immediate canvas update to test setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after obituary background selection'); } }, 50); }); } // Set initial selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Other Backgrounds function initOtherBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create other background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedOtherBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Other background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); // Force immediate canvas update to test setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after other background selection'); } }, 50); }); } // Set initial selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Pet Backgrounds function initPetBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create pet background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Add selection to current option this.classList.add('selected'); // Update selected background selectedPetBackground = this.dataset.background; console.log('Pet background selected:', selectedPetBackground); // Update global state if (window.editorState) { window.editorState.selectedPetBackground = selectedPetBackground; } // Sync state syncEditorState(); // Update canvas immediately setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after pet background selection'); } }, 50); }); } // Set initial selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Retirement Backgrounds function initRetirementBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create retirement background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); // Update selected background selectedRetirementBackground = this.dataset.background; updateEditorCanvas(); }); } // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Wedding Templates function initWeddingTemplates() { const templateCards = document.querySelectorAll('.wedding-template-card'); templateCards.forEach(card => { card.addEventListener('click', function() { const templateId = this.dataset.template; selectWeddingTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); } syncEditorState(); // Background graphic button const bgGraphicBtn = document.getElementById('backgroundGraphicBtn'); if (bgGraphicBtn) { bgGraphicBtn.addEventListener('click', showBackgroundGraphicDialog); } // Editor photo upload (prevent duplicate listeners) const editorPhotoUpload = document.getElementById('editorPhotoUpload'); const editorPhotoInput = document.getElementById('editorPhotoInput'); if (editorPhotoUpload && editorPhotoInput && !editorPhotoUpload.hasAttribute('data-listener-added')) { editorPhotoUpload.addEventListener('click', () => editorPhotoInput.click()); editorPhotoInput.addEventListener('change', handleEditorPhotoUpload); editorPhotoUpload.setAttribute('data-listener-added', 'true'); } // Handle photo upload for editor function handleEditorPhotoUpload(event) { const file = event.target.files[0]; if (file && file.type.startsWith('image/')) { const reader = new FileReader(); reader.onload = function(e) { editorUploadedImage = new Image(); editorUploadedImage.onload = function() { updateEditorCanvas(); }; editorUploadedImage.src = e.target.result; }; reader.readAsDataURL(file); } } } // Select Wedding Template function selectWeddingTemplate(templateId) { // Remove previous selection document.querySelectorAll('.wedding-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } currentWeddingTemplate = templateId; // Set default background based on template switch(templateId) { case 'wedding-template-1': selectedWeddingBackground = 'Wedding-10'; selectedBackgroundType = 'image'; break; case 'wedding-template-2': selectedWeddingBackground = 'Wedding-1'; selectedBackgroundType = 'image'; break; case 'wedding-template-3': selectedWeddingBackground = 'Wedding-3'; selectedBackgroundType = 'image'; break; default: selectedWeddingBackground = 'Wedding-10'; selectedBackgroundType = 'image'; } // Set default texts based on template const template = weddingTemplates[templateId]; if (template && template.defaultTexts) { currentTexts = [...template.defaultTexts]; // Update text input fields for (let i = 0; i { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } // Update color button to reflect template color const colorBtn = document.getElementById(`editorColorBtn${index + 1}`); if (colorBtn && style.color) { colorBtn.style.backgroundColor = style.color; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Show editor showTemplateEditor(); } // Select Welcome Template function selectWelcomeTemplate(templateId) { // Remove previous selection document.querySelectorAll('.welcome-template-card').forEach(card => { card.classList.remove('selected'); }); // Select current template const selectedCard = document.querySelector(`[data-template="${templateId}"]`); if (selectedCard) { selectedCard.classList.add('selected'); } currentWelcomeTemplate = templateId; // Set current purpose for Welcome templates currentPurpose = 'Welcome'; console.log('selectWelcomeTemplate: Set currentPurpose to:', currentPurpose); const template = welcomeTemplates[templateId]; if (!template) { console.error('selectWelcomeTemplate: Template not found:', templateId); return; } // Set default background based on template switch(templateId) { case 'welcome-template-1': selectedWelcomeBackground = 'Welcome-10'; break; case 'welcome-template-2': selectedWelcomeBackground = 'Welcome-15'; break; case 'welcome-template-3': selectedWelcomeBackground = 'Welcome-11'; break; default: selectedWelcomeBackground = 'Welcome-10'; } console.log('selectWelcomeTemplate: Template selected:', templateId); console.log('selectWelcomeTemplate: Background set to:', selectedWelcomeBackground); // Set current template for global access window.editorState = window.editorState || {}; window.editorState.currentWelcomeTemplate = templateId; window.editorState.welcomeTemplates = welcomeTemplates; syncEditorState(); // Set default texts in editor inputs if (template.defaultTexts) { template.defaultTexts.forEach((text, index) => { const input = document.getElementById(`editorLine${index + 1}`); if (input) { input.value = text; } }); } // Set background type to image for Welcome templates selectedBackgroundType = 'image'; // Update background state if (window.editorState) { window.editorState.selectedBackgroundType = selectedBackgroundType; window.editorState.selectedWelcomeBackground = selectedWelcomeBackground; } syncEditorState(); // Initialize editor text settings with template textStyles as defaults if (template && template.textStyles) { template.textStyles.forEach((style, index) => { const lineId = `editorLine${index + 1}`; if (window.editorState && window.editorState.editorTextSettings) { window.editorState.editorTextSettings[lineId] = { color: style.color || '#ffffff', fontSize: parseInt(style.fontSize) || 42, fontFamily: style.fontFamily || 'Arial', shadow: style.textShadow ? true : false, shadowWidth: 4, fontWeight: style.fontWeight || 'normal', fontStyle: style.fontStyle || 'normal', letterSpacing: style.letterSpacing || 'normal' }; } }); } // Update color picker buttons to reflect new template colors setTimeout(() => { EditorControlsManager.updateColors(); }, 50); // Show editor showTemplateEditor(); } // Initialize Welcome Templates function initWelcomeTemplates() { const templateCards = document.querySelectorAll('.welcome-template-card'); templateCards.forEach(card => { card.addEventListener('click', function() { const templateId = this.dataset.template; selectWelcomeTemplate(templateId); }); }); // Initialize editor canvas editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { editorCtx = editorCanvas.getContext('2d'); } syncEditorState(); // Background graphic button const bgGraphicBtn = document.getElementById('backgroundGraphicBtn'); if (bgGraphicBtn) { bgGraphicBtn.addEventListener('click', showBackgroundGraphicDialog); } // Editor photo upload (prevent duplicate listeners) const editorPhotoUpload = document.getElementById('editorPhotoUpload'); const editorPhotoInput = document.getElementById('editorPhotoInput'); if (editorPhotoUpload && editorPhotoInput && !editorPhotoUpload.hasAttribute('data-listener-added')) { editorPhotoUpload.addEventListener('click', () => editorPhotoInput.click()); editorPhotoInput.addEventListener('change', handleEditorPhotoUpload); editorPhotoUpload.setAttribute('data-listener-added', 'true'); } // Handle photo upload for editor function handleEditorPhotoUpload(event) { const file = event.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = function(e) { const img = new Image(); img.onload = function() { editorUploadedImage = img; syncEditorState(); updateEditorCanvas(); }; img.src = e.target.result; }; reader.readAsDataURL(file); } } // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Wedding Backgrounds function initWeddingBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create wedding background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); // Update selected background selectedWeddingBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); updateEditorCanvas(); }); } // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Prayer Backgrounds function initPrayerBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create prayer background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); // Update selected background selectedPrayerBackground = this.dataset.background; console.log('Prayer background selected:', selectedPrayerBackground); // Update global state if (window.editorState) { window.editorState.selectedPrayerBackground = selectedPrayerBackground; } // Sync state syncEditorState(); // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; if (window.editorState) { window.editorState.selectedBackgroundType = selectedBackgroundType; } // Update canvas immediately setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after prayer background selection'); } }, 50); }); } // Set initial selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Local School Backgrounds function initLocalSchoolBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create local school background options (1-10) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedLocalSchoolBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Local School background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); // Force immediate canvas update to test setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after local school background selection'); } }, 50); }); } // Update background selection to show current selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Welcome Backgrounds function initWelcomeBackgrounds() { const grid = document.getElementById('stockImageBackgroundsGrid'); // Reuse the same grid if (!grid) return; // Clear existing options grid.innerHTML = ''; // Create welcome background options (1-15) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); // Update selected background selectedWelcomeBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); updateEditorCanvas(); }); } // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Generate Local School Background Options function generateLocalSchoolBackgroundOptions() { const grid = document.getElementById('stockImageBackgroundsGrid'); if (!grid) { console.error('generateLocalSchoolBackgroundOptions: Stock image grid not found'); return; } // Clear existing options grid.innerHTML = ''; // Create local school background options (1-10) for (let i = 1; i { opt.classList.remove('selected'); }); // Select current this.classList.add('selected'); selectedLocalSchoolBackground = this.dataset.background; // Ensure background type is set to image when image is selected selectedBackgroundType = 'image'; syncEditorState(); // Save background state when image is selected saveBackgroundDialogState(); console.log('Local School background selected:', this.dataset.background, 'Background type set to:', selectedBackgroundType); // Force immediate canvas update to test setTimeout(() => { if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas updated immediately after local school background selection'); } }, 50); }); } // Update background selection to show current selection updateBackgroundSelection(); // Initialize dialog buttons and background type switching only once initBackgroundDialogControls(); } // Initialize Background Dialog Controls (buttons and type switching) function initBackgroundDialogControls() { // Only initialize if not already initialized if (window.backgroundDialogControlsInitialized) { return; } const selectBtn = document.getElementById('selectBackgroundBtn'); const dialog = document.getElementById('backgroundGraphicDialog'); if (selectBtn) { selectBtn.addEventListener('click', function() { console.log('Background Select button clicked. Current state:', { selectedBackgroundType, selectedBenefitBackground, selectedChristianBackground, currentBenefitTemplate, currentChristianTemplate }); // Force sync state before closing dialog syncEditorState(); try { dialog.close(); console.log('Background graphic dialog closed using modal method'); } catch (error) { // Fallback for browsers that don't support close dialog.classList.remove('show'); console.log('Background graphic dialog closed using fallback method'); } // Force canvas update with delay to ensure state is synced setTimeout(() => { updateEditorCanvas(); console.log('Canvas updated after background selection'); }, 100); }); } // Close dialog on background click if (dialog) { dialog.addEventListener('click', function(e) { if (e.target === dialog) { try { dialog.close(); console.log('Background graphic dialog closed by backdrop click using modal method'); } catch (error) { // Fallback for browsers that don't support close dialog.classList.remove('show'); console.log('Background graphic dialog closed by backdrop click using fallback method'); } } }); } // Initialize background type switching initBackgroundTypeSwitching(); // Mark as initialized window.backgroundDialogControlsInitialized = true; } // Initialize Background Type Switching function initBackgroundTypeSwitching() { // Only initialize if not already initialized if (window.backgroundTypeSwitchingInitialized) { return; } const imageBtn = document.getElementById('imageBackgroundBtn'); const colorBtn = document.getElementById('colorBackgroundBtn'); const imageSection = document.getElementById('imageBackgroundSection'); const colorSection = document.getElementById('colorBackgroundSection'); if (!imageBtn || !colorBtn || !imageSection || !colorSection) { console.warn('Background type switching elements not found'); return; } // Image background button click imageBtn.addEventListener('click', function() { selectedBackgroundType = 'image'; syncEditorState(); // Update button states imageBtn.classList.add('active'); colorBtn.classList.remove('active'); // Show/hide sections imageSection.style.display = 'block'; colorSection.style.display = 'none'; // CRITICAL FIX: Redraw canvas when switching to image background // This ensures the stock image is applied immediately if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas redrawn after switching to image background'); } else if (window.updateEditorCanvas) { window.updateEditorCanvas(); console.log('Canvas redrawn using global function after switching to image background'); } // Save background state for persistence saveBackgroundDialogState(); }); // Color background button click colorBtn.addEventListener('click', function() { selectedBackgroundType = 'color'; syncEditorState(); // Update button states colorBtn.classList.add('active'); imageBtn.classList.remove('active'); // Show/hide sections imageSection.style.display = 'none'; colorSection.style.display = 'block'; // CRITICAL FIX: Redraw canvas when switching to color background // This ensures the color background is applied immediately if (typeof updateEditorCanvas === 'function') { updateEditorCanvas(); console.log('Canvas redrawn after switching to color background'); } else if (window.updateEditorCanvas) { window.updateEditorCanvas(); console.log('Canvas redrawn using global function after switching to color background'); } // Save background state for persistence saveBackgroundDialogState(); }); // Initialize background color picker initBackgroundColorPicker(); // Mark as initialized window.backgroundTypeSwitchingInitialized = true; } // Save Background Dialog State for persistence function saveBackgroundDialogState() { try { // Get current background based on purpose let currentBackground = null; if (currentPurpose === 'Anniversary') { currentBackground = selectedAnniversaryBackground; } else if (currentPurpose === 'Benefit') { currentBackground = selectedBenefitBackground; } else if (currentPurpose === 'Christian') { currentBackground = selectedChristianBackground; } else if (currentPurpose === 'Graduation') { currentBackground = selectedGraduationBackground; } else if (currentPurpose === 'Holiday') { currentBackground = selectedHolidayBackground; } else if (currentPurpose === 'Local School') { currentBackground = selectedLocalSchoolBackground; } else if (currentPurpose === 'Love') { currentBackground = selectedLoveBackground; } else if (currentPurpose === 'Marry Me') { currentBackground = selectedMarryMeBackground; } else if (currentPurpose === 'New Born') { currentBackground = selectedNewbornBackground; } else if (currentPurpose === 'Obituary') { currentBackground = selectedObituaryBackground; } else if (currentPurpose === 'Other') { currentBackground = selectedOtherBackground; } else if (currentPurpose === 'Pet') { currentBackground = selectedPetBackground; } else if (currentPurpose === 'Prayer') { currentBackground = selectedPrayerBackground; } else if (currentPurpose === 'Retirement') { currentBackground = selectedRetirementBackground; } else if (currentPurpose === 'Wedding') { currentBackground = selectedWeddingBackground; } else if (currentPurpose === 'Welcome') { currentBackground = selectedWelcomeBackground; } const backgroundState = { type: selectedBackgroundType, graphic: currentBackground, color: selectedBackgroundColor, purpose: currentPurpose }; localStorage.setItem('editorBackgroundState', JSON.stringify(backgroundState)); console.log('saveBackgroundDialogState: Background state saved:', backgroundState); } catch (error) { console.error('saveBackgroundDialogState: Error saving background state:', error); } } // Test function to verify background type switching fix window.testBackgroundTypeSwitchingFix = function() { console.log('🧪 Testing Background Type Switching Fix...'); const testResults = []; // Test 1: Verify initial state console.log('Test 1: Checking initial background type state'); const imageBtn = document.getElementById('imageBackgroundBtn'); const colorBtn = document.getElementById('colorBackgroundBtn'); const imageSection = document.getElementById('imageBackgroundSection'); const colorSection = document.getElementById('colorBackgroundSection'); if (imageBtn && colorBtn && imageSection && colorSection) { testResults.push('✓ All background type switching elements found'); // Test 2: Switch to color background console.log('Test 2: Switching to color background'); // Simulate color button click selectedBackgroundType = 'image'; // Start with image colorBtn.click(); // Check if state changed correctly if (selectedBackgroundType === 'color') { testResults.push('✓ Background type correctly set to color'); } else { testResults.push('✗ Background type not set to color'); } // Check UI state if (colorBtn.classList.contains('active') && !imageBtn.classList.contains('active')) { testResults.push('✓ Color button activated, image button deactivated'); } else { testResults.push('✗ Button states not updated correctly'); } // Check section visibility if (colorSection.style.display !== 'none' && imageSection.style.display === 'none') { testResults.push('✓ Color section shown, image section hidden'); } else { testResults.push('✗ Section visibility not updated correctly'); } // Test 3: Switch back to image background console.log('Test 3: Switching back to image background'); imageBtn.click(); // Check if state changed correctly if (selectedBackgroundType === 'image') { testResults.push('✓ Background type correctly switched back to image'); } else { testResults.push('✗ Background type not switched back to image'); } // Check UI state if (imageBtn.classList.contains('active') && !colorBtn.classList.contains('active')) { testResults.push('✓ Image button activated, color button deactivated'); } else { testResults.push('✗ Button states not updated correctly on switch back'); } // Check section visibility if (imageSection.style.display !== 'none' && colorSection.style.display === 'none') { testResults.push('✓ Image section shown, color section hidden'); } else { testResults.push('✗ Section visibility not updated correctly on switch back'); } // Test 4: Check if canvas redraw functions are called console.log('Test 4: Checking canvas redraw functionality'); if (typeof updateEditorCanvas === 'function' || window.updateEditorCanvas) { testResults.push('✓ Canvas redraw function available'); } else { testResults.push('✗ Canvas redraw function not found'); } // Test 5: Check state persistence console.log('Test 5: Checking state persistence'); if (typeof saveBackgroundDialogState === 'function') { testResults.push('✓ Background state saving function available'); // Test saving state try { saveBackgroundDialogState(); const savedState = localStorage.getItem('editorBackgroundState'); if (savedState) { const parsedState = JSON.parse(savedState); if (parsedState.type === selectedBackgroundType) { testResults.push('✓ Background state correctly saved to localStorage'); } else { testResults.push('✗ Background state not correctly saved'); } } else { testResults.push('✗ Background state not saved to localStorage'); } } catch (error) { testResults.push('✗ Error saving background state: ' + error.message); } } else { testResults.push('✗ Background state saving function not found'); } } else { testResults.push('✗ Background type switching elements not found'); } // Display test results console.log('🧪 Background Type Switching Test Results:'); testResults.forEach(result => console.log(result)); console.log('🎉 Background Type Switching Fix Test Complete!'); console.log('📋 Summary: The fix ensures that:'); console.log(' 1. Background type switches correctly between image and color'); console.log(' 2. UI elements (buttons, sections) update properly'); console.log(' 3. Canvas is redrawn when background type changes'); console.log(' 4. Background state is saved for persistence'); console.log(' 5. Stock images apply correctly when switching from color back to image'); return testResults; }; // Initialize Background Color Picker function initBackgroundColorPicker() { const gradientArea = document.getElementById('backgroundColorGradient'); const hueSlider = document.getElementById('backgroundHueSlider'); const colorPreview = document.getElementById('backgroundColorPreview'); const resetBtn = document.getElementById('backgroundColorReset'); if (!gradientArea || !hueSlider || !colorPreview || !resetBtn) { console.warn('Background color picker elements not found'); return; } let currentHue = 0; let currentSaturation = 100; let currentLightness = 50; // Convert HSL to RGB function hslToRgb(h, s, l) { h /= 360; s /= 100; l /= 100; const a = s * Math.min(l, 1 - l); const f = n => { const k = (n + h * 12) % 12; return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); }; return [Math.round(f(0) * 255), Math.round(f(8) * 255), Math.round(f(4) * 255)]; } // Convert RGB to Hex function rgbToHex(r, g, b) { return "#" + ((1 << 24) + (r << 16) + (g < { const field = mainFormFields[fieldName]; const value = editorData.textLines[fieldName]; if (field && value !== undefined) { field.value = value; console.log(`confirmTemplateDesignGlobal: Updated ${fieldName} = "${value}"`); } else if (!field) { console.warn(`confirmTemplateDesignGlobal: Main form field ${fieldName} not found`); } }); // Update hidden fields with null checks const hiddenFields = { selectedTemplate: document.getElementById('selectedTemplate'), billboardData: document.getElementById('billboardData') }; if (hiddenFields.selectedTemplate) { hiddenFields.selectedTemplate.value = currentTemplate; console.log('confirmTemplateDesignGlobal: Updated selectedTemplate field'); } else { console.warn('confirmTemplateDesignGlobal: selectedTemplate field not found'); } if (hiddenFields.billboardData) { hiddenFields.billboardData.value = JSON.stringify(editorData); console.log('confirmTemplateDesignGlobal: Updated billboardData field'); } else { console.warn('confirmTemplateDesignGlobal: billboardData field not found'); } // Store in localStorage for checkout localStorage.setItem('adDesignData', JSON.stringify(editorData)); localStorage.setItem('currentAnniversaryTemplate', currentTemplate); localStorage.setItem('selectedAnniversaryBackground', selectedBackground); localStorage.setItem('selectedBackgroundType', backgroundType); localStorage.setItem('selectedBackgroundColor', backgroundColor); // Professional canvas image capture for template confirmation let canvasDataURL = null; const canvasSources = ['editorCanvas', 'billboardCanvas']; for (const canvasId of canvasSources) { const canvas = document.getElementById(canvasId); if (canvas) { try { // Check if canvas has content const ctx = canvas.getContext('2d'); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const hasContent = imageData.data.some(pixel => pixel !== 0); if (hasContent) { canvasDataURL = canvas.toDataURL('image/png', 0.9); localStorage.setItem('adPreviewImage', canvasDataURL); localStorage.setItem('billboardCanvasImage', canvasDataURL); console.log(`confirmTemplateDesignGlobal: Canvas image saved from ${canvasId}`); break; } } catch (error) { console.warn(`confirmTemplateDesignGlobal: Error capturing ${canvasId}:`, error); } } } // Generate preview if no canvas image captured if (!canvasDataURL) { console.log('confirmTemplateDesignGlobal: Generating preview from design data...'); canvasDataURL = generatePreviewFromDesignData(); if (canvasDataURL) { localStorage.setItem('adPreviewImage', canvasDataURL); localStorage.setItem('billboardCanvasImage', canvasDataURL); console.log('confirmTemplateDesignGlobal: Preview generated and saved'); } } // Professional UX: Keep editor open for continued editing // Instead of closing the editor, just show a success message and keep it accessible console.log('confirmTemplateDesignGlobal: Design confirmed, keeping editor open for continued editing'); // Add a visual confirmation that design is saved showDesignConfirmationMessage(); // Update the editor title to show it's confirmed updateEditorTitle('confirmed'); // Show professional success message (non-blocking) console.log('confirmTemplateDesignGlobal: Completed successfully'); } catch (error) { console.error('confirmTemplateDesignGlobal: Error occurred:', error); console.error('confirmTemplateDesignGlobal: Error stack:', error.stack); alert('An error occurred while confirming the design. Please try again.'); } finally { // Always reset the running flag setTimeout(() => { window.confirmTemplateDesignGlobal.isRunning = false; }, 500); } }; // Professional visual confirmation functions window.showDesignConfirmationMessage = function() { // Remove any existing confirmation messages const existingMessages = document.querySelectorAll('.design-confirmation-message'); existingMessages.forEach(msg => msg.remove()); // Create professional confirmation message const confirmationDiv = document.createElement('div'); confirmationDiv.className = 'design-confirmation-message'; confirmationDiv.style.cssText = ` position: fixed; top: 20px; right: 20px; background: linear-gradient(135deg, #28a745, #20c997); color: white; padding: 15px 25px; border-radius: 8px; box-shadow: 0 4px 12px rgba(40, 167, 69, 0.3); z-index: 999999 !important; font-family: Arial, sans-serif; font-size: 14px; font-weight: 600; animation: slideInRight 0.5s ease-out; max-width: 300px; `; confirmationDiv.innerHTML = ` ✅ Design Confirmed! Continue editing or proceed to checkout `; // Add animation keyframes if not already added if (!document.querySelector('#confirmation-animations')) { const style = document.createElement('style'); style.id = 'confirmation-animations'; style.textContent = ` @keyframes slideInRight { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } `; document.head.appendChild(style); } document.body.appendChild(confirmationDiv); // Auto-remove after 4 seconds with fade out setTimeout(() => { confirmationDiv.style.animation = 'fadeOut 0.5s ease-out'; setTimeout(() => { if (confirmationDiv.parentNode) { confirmationDiv.remove(); } }, 500); }, 4000); console.log('showDesignConfirmationMessage: Confirmation message displayed'); }; // Update editor title to show confirmation status window.updateEditorTitle = function(status) { const editorContainer = document.getElementById('templateEditorContainer'); if (!editorContainer) return; let titleElement = editorContainer.querySelector('.editor-title-status'); if (!titleElement) { // Create title status element if it doesn't exist titleElement = document.createElement('div'); titleElement.className = 'editor-title-status'; titleElement.style.cssText = ` text-align: center; padding: 10px; margin-bottom: 15px; border-radius: 6px; font-weight: 600; font-size: 14px; `; // Insert at the beginning of the editor container const firstChild = editorContainer.firstElementChild; if (firstChild) { editorContainer.insertBefore(titleElement, firstChild); } else { editorContainer.appendChild(titleElement); } } if (status === 'confirmed') { titleElement.style.background = 'linear-gradient(135deg, #d4edda, #c3e6cb)'; titleElement.style.color = '#155724'; titleElement.style.border = '1px solid #c3e6cb'; titleElement.innerHTML = ` ✅ Design Confirmed - Continue editing or proceed to checkout `; } else { titleElement.style.background = 'linear-gradient(135deg, #e3f2fd, #bbdefb)'; titleElement.style.color = '#1565c0'; titleElement.style.border = '1px solid #bbdefb'; titleElement.innerHTML = ` 🎨 Customize Your Anniversary Billboard `; } console.log(`updateEditorTitle: Title updated to ${status} status`); }; // Universal Confirm Template Design - Works for any purpose window.confirmUniversalTemplateDesign = function() { const state = window.editorState; if (!state || !state.currentTemplate || !state.currentPurpose) { console.log('confirmUniversalTemplateDesign: Missing required state'); alert('Please select a template first.'); return; } try { console.log('confirmUniversalTemplateDesign: Starting for purpose:', state.currentPurpose); // Get editor data const editorData = { purpose: state.currentPurpose, template: state.currentTemplate, templateConfig: state.templateConfig, textLines: { line1: document.getElementById('editorLine1')?.value || '', line2: document.getElementById('editorLine2')?.value || '', line3: document.getElementById('editorLine3')?.value || '', line4: document.getElementById('editorLine4')?.value || '' }, hasUploadedImage: !!state.editorUploadedImage }; // Update main form fields const mainFormFields = { line1: document.getElementById('line1'), line2: document.getElementById('line2'), line3: document.getElementById('line3'), line4: document.getElementById('line4') }; Object.keys(mainFormFields).forEach(fieldName => { const field = mainFormFields[fieldName]; const value = editorData.textLines[fieldName]; if (field && value !== undefined) { field.value = value; console.log(`confirmUniversalTemplateDesign: Updated ${fieldName} = "${value}"`); } }); // Update hidden fields const selectedTemplateField = document.getElementById('selectedTemplate'); const billboardDataField = document.getElementById('billboardData'); if (selectedTemplateField) { selectedTemplateField.value = state.currentTemplate; } if (billboardDataField) { billboardDataField.value = JSON.stringify(editorData); } // Store in localStorage for checkout localStorage.setItem('adDesignData', JSON.stringify(editorData)); localStorage.setItem('currentTemplate', state.currentTemplate); localStorage.setItem('currentPurpose', state.currentPurpose); // Capture canvas image const editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas) { try { const canvasDataURL = editorCanvas.toDataURL('image/png', 0.9); localStorage.setItem('adPreviewImage', canvasDataURL); localStorage.setItem('billboardCanvasImage', canvasDataURL); console.log('confirmUniversalTemplateDesign: Canvas image saved'); } catch (error) { console.warn('confirmUniversalTemplateDesign: Error capturing canvas:', error); } } // Show confirmation message showDesignConfirmationMessage(); // Update editor title updateEditorTitle('confirmed'); console.log('confirmUniversalTemplateDesign: Completed successfully'); } catch (error) { console.error('confirmUniversalTemplateDesign: Error occurred:', error); alert('An error occurred while confirming the design. Please try again.'); } }; // Universal Confirm Design Router - Routes to appropriate confirm function window.confirmDesignUniversal = function() { const currentPurpose = localStorage.getItem('selectedPurpose'); const state = window.editorState; console.log('confirmDesignUniversal: Current purpose:', currentPurpose); console.log('confirmDesignUniversal: Editor state:', state); if (currentPurpose === 'Anniversary') { // Use anniversary-specific confirm function if (window.confirmTemplateDesignGlobal) { window.confirmTemplateDesignGlobal(); } else if (window.confirmTemplateDesign) { window.confirmTemplateDesign(); } else { console.error('confirmDesignUniversal: No anniversary confirm function available'); alert('Error: Unable to confirm anniversary design.'); } } else if (currentPurpose === 'Benefit') { // Use benefit-specific confirm function if (window.confirmBenefitTemplateDesign) { window.confirmBenefitTemplateDesign(); } else { console.error('confirmDesignUniversal: No benefit confirm function available'); alert('Error: Unable to confirm benefit design.'); } } else if (currentPurpose === 'Christian') { // Use christian-specific confirm function if (window.confirmChristianTemplateDesign) { window.confirmChristianTemplateDesign(); } else { console.error('confirmDesignUniversal: No christian confirm function available'); alert('Error: Unable to confirm christian design.'); } } else if (currentPurpose === 'Graduation') { // Use graduation-specific confirm function if (window.confirmGraduationTemplateDesign) { window.confirmGraduationTemplateDesign(); } else { console.error('confirmDesignUniversal: No graduation confirm function available'); alert('Error: Unable to confirm graduation design.'); } } else if (UNIVERSAL_TEMPLATE_CONFIG[currentPurpose]) { // Use universal template confirm function window.confirmUniversalTemplateDesign(); } else { // Fallback to global confirm function if (window.confirmTemplateDesignGlobal) { window.confirmTemplateDesignGlobal(); } else { console.error('confirmDesignUniversal: No confirm function available'); alert('Error: Unable to confirm design.'); } } }; // Create a global version of backToTemplateSelection with debouncing window.backToTemplateSelection = function() { // Prevent multiple simultaneous executions if (window.backToTemplateSelection.isRunning) { console.log('backToTemplateSelection: Already running, skipping...'); return; } window.backToTemplateSelection.isRunning = true; try { console.log('backToTemplateSelection: Starting...'); // Close the template editor const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer) { editorContainer.classList.remove('active'); console.log('backToTemplateSelection: Template editor closed'); } // Get current purpose to show appropriate templates const currentPurpose = localStorage.getItem('selectedPurpose'); console.log('backToTemplateSelection: Current purpose:', currentPurpose); // Show templates for the current purpose if (currentPurpose && currentPurpose !== 'Select a Purpose') { console.log('backToTemplateSelection: Showing templates for purpose:', currentPurpose); // Use the existing showTemplatesForPurpose function if available if (window.showTemplatesForPurpose) { window.showTemplatesForPurpose(currentPurpose); } else { // Fallback: show templates manually console.log('backToTemplateSelection: showTemplatesForPurpose not available, showing templates manually'); // Hide all template sections first const allTemplateSections = document.querySelectorAll('[id$="TemplatesSection"]'); allTemplateSections.forEach(section => { section.style.display = 'none'; }); // Show the appropriate template section const sectionId = currentPurpose.toLowerCase().replace(/\s+/g, '') + 'TemplatesSection'; const targetSection = document.getElementById(sectionId); if (targetSection) { targetSection.style.display = 'block'; console.log('backToTemplateSelection: Showed section:', sectionId); } else { console.warn('backToTemplateSelection: Template section not found:', sectionId); } } } else { console.log('backToTemplateSelection: No current purpose, showing default state'); // Show default template selection state const purposeSelection = document.getElementById('purposeSelection'); if (purposeSelection) { purposeSelection.style.display = 'block'; } } console.log('backToTemplateSelection: Completed successfully'); } catch (error) { console.error('backToTemplateSelection: Error occurred:', error); console.error('backToTemplateSelection: Error stack:', error.stack); } finally { // Reset the running flag after a delay setTimeout(() => { window.backToTemplateSelection.isRunning = false; }, 300); } }; // Professional Color Picker Manager - Singleton Pattern const EditorColorPickerManager = { initialized: false, eventHandlers: new Map(), documentClickHandler: null, init() { if (this.initialized) { console.log('EditorColorPickerManager: Already initialized, skipping...'); return; } console.log('EditorColorPickerManager: Initializing...'); this.cleanup(); this.setupColorPickers(); this.setupDocumentClickHandler(); this.initialized = true; console.log('EditorColorPickerManager: Initialization complete'); }, cleanup() { // Remove all existing event handlers this.eventHandlers.forEach((handler, element) => { if (element && element.removeEventListener) { element.removeEventListener('click', handler); } }); this.eventHandlers.clear(); // Remove document click handler if (this.documentClickHandler) { document.removeEventListener('click', this.documentClickHandler); this.documentClickHandler = null; } // Close all dropdowns document.querySelectorAll('.color-dropdown').forEach(dropdown => { dropdown.classList.remove('show'); }); }, setupColorPickers() { ['1', '2', '3', '4'].forEach(lineNum => { const colorBtn = document.getElementById(`editorColorBtn${lineNum}`); const colorDropdown = document.getElementById(`editorColorDropdown${lineNum}`); const colorPaletteEl = document.getElementById(`editorColorPalette${lineNum}`); const lineId = `editorLine${lineNum}`; if (!colorBtn || !colorDropdown || !colorPaletteEl) { console.warn(`EditorColorPickerManager: Missing elements for line ${lineNum}`); return; } // Set initial color const initialColor = this.getInitialColor(lineId); colorBtn.style.backgroundColor = initialColor; // Clear and create color picker colorPaletteEl.innerHTML = ''; try { createUnifiedColorPicker(colorPaletteEl, colorDropdown, lineId, setEditorTextColor); } catch (error) { console.error(`EditorColorPickerManager: Error creating picker for line ${lineNum}:`, error); return; } // Create and store event handler const clickHandler = (e) => { e.stopPropagation(); this.handleColorButtonClick(colorDropdown, lineNum); }; // Remove existing handler if any if (this.eventHandlers.has(colorBtn)) { colorBtn.removeEventListener('click', this.eventHandlers.get(colorBtn)); } // Add new handler colorBtn.addEventListener('click', clickHandler); this.eventHandlers.set(colorBtn, clickHandler); }); }, getInitialColor(lineId) { if (window.editorState?.editorTextSettings?.[lineId]?.color) { return window.editorState.editorTextSettings[lineId].color; } if (editorTextSettings?.[lineId]?.color) { return editorTextSettings[lineId].color; } return '#ffffff'; }, handleColorButtonClick(colorDropdown, lineNum) { // Close all other dropdowns document.querySelectorAll('.color-dropdown').forEach(dropdown => { if (dropdown !== colorDropdown) { dropdown.classList.remove('show'); } }); // Toggle current dropdown colorDropdown.classList.toggle('show'); console.log(`EditorColorPickerManager: Toggled dropdown for line ${lineNum}`); }, setupDocumentClickHandler() { this.documentClickHandler = (e) => { if (!e.target.closest('.color-picker-dropdown')) { document.querySelectorAll('.color-dropdown').forEach(dropdown => { dropdown.classList.remove('show'); }); } }; document.addEventListener('click', this.documentClickHandler); }, reinitialize() { console.log('EditorColorPickerManager: Reinitializing...'); this.initialized = false; setTimeout(() => this.init(), 50); }, updateColors() { ['1', '2', '3', '4'].forEach(lineNum => { const colorBtn = document.getElementById(`editorColorBtn${lineNum}`); const lineId = `editorLine${lineNum}`; if (colorBtn) { colorBtn.style.backgroundColor = this.getInitialColor(lineId); } }); } }; // Legacy function for backward compatibility function setupEditorColorPickers() { EditorColorPickerManager.init(); } // Professional Settings Button Manager const EditorSettingsManager = { initialized: false, eventHandlers: new Map(), init() { if (this.initialized) { console.log('EditorSettingsManager: Already initialized, skipping...'); return; } console.log('EditorSettingsManager: Initializing...'); this.cleanup(); this.setupSettingsButtons(); this.initialized = true; console.log('EditorSettingsManager: Initialization complete'); }, cleanup() { this.eventHandlers.forEach((handler, element) => { if (element && element.removeEventListener) { element.removeEventListener('click', handler); } }); this.eventHandlers.clear(); }, setupSettingsButtons() { ['1', '2', '3', '4'].forEach(lineNum => { const settingsBtn = document.getElementById(`editorSettingsBtn${lineNum}`); if (!settingsBtn) { console.warn(`EditorSettingsManager: Missing settings button for line ${lineNum}`); return; } const clickHandler = () => { openEditorFontModal(`editorLine${lineNum}`); }; // Remove existing handler if any if (this.eventHandlers.has(settingsBtn)) { settingsBtn.removeEventListener('click', this.eventHandlers.get(settingsBtn)); } // Add new handler settingsBtn.addEventListener('click', clickHandler); this.eventHandlers.set(settingsBtn, clickHandler); }); }, reinitialize() { console.log('EditorSettingsManager: Reinitializing...'); this.initialized = false; setTimeout(() => this.init(), 50); } }; // Professional Editor Controls Manager - Main Controller const EditorControlsManager = { init() { console.log('EditorControlsManager: Initializing all editor controls...'); EditorColorPickerManager.init(); EditorSettingsManager.init(); }, reinitialize() { console.log('EditorControlsManager: Reinitializing all editor controls...'); EditorColorPickerManager.reinitialize(); EditorSettingsManager.reinitialize(); }, updateColors() { EditorColorPickerManager.updateColors(); } }; // Legacy functions for backward compatibility function setupEditorSettingsButtons() { EditorSettingsManager.init(); } function forceSetupEditorColorPickers() { EditorControlsManager.reinitialize(); } // Debug function window.testColorPicker = function(lineNum) { const colorBtn = document.getElementById(`editorColorBtn${lineNum}`); const colorDropdown = document.getElementById(`editorColorDropdown${lineNum}`); const colorPalette = document.getElementById(`editorColorPalette${lineNum}`); console.log(`Testing color picker for line ${lineNum}:`); console.log('- Color button:', colorBtn); console.log('- Color dropdown:', colorDropdown); console.log('- Color palette:', colorPalette); console.log('- Dropdown classes:', colorDropdown ? colorDropdown.className : 'N/A'); console.log('- Palette children:', colorPalette ? colorPalette.children.length : 'N/A'); if (colorDropdown) { colorDropdown.classList.toggle('show'); console.log('- Toggled dropdown, now visible:', colorDropdown.classList.contains('show')); } }; // Set Editor Text Color - Professional Implementation function setEditorTextColor(lineId, color) { console.log(`setEditorTextColor: Setting ${lineId} to ${color}`); // Update local state if (editorTextSettings && editorTextSettings[lineId]) { editorTextSettings[lineId].color = color; } // Update global state if (window.editorState?.editorTextSettings?.[lineId]) { window.editorState.editorTextSettings[lineId].color = color; } // Update color button const lineNum = lineId.replace('editorLine', ''); const colorBtn = document.getElementById(`editorColorBtn${lineNum}`); if (colorBtn) { colorBtn.style.backgroundColor = color; console.log(`setEditorTextColor: Updated button color for ${lineId}`); } // Update canvas updateEditorCanvas(); } // Open Editor Font Modal with comprehensive restoration let currentEditorEditingLine = null; function openEditorFontModal(lineId) { console.log('openEditorFontModal: Opening modal for line:', lineId); currentEditorEditingLine = lineId; const modal = document.getElementById('editorFontModal'); if (!modal) { console.error('openEditorFontModal: Modal element not found'); return; } // Get settings from multiple sources for restoration let settings = (window.editorState && window.editorState.editorTextSettings && window.editorState.editorTextSettings[lineId]) ? window.editorState.editorTextSettings[lineId] : editorTextSettings[lineId]; // Get template's default font size for this line let templateDefaultFontSize = 50; // fallback const lineIndex = parseInt(lineId.replace('editorLine', '')) - 1; console.log(`openEditorFontModal: Looking for font size for ${lineId}, lineIndex: ${lineIndex}`); // Check current template for default font size let currentTemplate = null; if (currentAnniversaryTemplate) { currentTemplate = anniversaryTemplates[currentAnniversaryTemplate]; console.log(`openEditorFontModal: Using anniversary template: ${currentAnniversaryTemplate}`); } else if (currentBenefitTemplate) { currentTemplate = benefitTemplates[currentBenefitTemplate]; console.log(`openEditorFontModal: Using benefit template: ${currentBenefitTemplate}`); } else if (currentChristianTemplate) { currentTemplate = christianTemplates[currentChristianTemplate]; console.log(`openEditorFontModal: Using christian template: ${currentChristianTemplate}`); } else if (currentGraduationTemplate) { currentTemplate = graduationTemplates[currentGraduationTemplate]; console.log(`openEditorFontModal: Using graduation template: ${currentGraduationTemplate}`); } if (currentTemplate) { console.log(`openEditorFontModal: Template found:`, currentTemplate); if (currentTemplate.textStyles && currentTemplate.textStyles[lineIndex]) { const templateStyle = currentTemplate.textStyles[lineIndex]; console.log(`openEditorFontModal: Template style for line ${lineIndex}:`, templateStyle); if (templateStyle.fontSize) { // Handle both string and number formats if (typeof templateStyle.fontSize === 'string') { templateDefaultFontSize = parseInt(templateStyle.fontSize.replace('px', '')); } else { templateDefaultFontSize = parseInt(templateStyle.fontSize); } console.log(`openEditorFontModal: Extracted template font size: ${templateDefaultFontSize} for line ${lineIndex}`); } } else { console.log(`openEditorFontModal: No textStyles found for line ${lineIndex} in template`); } } else { console.log(`openEditorFontModal: No current template found`); } // Provide default settings if none exist, using template's font size if (!settings) { settings = { fontFamily: 'Arial', fontSize: templateDefaultFontSize, shadow: true, shadowWidth: 4 }; editorTextSettings[lineId] = settings; } // Try to restore from saved data if available const savedTextSettings = localStorage.getItem('editorTextSettings'); if (savedTextSettings) { try { const parsedSettings = JSON.parse(savedTextSettings); if (parsedSettings[lineId]) { settings = { ...settings, ...parsedSettings[lineId] }; // Update global settings editorTextSettings[lineId] = settings; console.log(`openEditorFontModal: Restored settings for ${lineId}:`, settings); } } catch (e) { console.warn('openEditorFontModal: Error parsing saved text settings:', e); } } // Determine final font size to use (saved settings take priority over template default) const finalFontSize = settings.fontSize || templateDefaultFontSize || 50; console.log(`openEditorFontModal: Final font size to use: ${finalFontSize}`); // Set current values in modal with error checking const fontSelect = document.getElementById('editorModalFontSelect'); const fontSizeInput = document.getElementById('editorModalFontSize'); const shadowCheckbox = document.getElementById('editorModalShadow'); const shadowWidthSlider = document.getElementById('editorModalShadowWidth'); if (fontSelect) fontSelect.value = settings.fontFamily || 'Arial'; if (fontSizeInput) { fontSizeInput.value = finalFontSize; console.log(`openEditorFontModal: Font size input set to: ${fontSizeInput.value}`); } if (shadowCheckbox) shadowCheckbox.checked = settings.shadow !== false; if (shadowWidthSlider) { const shadowWidth = settings.shadowWidth !== undefined ? settings.shadowWidth : 4; shadowWidthSlider.value = shadowWidth; // Update the value display const shadowValueDisplay = document.getElementById('editorShadowWidthValue'); if (shadowValueDisplay) { shadowValueDisplay.textContent = shadowWidth; } } console.log('openEditorFontModal: Modal populated with settings:', settings); try { modal.showModal(); // Ensure proper centering modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.margin = 'auto'; } catch (error) { // Fallback for browsers that don't support showModal modal.style.display = 'flex'; modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.margin = 'auto'; } } // Make openEditorFontModal globally accessible window.openEditorFontModal = openEditorFontModal; // Apply Editor Font Settings window.applyEditorFontSettings = function() { console.log('applyEditorFontSettings: Starting application for line:', currentEditorEditingLine); if (!currentEditorEditingLine) { console.error('applyEditorFontSettings: No current editing line set'); return; } const fontFamily = document.getElementById('editorModalFontSelect').value; const fontSizeRaw = parseInt(document.getElementById('editorModalFontSize').value); // Validate font size within reasonable bounds const fontSize = Math.max(8, Math.min(200, fontSizeRaw || 50)); const shadow = document.getElementById('editorModalShadow').checked; const shadowWidth = parseInt(document.getElementById('editorModalShadowWidth').value); const applyToAll = document.getElementById('editorApplyToAll').checked; console.log('applyEditorFontSettings: Settings to apply:', { fontFamily, fontSize, shadow, shadowWidth, applyToAll }); if (applyToAll) { // Apply to all editor text lines Object.keys(editorTextSettings).forEach(line => { editorTextSettings[line].fontFamily = fontFamily; editorTextSettings[line].fontSize = fontSize; editorTextSettings[line].shadow = shadow; editorTextSettings[line].shadowWidth = shadowWidth; // Update global state if (window.editorState && window.editorState.editorTextSettings && window.editorState.editorTextSettings[line]) { window.editorState.editorTextSettings[line].fontFamily = fontFamily; window.editorState.editorTextSettings[line].fontSize = fontSize; window.editorState.editorTextSettings[line].shadow = shadow; window.editorState.editorTextSettings[line].shadowWidth = shadowWidth; } }); } else { // Apply only to current line if (!editorTextSettings[currentEditorEditingLine]) { editorTextSettings[currentEditorEditingLine] = {}; } editorTextSettings[currentEditorEditingLine].fontFamily = fontFamily; editorTextSettings[currentEditorEditingLine].fontSize = fontSize; editorTextSettings[currentEditorEditingLine].shadow = shadow; editorTextSettings[currentEditorEditingLine].shadowWidth = shadowWidth; // Update global state if (window.editorState && window.editorState.editorTextSettings) { if (!window.editorState.editorTextSettings[currentEditorEditingLine]) { window.editorState.editorTextSettings[currentEditorEditingLine] = {}; } window.editorState.editorTextSettings[currentEditorEditingLine].fontFamily = fontFamily; window.editorState.editorTextSettings[currentEditorEditingLine].fontSize = fontSize; window.editorState.editorTextSettings[currentEditorEditingLine].shadow = shadow; window.editorState.editorTextSettings[currentEditorEditingLine].shadowWidth = shadowWidth; } console.log('applyEditorFontSettings: Applied to line:', currentEditorEditingLine); } // Save settings to localStorage try { localStorage.setItem('editorTextSettings', JSON.stringify(editorTextSettings)); console.log('applyEditorFontSettings: Settings saved to localStorage'); } catch (e) { console.warn('applyEditorFontSettings: Failed to save to localStorage:', e); } // Force canvas update console.log('applyEditorFontSettings: Updating canvas...'); updateEditorCanvas(); // Also try global update if available if (window.updateEditorCanvasGlobal) { window.updateEditorCanvasGlobal(); } window.closeEditorFontModal(); }; // Close Editor Font Modal window.closeEditorFontModal = function() { console.log('closeEditorFontModal: Closing modal'); const modal = document.getElementById('editorFontModal'); if (modal) { try { modal.close(); console.log('closeEditorFontModal: Modal closed using modal method'); } catch (error) { // Fallback for browsers that don't support close modal.style.display = 'none'; console.log('closeEditorFontModal: Modal hidden using fallback'); } } else { console.error('closeEditorFontModal: Modal element not found'); } currentEditorEditingLine = null; const applyToAllCheckbox = document.getElementById('editorApplyToAll'); if (applyToAllCheckbox) { applyToAllCheckbox.checked = false; } console.log('closeEditorFontModal: Modal closed and reset'); }; // Create Unified Color Picker function createUnifiedColorPicker(colorPaletteEl, colorDropdown, lineId, setColorFunction) { // Clear existing content colorPaletteEl.innerHTML = ''; // Create color palette colorPalette.forEach(color => { const swatch = document.createElement('div'); swatch.className = 'color-swatch'; if (color === '✓') { swatch.classList.add('checkmark'); swatch.innerHTML = '✓'; } else { swatch.style.backgroundColor = color; } swatch.addEventListener('click', () => { if (color !== '✓') { setColorFunction(lineId, color); colorDropdown.classList.remove('show'); // Remove selected class from all swatches colorPaletteEl.querySelectorAll('.color-swatch').forEach(s => s.classList.remove('selected')); // Add selected class to clicked swatch swatch.classList.add('selected'); } }); colorPaletteEl.appendChild(swatch); }); // Create advanced color picker const advancedPicker = document.createElement('div'); advancedPicker.className = 'color-picker-advanced'; // Color gradient area const gradientArea = document.createElement('div'); gradientArea.className = 'color-gradient-area'; gradientArea.style.background = 'linear-gradient(to right, #fff, #ff0000)'; const gradientPicker = document.createElement('div'); gradientPicker.className = 'color-gradient-picker'; gradientPicker.style.left = '50%'; gradientPicker.style.top = '50%'; gradientArea.appendChild(gradientPicker); // Hue slider const hueContainer = document.createElement('div'); hueContainer.className = 'hue-slider-container'; const hueSlider = document.createElement('div'); hueSlider.className = 'hue-slider'; const hueHandle = document.createElement('div'); hueHandle.className = 'hue-slider-handle'; hueHandle.style.top = '0%'; hueSlider.appendChild(hueHandle); // Color preview and buttons const previewSection = document.createElement('div'); previewSection.className = 'color-preview-section'; const colorPreview = document.createElement('div'); colorPreview.className = 'color-preview-large'; colorPreview.style.backgroundColor = '#ff0000'; const buttonsContainer = document.createElement('div'); buttonsContainer.className = 'color-picker-buttons'; const cancelBtn = document.createElement('button'); cancelBtn.className = 'color-picker-btn-small cancel'; cancelBtn.textContent = 'cancel'; cancelBtn.addEventListener('click', () => { colorDropdown.classList.remove('show'); }); const chooseBtn = document.createElement('button'); chooseBtn.className = 'color-picker-btn-small choose'; chooseBtn.textContent = 'choose'; chooseBtn.addEventListener('click', () => { const selectedColor = colorPreview.style.backgroundColor; setColorFunction(lineId, selectedColor); colorDropdown.classList.remove('show'); }); buttonsContainer.appendChild(cancelBtn); buttonsContainer.appendChild(chooseBtn); previewSection.appendChild(colorPreview); previewSection.appendChild(buttonsContainer); hueContainer.appendChild(hueSlider); advancedPicker.appendChild(gradientArea); advancedPicker.appendChild(hueContainer); advancedPicker.appendChild(previewSection); colorDropdown.appendChild(advancedPicker); // Add interaction handlers for advanced picker setupAdvancedColorPicker(gradientArea, hueSlider, colorPreview, lineId); } // Setup Advanced Color Picker Interactions function setupAdvancedColorPicker(gradientArea, hueSlider, colorPreview, lineId) { let currentHue = 0; let currentSaturation = 100; let currentLightness = 50; // Convert HSL to RGB function hslToRgb(h, s, l) { h /= 360; s /= 100; l /= 100; const a = s * Math.min(l, 1 - l); const f = n => { const k = (n + h * 12) % 12; return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); }; return [Math.round(f(0) * 255), Math.round(f(8) * 255), Math.round(f(4) * 255)]; } // Convert RGB to Hex function rgbToHex(r, g, b) { return "#" + ((1 << 24) + (r << 16) + (g < 10) { window.errorLog = window.errorLog.slice(-10); } }; // Performance monitoring window.performanceMonitor = { start: function(operation) { this[operation + '_start'] = performance.now(); }, end: function(operation) { const startTime = this[operation + '_start']; if (startTime) { const duration = performance.now() - startTime; console.log(`Performance: ${operation} took ${duration.toFixed(2)}ms`); delete this[operation + '_start']; } } }; // Global initialization function to ensure everything is properly set up window.initializeGlobalFunctions = function() { console.log('Initializing global functions...'); window.performanceMonitor.start('initialization'); try { // Ensure global state exists if (!window.editorState) { window.editorState = { currentAnniversaryTemplate: null, selectedAnniversaryBackground: 'Anniversary-1', selectedBackgroundType: 'image', selectedBackgroundColor: '#ff0000', editorCanvas: null, editorCtx: null, editorUploadedImage: null, isEditorMode: false, anniversaryTemplates: null, editorTextSettings: { editorLine1: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 }, editorLine2: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 }, editorLine3: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 }, editorLine4: { color: '#ffffff', fontSize: 50, fontFamily: 'Arial', shadow: true, shadowWidth: 4 } } }; console.log('Global state initialized'); } // Initialize canvas references const editorCanvas = document.getElementById('editorCanvas'); if (editorCanvas && !window.editorState.editorCanvas) { window.editorState.editorCanvas = editorCanvas; window.editorState.editorCtx = editorCanvas.getContext('2d'); console.log('Global canvas references initialized'); } // Initialize function flags window.confirmTemplateDesignGlobal.isRunning = false; window.backToTemplateSelection.isRunning = false; console.log('Global functions initialized successfully'); window.performanceMonitor.end('initialization'); } catch (error) { window.handleGlobalError(error, 'initializeGlobalFunctions'); } }; // Global error handling window.addEventListener('error', function(event) { window.handleGlobalError(event.error, 'Global Window Error'); }); window.addEventListener('unhandledrejection', function(event) { window.handleGlobalError(event.reason, 'Unhandled Promise Rejection'); }); // Professional page initialization with state restoration function initializePage() { console.log('initializePage: Starting page initialization...'); // Initialize global functions first window.initializeGlobalFunctions(); // Check if we're returning from checkout const returningFromCheckout = localStorage.getItem('returningFromCheckout'); if (returningFromCheckout) { console.log('initializePage: Detected return from checkout, restoring design state...'); // Remove the flag localStorage.removeItem('returningFromCheckout'); // Professional restoration with editor reopening setTimeout(() => { const savedDesign = localStorage.getItem('adDesignData'); const currentPurpose = localStorage.getItem('selectedPurpose'); if (savedDesign && currentPurpose === 'Anniversary') { console.log('initializePage: Restoring anniversary design with editor...'); // Show anniversary templates section first const anniversarySection = document.getElementById('anniversaryTemplatesSection'); if (anniversarySection) { anniversarySection.style.display = 'block'; } } else if (savedDesign && currentPurpose === 'Benefit') { console.log('initializePage: Restoring benefit design with editor...'); // Show benefit templates section first const benefitSection = document.getElementById('benefitTemplatesSection'); if (benefitSection) { benefitSection.style.display = 'block'; } } else if (savedDesign && currentPurpose === 'Christian') { console.log('initializePage: Restoring christian design with editor...'); // Show christian templates section first const christianSection = document.getElementById('christianTemplatesSection'); if (christianSection) { christianSection.style.display = 'block'; } } else if (savedDesign && currentPurpose === 'Graduation') { console.log('initializePage: Restoring graduation design with editor...'); // Show graduation templates section first const graduationSection = document.getElementById('graduationTemplatesSection'); if (graduationSection) { graduationSection.style.display = 'block'; } } if (savedDesign && currentPurpose === 'Holiday') { console.log('initializePage: Restoring holiday design with editor...'); // Show holiday templates section first const holidaySection = document.getElementById('holidayTemplatesSection'); if (holidaySection) { holidaySection.style.display = 'block'; } } if (savedDesign && (currentPurpose === 'Anniversary' || currentPurpose === 'Benefit' || currentPurpose === 'Christian' || currentPurpose === 'Graduation' || currentPurpose === 'Holiday' || currentPurpose === 'Local School' || currentPurpose === 'Love' || currentPurpose === 'Marry Me' || currentPurpose === 'New Born' || currentPurpose === 'Obituary' || currentPurpose === 'Other' || currentPurpose === 'Pet' || currentPurpose === 'Prayer' || currentPurpose === 'Retirement' || currentPurpose === 'Wedding' || currentPurpose === 'Welcome')) { // Open the editor container - ALWAYS keep it open when returning from checkout const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer) { editorContainer.classList.add('active'); console.log('initializePage: Editor container reopened'); // Set flag to ensure editor stays open localStorage.setItem('editorShouldStayOpen', 'true'); } // Restore design state const restored = window.restoreBillboardDesign(); if (restored) { console.log('initializePage: Design state restored successfully'); // Update editor title to show confirmed status (design was confirmed before checkout) updateEditorTitle('confirmed'); // Restore complete UI state setTimeout(() => { if (window.restoreCompleteUIState) { window.restoreCompleteUIState(); console.log('initializePage: Complete UI state restored'); } }, 800); // Try to update canvas if function exists setTimeout(() => { if (window.updateEditorCanvasGlobal) { window.updateEditorCanvasGlobal(); console.log('initializePage: Editor canvas updated after restoration'); } else if (window.updateCanvas) { window.updateCanvas(); console.log('initializePage: Canvas updated after restoration'); } }, 1200); // Ensure editor remains open after all restoration setTimeout(() => { if (editorContainer && !editorContainer.classList.contains('active')) { editorContainer.classList.add('active'); console.log('initializePage: Re-ensured editor container is open'); } }, 1500); } } else { // Regular restoration for non-anniversary templates const restored = window.restoreBillboardDesign(); if (restored) { console.log('initializePage: Design state restored successfully'); setTimeout(() => { if (window.updateCanvas) { window.updateCanvas(); console.log('initializePage: Canvas updated after restoration'); } else if (window.updateBillboardCanvas) { window.updateBillboardCanvas(); console.log('initializePage: Billboard canvas updated after restoration'); } }, 500); } } }, 1000); } else { console.log('initializePage: Normal page load, checking for existing design data...'); // Check for existing design data and restore if available setTimeout(() => { const hasDesignData = localStorage.getItem('adDesignData'); if (hasDesignData) { console.log('initializePage: Found existing design data, attempting restoration...'); window.restoreBillboardDesign(); } }, 2000); } } // Call initialization when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializePage); } else { initializePage(); } // Debug helper function window.debugBillboardSystem = function() { console.log('=== Billboard System Debug Info ==='); console.log('Editor State:', window.editorState); console.log('Error Log:', window.errorLog); console.log('Function States:', { confirmTemplateDesignRunning: window.confirmTemplateDesignGlobal?.isRunning, backToTemplateSelectionRunning: window.backToTemplateSelection?.isRunning }); console.log('DOM Elements:', { editorCanvas: !!document.getElementById('editorCanvas'), confirmBtn: !!document.getElementById('confirmTemplateBtn'), backBtn: !!document.getElementById('backToTemplatesBtn'), editorContainer: !!document.getElementById('templateEditorContainer') }); console.log('LocalStorage:', { selectedPurpose: localStorage.getItem('selectedPurpose'), adDesignData: localStorage.getItem('adDesignData'), adPreviewImage: !!localStorage.getItem('adPreviewImage') }); console.log('=== End Debug Info ==='); }; // Comprehensive restoration test function window.testCompleteRestoration = function() { console.log('=== TESTING COMPLETE RESTORATION FLOW ==='); try { // Test 1: Check if saved data exists const savedData = localStorage.getItem('adDesignData'); if (!savedData) { console.error('TEST FAILED: No saved design data found'); return false; } const designData = JSON.parse(savedData); console.log('✓ Test 1 PASSED: Saved design data found:', designData); // Test 2: Check text restoration let textRestored = true; if (designData.textLines) { ['editorLine1', 'editorLine2', 'editorLine3', 'editorLine4'].forEach((editorId, index) => { const lineKey = `line${index + 1}`; const element = document.getElementById(editorId); if (element && designData.textLines[lineKey]) { if (element.value !== designData.textLines[lineKey]) { console.error(`TEST FAILED: Text not restored for ${editorId}. Expected: "${designData.textLines[lineKey]}", Got: "${element.value}"`); textRestored = false; } } else if (designData.textLines[lineKey]) { console.error(`TEST FAILED: Element ${editorId} not found or no saved text for ${lineKey}`); textRestored = false; } }); } if (textRestored) { console.log('✓ Test 2 PASSED: Text content restored correctly'); } // Test 3: Check color picker restoration let colorsRestored = true; if (designData.uiState && designData.uiState.colorPickerStates) { Object.keys(designData.uiState.colorPickerStates).forEach(btnId => { const btn = document.getElementById(btnId); if (btn) { const expectedColor = designData.uiState.colorPickerStates[btnId]; const actualColor = btn.style.backgroundColor; if (actualColor !== expectedColor) { console.error(`TEST FAILED: Color picker ${btnId} not restored. Expected: "${expectedColor}", Got: "${actualColor}"`); colorsRestored = false; } } else { console.error(`TEST FAILED: Color picker button ${btnId} not found`); colorsRestored = false; } }); } if (colorsRestored) { console.log('✓ Test 3 PASSED: Color picker states restored correctly'); } // Test 4: Check template selection restoration let templateRestored = true; if (designData.template) { const templateCards = document.querySelectorAll('.anniversary-template-card'); let foundSelected = false; templateCards.forEach(card => { if (card.dataset.template === designData.template && card.classList.contains('selected')) { foundSelected = true; } }); if (!foundSelected) { console.error(`TEST FAILED: Template ${designData.template} not visually selected`); templateRestored = false; } } if (templateRestored) { console.log('✓ Test 4 PASSED: Template selection restored correctly'); } // Test 5: Check editor state restoration let editorStateRestored = true; if (window.editorState) { if (window.editorState.currentAnniversaryTemplate !== designData.template) { console.error(`TEST FAILED: Editor state template not restored. Expected: "${designData.template}", Got: "${window.editorState.currentAnniversaryTemplate}"`); editorStateRestored = false; } if (window.editorState.selectedAnniversaryBackground !== designData.bgGraphic) { console.error(`TEST FAILED: Editor state background not restored. Expected: "${designData.bgGraphic}", Got: "${window.editorState.selectedAnniversaryBackground}"`); editorStateRestored = false; } } else { console.error('TEST FAILED: Editor state not found'); editorStateRestored = false; } if (editorStateRestored) { console.log('✓ Test 5 PASSED: Editor state restored correctly'); } // Test 6: Check uploaded image restoration let imageRestored = true; if (designData.uploadedImageData) { if (!window.editorState?.editorUploadedImage) { console.error('TEST FAILED: Uploaded image not restored to editor state'); imageRestored = false; } } if (imageRestored) { console.log('✓ Test 6 PASSED: Uploaded image restored correctly'); } // Overall test result const allTestsPassed = textRestored && colorsRestored && templateRestored && editorStateRestored && imageRestored; if (allTestsPassed) { console.log('🎉 ALL TESTS PASSED: Complete restoration working correctly!'); return true; } else { console.error('❌ SOME TESTS FAILED: Restoration needs fixes'); return false; } } catch (error) { console.error('TEST ERROR: Exception during restoration test:', error); return false; } console.log('=== END RESTORATION TEST ==='); }; // Simulate checkout return flow for testing window.simulateCheckoutReturn = function() { console.log('=== SIMULATING CHECKOUT RETURN FLOW ==='); try { // First, save current state (simulate going to checkout) if (window.saveBillboardData) { window.saveBillboardData(); console.log('✓ Current state saved'); } // Set the return flag (simulate coming back from checkout) localStorage.setItem('returningFromCheckout', 'true'); console.log('✓ Return flag set'); // Clear current UI state (simulate page reload) const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer) { editorContainer.classList.remove('active'); } // Clear template selections document.querySelectorAll('.anniversary-template-card').forEach(card => { card.classList.remove('selected'); }); // Clear color picker states ['editorColorBtn1', 'editorColorBtn2', 'editorColorBtn3', 'editorColorBtn4'].forEach(btnId => { const btn = document.getElementById(btnId); if (btn) { btn.style.backgroundColor = '#ffffff'; } }); console.log('✓ UI state cleared (simulating page reload)'); // Now trigger the restoration (simulate page initialization) setTimeout(() => { console.log('🔄 Triggering restoration...'); // Simulate the restoration flow const savedDesign = localStorage.getItem('adDesignData'); const currentPurpose = localStorage.getItem('selectedPurpose'); if (savedDesign && currentPurpose === 'Anniversary') { // Show anniversary templates section const anniversarySection = document.getElementById('anniversaryTemplatesSection'); if (anniversarySection) { anniversarySection.style.display = 'block'; } } else if (savedDesign && currentPurpose === 'Benefit') { // Show benefit templates section const benefitSection = document.getElementById('benefitTemplatesSection'); if (benefitSection) { benefitSection.style.display = 'block'; } } else if (savedDesign && currentPurpose === 'Christian') { // Show christian templates section const christianSection = document.getElementById('christianTemplatesSection'); if (christianSection) { christianSection.style.display = 'block'; } } else if (savedDesign && currentPurpose === 'Graduation') { // Show graduation templates section const graduationSection = document.getElementById('graduationTemplatesSection'); if (graduationSection) { graduationSection.style.display = 'block'; } } else if (savedDesign && currentPurpose === 'Holiday') { // Show holiday templates section const holidaySection = document.getElementById('holidayTemplatesSection'); if (holidaySection) { holidaySection.style.display = 'block'; } } if (savedDesign && (currentPurpose === 'Anniversary' || currentPurpose === 'Benefit' || currentPurpose === 'Christian' || currentPurpose === 'Graduation' || currentPurpose === 'Holiday' || currentPurpose === 'Local School' || currentPurpose === 'Love' || currentPurpose === 'Marry Me' || currentPurpose === 'New Born' || currentPurpose === 'Obituary' || currentPurpose === 'Other' || currentPurpose === 'Pet' || currentPurpose === 'Prayer' || currentPurpose === 'Retirement' || currentPurpose === 'Wedding' || currentPurpose === 'Welcome')) { // Open the editor container if (editorContainer) { editorContainer.classList.add('active'); console.log('✓ Editor container reopened'); } // Restore design state const restored = window.restoreBillboardDesign(); if (restored) { console.log('✓ Design state restored'); // Restore complete UI state setTimeout(() => { if (window.restoreCompleteUIState) { window.restoreCompleteUIState(); console.log('✓ Complete UI state restored'); } // Update canvas setTimeout(() => { if (window.updateEditorCanvasGlobal) { window.updateEditorCanvasGlobal(); console.log('✓ Canvas updated'); } // Run the test setTimeout(() => { console.log('🧪 Running restoration test...'); const testResult = window.testCompleteRestoration(); if (testResult) { console.log('🎉 SIMULATION SUCCESSFUL: Checkout return flow working correctly!'); } else { console.error('❌ SIMULATION FAILED: Issues found in restoration flow'); } // Clean up localStorage.removeItem('returningFromCheckout'); console.log('=== END SIMULATION ==='); }, 500); }, 500); }, 300); } } }, 1000); } catch (error) { console.error('SIMULATION ERROR:', error); localStorage.removeItem('returningFromCheckout'); } }; // Professional editor state management window.ensureEditorOpen = function() { const currentPurpose = localStorage.getItem('selectedPurpose'); const hasDesignData = localStorage.getItem('adDesignData'); if (currentPurpose === 'Anniversary' && hasDesignData) { console.log('ensureEditorOpen: Opening anniversary editor...'); // Show anniversary templates section const anniversarySection = document.getElementById('anniversaryTemplatesSection'); if (anniversarySection) { anniversarySection.style.display = 'block'; } // Open editor container const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer) { editorContainer.classList.add('active'); console.log('ensureEditorOpen: Editor container opened'); } // Update title to show confirmed status setTimeout(() => { updateEditorTitle('confirmed'); }, 500); return true; } if (currentPurpose === 'Benefit' && hasDesignData) { console.log('ensureEditorOpen: Opening benefit editor...'); // Show benefit templates section const benefitSection = document.getElementById('benefitTemplatesSection'); if (benefitSection) { benefitSection.style.display = 'block'; } // Open editor container const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer) { editorContainer.classList.add('active'); console.log('ensureEditorOpen: Editor container opened'); } return true; } if (currentPurpose === 'Christian' && hasDesignData) { console.log('ensureEditorOpen: Opening christian editor...'); // Show christian templates section const christianSection = document.getElementById('christianTemplatesSection'); if (christianSection) { christianSection.style.display = 'block'; } // Open editor container const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer) { editorContainer.classList.add('active'); console.log('ensureEditorOpen: Editor container opened'); } // Update title to show confirmed status setTimeout(() => { updateEditorTitle('confirmed'); }, 500); return true; } if (currentPurpose === 'Graduation' && hasDesignData) { console.log('ensureEditorOpen: Opening graduation editor...'); // Show graduation templates section const graduationSection = document.getElementById('graduationTemplatesSection'); if (graduationSection) { graduationSection.style.display = 'block'; } // Open editor container const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer) { editorContainer.classList.add('active'); console.log('ensureEditorOpen: Editor container opened'); } // Update title to show confirmed status setTimeout(() => { updateEditorTitle('confirmed'); }, 500); return true; } if (currentPurpose === 'Holiday' && hasDesignData) { console.log('ensureEditorOpen: Opening holiday editor...'); // Show holiday templates section const holidaySection = document.getElementById('holidayTemplatesSection'); if (holidaySection) { holidaySection.style.display = 'block'; } // Open editor container const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer) { editorContainer.classList.add('active'); console.log('ensureEditorOpen: Editor container opened'); } // Update title to show confirmed status setTimeout(() => { updateEditorTitle('confirmed'); }, 500); return true; } return false; }; // Enhanced template selection to maintain editor state window.selectAnniversaryTemplateEnhanced = function(templateName) { console.log('selectAnniversaryTemplateEnhanced: Selecting template:', templateName); // Call original function if it exists if (window.selectAnniversaryTemplate) { window.selectAnniversaryTemplate(templateName); } // Ensure editor stays open after template selection setTimeout(() => { const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer && !editorContainer.classList.contains('active')) { editorContainer.classList.add('active'); console.log('selectAnniversaryTemplateEnhanced: Re-opened editor after template selection'); } }, 100); }; // Global function for template reset window.showAllTemplates = function() { // Close any open editor const editorContainer = document.getElementById('templateEditorContainer'); if (editorContainer && editorContainer.classList.contains('active')) { backToTemplateSelection(); } // Close any open modals const fontModal = document.getElementById('editorFontModal'); if (fontModal && fontModal.style.display === 'flex') { window.closeEditorFontModal(); } const bgDialog = document.getElementById('backgroundGraphicDialog'); if (bgDialog && bgDialog.classList.contains('show')) { bgDialog.classList.remove('show'); } // Reset template selections currentAnniversaryTemplate = null; currentBenefitTemplate = null; currentChristianTemplate = null; currentGraduationTemplate = null; currentHolidayTemplate = null; currentLocalSchoolTemplate = null; currentLoveTemplate = null; currentMarryMeTemplate = null; editorUploadedImage = null; syncEditorState(); document.querySelectorAll('.anniversary-template-card, .benefit-template-card, .christian-template-card, .graduation-template-card, .holiday-template-card, .local-school-template-card, .love-template-card, .marry-me-template-card, .newborn-template-card, .obituary-template-card, .other-template-card, .pet-template-card, .prayer-template-card, .retirement-template-card, .wedding-template-card').forEach(card => { card.classList.remove('selected'); }); // Reset to show all templates const purposeDisplay = document.getElementById('purposeDisplay'); if (purposeDisplay) { purposeDisplay.style.display = 'none'; } localStorage.removeItem('selectedPurpose'); const selectedPurposeInput = document.getElementById('selectedPurpose'); if (selectedPurposeInput) { selectedPurposeInput.value = ''; } // Reset current purpose currentPurpose = null; // Show default template state showDefaultTemplateState(); console.log('Templates reset to default state'); }; // Image Resize Dialog Functions let originalImageForResize = null; let cropData = { x: 50, y: 50, width: 200, height: 200 }; let isDragging = false; let isResizing = false; let dragStart = { x: 0, y: 0 }; let resizeHandle = null; let imageContainer = null; // Global mouse event handlers for image resize function handleMouseMove(e) { const canvas = document.getElementById('imageResizeCanvas'); if (!canvas) return; const rect = canvas.getBoundingClientRect(); const mouseX = e.clientX - rect.left; const mouseY = e.clientY - rect.top; if (isDragging) { let newX = mouseX - dragStart.x; let newY = mouseY - dragStart.y; // Keep within bounds newX = Math.max(0, Math.min(newX, canvas.offsetWidth - cropData.width)); newY = Math.max(0, Math.min(newY, canvas.offsetHeight - cropData.height)); cropData.x = newX; cropData.y = newY; updateCropOverlay(); } else if (isResizing && resizeHandle) { const deltaX = mouseX - dragStart.x; const deltaY = mouseY - dragStart.y; // For 1:1 aspect ratio, use the larger absolute delta const delta = Math.max(Math.abs(deltaX), Math.abs(deltaY)); const signX = deltaX >= 0 ? 1 : -1; const signY = deltaY >= 0 ? 1 : -1; let newWidth = cropData.width; let newHeight = cropData.height; let newX = cropData.x; let newY = cropData.y; if (resizeHandle === 'se') { newWidth = cropData.width + delta * signX; newHeight = newWidth; // 1:1 aspect ratio } else if (resizeHandle === 'nw') { newWidth = cropData.width - delta * signX; newHeight = newWidth; // 1:1 aspect ratio newX = cropData.x + (cropData.width - newWidth); newY = cropData.y + (cropData.height - newHeight); } else if (resizeHandle === 'ne') { newWidth = cropData.width + delta * signX; newHeight = newWidth; // 1:1 aspect ratio newY = cropData.y + (cropData.height - newHeight); } else if (resizeHandle === 'sw') { newWidth = cropData.width - delta * signX; newHeight = newWidth; // 1:1 aspect ratio newX = cropData.x + (cropData.width - newWidth); } // Ensure minimum size and bounds if (newWidth >= 50 && newHeight >= 50 && newX >= 0 && newY >= 0 && newX + newWidth <= canvas.offsetWidth && newY + newHeight maxWidth || displayHeight > maxHeight) { const scaleX = maxWidth / displayWidth; const scaleY = maxHeight / displayHeight; const scale = Math.min(scaleX, scaleY); displayWidth = Math.floor(displayWidth * scale); displayHeight = Math.floor(displayHeight * scale); } // Set image size resizeImage.style.width = displayWidth + 'px'; resizeImage.style.height = displayHeight + 'px'; // Set canvas size to match image canvas.style.width = displayWidth + 'px'; canvas.style.height = displayHeight + 'px'; // Initialize crop overlay (1:1 aspect ratio, centered) const cropSize = Math.min(displayWidth, displayHeight) * 0.5; cropData = { x: (displayWidth - cropSize) / 2, y: (displayHeight - cropSize) / 2, width: cropSize, height: cropSize }; console.log('Crop data initialized:', cropData); updateCropOverlay(); setupCropInteractions(); // Add global event listeners for mouse interactions document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); }; try { modal.showModal(); // Ensure proper centering modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.margin = 'auto'; console.log('Image resize modal opened using modal method'); } catch (error) { // Fallback for browsers that don't support showModal modal.style.display = 'flex'; modal.style.zIndex = '2000'; modal.style.position = 'fixed'; modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.margin = 'auto'; console.log('Image resize modal opened using fallback method'); } } function updateCropOverlay() { const overlay = document.getElementById('cropOverlay'); if (overlay) { overlay.style.left = cropData.x + 'px'; overlay.style.top = cropData.y + 'px'; overlay.style.width = cropData.width + 'px'; overlay.style.height = cropData.height + 'px'; console.log('Overlay updated:', cropData); } } function setupCropInteractions() { const overlay = document.getElementById('cropOverlay'); const canvas = document.getElementById('imageResizeCanvas'); if (!overlay || !canvas) { console.error('Overlay or canvas not found'); return; } // Remove existing listeners overlay.removeEventListener('mousedown', handleOverlayMouseDown); // Make overlay draggable function handleOverlayMouseDown(e) { if (e.target.classList.contains('crop-handle')) return; console.log('Starting drag'); isDragging = true; const rect = canvas.getBoundingClientRect(); dragStart.x = e.clientX - rect.left - cropData.x; dragStart.y = e.clientY - rect.top - cropData.y; e.preventDefault(); } overlay.addEventListener('mousedown', handleOverlayMouseDown); // Handle resize handles const handles = overlay.querySelectorAll('.crop-handle'); handles.forEach(handle => { handle.addEventListener('mousedown', function(e) { console.log('Starting resize with handle:', handle.classList[1]); isResizing = true; resizeHandle = handle.classList[1]; // nw, ne, sw, se const rect = canvas.getBoundingClientRect(); dragStart.x = e.clientX - rect.left; dragStart.y = e.clientY - rect.top; e.preventDefault(); e.stopPropagation(); }); }); } window.cancelImageResize = function() { console.log('Canceling image resize'); const modal = document.getElementById('imageResizeModal'); try { modal.close(); console.log('Image resize modal closed using modal method'); } catch (error) { // Fallback for browsers that don't support close modal.style.display = 'none'; console.log('Image resize modal closed using fallback method'); } originalImageForResize = null; // Clean up event listeners document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); }; window.confirmImageResize = function() { console.log('Confirming image resize'); if (!originalImageForResize) { console.error('No original image found'); return; } try { // Create a canvas to crop the image const cropCanvas = document.createElement('canvas'); const cropCtx = cropCanvas.getContext('2d'); // Set canvas size to crop dimensions (1:1 aspect ratio) const finalSize = 400; // Final output size cropCanvas.width = finalSize; cropCanvas.height = finalSize; // Calculate scale factor between display and actual image const resizeImage = document.getElementById('resizeImage'); const scaleX = originalImageForResize.width / resizeImage.offsetWidth; const scaleY = originalImageForResize.height / resizeImage.offsetHeight; console.log('Scale factors:', scaleX, scaleY); console.log('Crop data:', cropData); // Calculate actual crop coordinates const actualCropX = cropData.x * scaleX; const actualCropY = cropData.y * scaleY; const actualCropWidth = cropData.width * scaleX; const actualCropHeight = cropData.height * scaleY; console.log('Actual crop:', actualCropX, actualCropY, actualCropWidth, actualCropHeight); // Draw the cropped image cropCtx.drawImage( originalImageForResize, actualCropX, actualCropY, actualCropWidth, actualCropHeight, 0, 0, finalSize, finalSize ); // Convert to image and set as uploaded image const croppedImage = new Image(); croppedImage.onload = function() { console.log('Cropped image loaded successfully'); // Set the cropped image in global state if (window.editorState) { window.editorState.editorUploadedImage = croppedImage; console.log('Cropped image set in global state'); } // Force canvas update with a slight delay to ensure proper rendering setTimeout(() => { if (window.updateEditorCanvasGlobal) { window.updateEditorCanvasGlobal(); console.log('Canvas updated with cropped image via global function'); } else if (window.updateEditorCanvas) { window.updateEditorCanvas(); console.log('Canvas updated with cropped image via local function'); } else { console.error('No updateEditorCanvas function available'); } }, 100); // Close modal const modal = document.getElementById('imageResizeModal'); try { modal.close(); console.log('Image resize modal closed after confirm using modal method'); } catch (error) { // Fallback for browsers that don't support close modal.style.display = 'none'; console.log('Image resize modal closed after confirm using fallback method'); } originalImageForResize = null; // Clean up event listeners document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); }; // Ensure the image loads properly croppedImage.crossOrigin = 'anonymous'; croppedImage.src = cropCanvas.toDataURL('image/png'); } catch (error) { console.error('Error during image resize:', error); } }; // Auto-run test on page load (for development) setTimeout(() => { if (window.location.search.includes('test=true')) { window.testUniversalTemplateSystem(); } }, 2000);