/* 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);