/* 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
Customize Design
Upload Your Photo
📷
Click to upload your photo
Accepted formats: JPG, PNG. High resolution recommended.
// 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);