insert property data

This commit is contained in:
Ubuntu 2025-09-10 17:40:07 +05:30
parent 9bb7f6a727
commit 2bb4747426
3 changed files with 667 additions and 253 deletions

View File

@ -247,7 +247,7 @@
.draggable-table-container .resize-handle.resize-sw { bottom: -4px; left: -4px; cursor: sw-resize; } .draggable-table-container .resize-handle.resize-sw { bottom: -4px; left: -4px; cursor: sw-resize; }
.draggable-table-container .resize-handle.resize-se { bottom: -4px; right: -4px; cursor: se-resize; } .draggable-table-container .resize-handle.resize-se { bottom: -4px; right: -4px; cursor: se-resize; }
/* Draggable table container (mirrors images) */ /* Draggable table container (mirrors images) */
.draggable-table-container { position: absolute; cursor: move; user-select: none; z-index: 1000; border: 2px dashed #667eea; border-radius: 8px; background: #ffffff; } .draggable-table-container { position: absolute; cursor: move; user-select: none; z-index: 1000; border: 2px solid transparent; border-radius: 8px; background: #ffffff; }
.draggable-table-container .resize-handle { opacity: 1; } .draggable-table-container .resize-handle { opacity: 1; }
.asgar1-preview .cover-hero { position: relative; height: 180px; overflow: hidden; border-radius: 10px; margin: 12px; background: #222; background-size: cover; background-position: center; } .asgar1-preview .cover-hero { position: relative; height: 180px; overflow: hidden; border-radius: 10px; margin: 12px; background: #222; background-size: cover; background-position: center; }
.asgar1-preview .cover-hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(0,0,0,0.15), rgba(0,0,0,0.35)); } .asgar1-preview .cover-hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(0,0,0,0.15), rgba(0,0,0,0.35)); }
@ -7679,7 +7679,7 @@ late particularay
.draggable-element:hover, .draggable-element:hover,
.draggable-element.selected { .draggable-element.selected {
border-color: #C0A062; /* Gold accent theme */ border: 2px solid transparent !important; /* Keep transparent border */
background: rgba(102, 126, 234, 0.1); background: rgba(102, 126, 234, 0.1);
box-shadow: 0 2px 10px rgba(102, 126, 234, 0.3); box-shadow: 0 2px 10px rgba(102, 126, 234, 0.3);
} }
@ -8536,20 +8536,27 @@ button, .btn, .toolbar-button, .export-pdf-btn {
z-index: 1000; z-index: 1000;
min-width: 100px; min-width: 100px;
min-height: 100px; min-height: 100px;
border: 2px dashed #667eea; border: none !important;
border-radius: 8px; border-radius: 4px;
background: rgba(102, 126, 234, 0.1); background: transparent;
padding: 5px; padding: 0;
transition: all 0.2s ease; transition: all 0.2s ease;
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
box-shadow: none;
}
.draggable-image-container img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 4px;
} }
.draggable-image-container img { display: block; }
.draggable-image-container:hover { .draggable-image-container:hover {
border-color: #764ba2; border: none !important;
background: rgba(102, 126, 234, 0.15); background: transparent;
transform: translate3d(0, -2px, 0); transform: translate3d(0, 0, 0);
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
} }
/* Minimal frame variant to avoid visual/positional shifts when wrapping existing images */ /* Minimal frame variant to avoid visual/positional shifts when wrapping existing images */
@ -8558,9 +8565,9 @@ button, .btn, .toolbar-button, .export-pdf-btn {
.draggable-image-container.no-frame.dragging { border: none; background: transparent; box-shadow: none; transform: none; } .draggable-image-container.no-frame.dragging { border: none; background: transparent; box-shadow: none; transform: none; }
.draggable-image-container.dragging { .draggable-image-container.dragging {
border-color: #764ba2; border: none !important;
background: rgba(102, 126, 234, 0.2); background: transparent;
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
transform: scale(1.02); transform: scale(1.02);
transition: none; transition: none;
z-index: 1001; z-index: 1001;
@ -8658,15 +8665,15 @@ button, .btn, .toolbar-button, .export-pdf-btn {
/* Dragging state */ /* Dragging state */
.draggable-image-container.dragging { .draggable-image-container.dragging {
border-color: #764ba2; border: none !important;
background: rgba(102, 126, 234, 0.2); background: transparent;
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
} }
/* Resizing state */ /* Resizing state */
.draggable-image-container.resizing { .draggable-image-container.resizing {
border-color: #ff6b6b; border: none !important;
background: rgba(255, 107, 107, 0.1); background: transparent;
} }
/* Text Alignment Section - Fixed Width */ /* Text Alignment Section - Fixed Width */
@ -10431,8 +10438,8 @@ img[draggable="true"] {
} }
.draggable-image-container.selected { .draggable-image-container.selected {
border-color: #C0A062; /* Gold accent theme */ border: none !important;
box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.2); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
} }
.draggable-image-container img { .draggable-image-container img {
@ -10499,7 +10506,7 @@ img[draggable="true"] {
overflow: hidden; overflow: hidden;
} }
.draggable-table-container.selected { .draggable-table-container.selected {
border-color: #C0A062; /* Gold accent theme */ border: 2px solid transparent !important; /* Keep transparent border */
box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.2); box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.2);
} }

View File

@ -846,37 +846,76 @@
<div class="toolbar-section"> <div class="toolbar-section">
<div class="toolbar-section-title">Insert Property Data</div> <div class="toolbar-section-title">Insert Property Data</div>
<div class="property-insert-grid"> <div class="property-insert-grid">
<!-- Basic Information -->
<button class="property-insert-btn" onclick={insertPropertyName} <button class="property-insert-btn" onclick={insertPropertyName}
title="Insert Property Name"> title="Insert Property Name">
Name Name
</button> </button>
<button class="property-insert-btn" onclick={insertPropertyPrice} <button class="property-insert-btn" onclick={insertPropertyTitle}
title="Insert Property Price"> title="Insert Property Title">
Price Title
</button> </button>
<button class="property-insert-btn" onclick={insertPropertyType} <button class="property-insert-btn" onclick={insertPropertyType}
title="Insert Property Type"> title="Insert Property Type">
Type Type
</button> </button>
<button class="property-insert-btn" onclick={insertPropertyBedrooms}
title="Insert Bedrooms">
Beds
</button> <!-- Pricing Information -->
<button class="property-insert-btn" onclick={insertPropertyBathrooms} <button class="property-insert-btn" onclick={insertPropertyPrice}
title="Insert Bathrooms"> title="Insert Property Price">
Baths Price
</button> </button>
<button class="property-insert-btn" onclick={insertPropertySqft} <button class="property-insert-btn" onclick={insertPropertySqft}
title="Insert Square Footage"> title="Insert Square Footage">
Sq Ft Sq Ft
</button> </button>
<button class="property-insert-btn" onclick={insertPropertyAddress} title="Insert Address"> <button class="property-insert-btn" onclick={insertPropertyFloor}
Address title="Insert Floor">
Floor
</button> </button>
<button class="property-insert-btn" onclick={insertPropertyDescription} <button class="property-insert-btn" onclick={insertPropertyBuildYear}
title="Insert Description"> title="Insert Build Year">
Description Year
</button> </button>
<button class="property-insert-btn" onclick={insertPropertyParking}
title="Insert Parking">
Parking
</button>
<button class="property-insert-btn" onclick={insertPropertyFurnished}
title="Insert Furnished Status">
Furnished
</button>
<button class="property-insert-btn" onclick={insertPropertyOfferingType}
title="Insert Offering Type">
Offering
</button>
<!-- Location Information -->
<button class="property-insert-btn" onclick={insertPropertyCity}
title="Insert City">
City
</button>
<button class="property-insert-btn" onclick={insertPropertyContactEmail}
title="Insert Contact Email">
Email
</button>
<button class="property-insert-btn" onclick={insertPropertyContactPhone}
title="Insert Contact Phone">
Phone
</button>
</div> </div>
</div> </div>

View File

@ -1399,6 +1399,16 @@ export default class PropertyTemplateSelector extends LightningElement {
if (editorFrame && editorFrame.innerHTML) { if (editorFrame && editorFrame.innerHTML) {
htmlContent = editorFrame.innerHTML; htmlContent = editorFrame.innerHTML;
// Check if there are draggable elements - if so, don't regenerate template
const tempDiv = document.createElement("div");
tempDiv.innerHTML = htmlContent;
const draggableElements = tempDiv.querySelectorAll(
".draggable-element, .draggable-image-container, .draggable-table-container"
);
if (draggableElements.length === 0 && htmlContent.length < 100) {
// Only regenerate if truly empty and no draggable elements
htmlContent = this.createCompleteTemplateHTML();
}
} else { } else {
// Fallback: generate template HTML if editor is empty // Fallback: generate template HTML if editor is empty
htmlContent = this.createCompleteTemplateHTML(); htmlContent = this.createCompleteTemplateHTML();
@ -1502,15 +1512,92 @@ export default class PropertyTemplateSelector extends LightningElement {
} }
// Clean HTML content for PDF generation by removing editor controls // Clean HTML content for PDF generation by removing editor controls
cleanHtmlForPdf(htmlContent) { cleanHtmlForPdf(htmlContent) {
// Wrap editor content so we can sanitize before PDF // Use string manipulation to preserve inline styles better
const tempDiv = document.createElement("div"); let cleanedHtml = htmlContent;
tempDiv.innerHTML = htmlContent;
// Remove preview-only UI like no-image placeholders // Remove preview-only UI elements using regex
const previewOnly = tempDiv.querySelectorAll( cleanedHtml = cleanedHtml.replace(
'[data-preview-only="true"], .floating-placeholder, .placeholder-badge, .placeholder-bubble' /<[^>]*(?:data-preview-only="true"|class="[^"]*(?:floating-placeholder|placeholder-badge|placeholder-bubble)[^"]*")[^>]*>.*?<\/[^>]*>/gi,
''
); );
previewOnly.forEach((el) => el.remove());
// Remove resize handles using regex
cleanedHtml = cleanedHtml.replace(
/<div[^>]*class="[^"]*resize-handle[^"]*"[^>]*>.*?<\/div>/gi,
''
);
// Remove delete buttons using regex
cleanedHtml = cleanedHtml.replace(
/<button[^>]*class="[^"]*delete-btn[^"]*"[^>]*>.*?<\/button>/gi,
''
);
// Remove table controls using regex
cleanedHtml = cleanedHtml.replace(
/<div[^>]*class="[^"]*table-controls-overlay[^"]*"[^>]*>.*?<\/div>/gi,
''
);
// Remove editor-specific classes but preserve positioning
cleanedHtml = cleanedHtml.replace(
/class="([^"]*)(?:selected|dragging)([^"]*)"/gi,
'class="$1$2"'
);
// Clean up empty class attributes
cleanedHtml = cleanedHtml.replace(/class="\s*"/gi, '');
// Now use DOM manipulation for more complex operations
const tempDiv = document.createElement("div");
tempDiv.innerHTML = cleanedHtml;
// Process draggable elements to ensure proper styling
const draggableElements = tempDiv.querySelectorAll(
".draggable-element, .draggable-image-container, .draggable-table-container"
);
draggableElements.forEach((el) => {
// Ensure absolute positioning is maintained and properly formatted
if (el.style.position === "absolute" || el.classList.contains('draggable-image-container') || el.classList.contains('draggable-element')) {
el.style.position = "absolute";
// Ensure positioning values are properly set
if (!el.style.left) el.style.left = "0px";
if (!el.style.top) el.style.top = "0px";
if (!el.style.zIndex) el.style.zIndex = "1000";
// Ensure proper box-sizing
el.style.boxSizing = "border-box";
// Remove any borders that might interfere
el.style.border = "none";
el.style.outline = "none";
}
// Ensure images inside draggable containers maintain proper styling
const images = el.querySelectorAll("img");
images.forEach(img => {
img.style.width = "100%";
img.style.height = "100%";
img.style.objectFit = "cover";
img.style.display = "block";
img.style.border = "none";
img.style.outline = "none";
});
// Ensure tables maintain proper styling
const tables = el.querySelectorAll("table");
tables.forEach(table => {
table.style.width = "100%";
table.style.height = "100%";
table.style.borderCollapse = "collapse";
table.style.border = "none";
table.style.outline = "none";
});
// Remove any editor-specific classes that might interfere
el.classList.remove('selected', 'dragging', 'resizing');
});
// Ensure list styling is preserved in output // Ensure list styling is preserved in output
const lists = tempDiv.querySelectorAll("ul, ol"); const lists = tempDiv.querySelectorAll("ul, ol");
@ -1577,29 +1664,54 @@ export default class PropertyTemplateSelector extends LightningElement {
// First, ensure we have template content loaded // First, ensure we have template content loaded
let htmlContent = ""; let htmlContent = "";
// Check if preview frame has content // Check if preview frame has content - get from all editor elements
const previewFrame = this.template.querySelector( const previewFrames = this.template.querySelectorAll(
".enhanced-editor-content" ".enhanced-editor-content"
); );
if (!previewFrame) { if (!previewFrames || previewFrames.length === 0) {
throw new Error("Editor content not found"); throw new Error("Editor content not found");
} }
htmlContent = previewFrame.innerHTML; // Combine content from all editor frames
htmlContent = "";
previewFrames.forEach((frame, index) => {
if (frame.innerHTML && frame.innerHTML.trim()) {
if (htmlContent) {
htmlContent += `<div class="page-break"></div>${frame.innerHTML}`;
} else {
htmlContent = frame.innerHTML;
}
}
});
// Debug: Check if draggable elements are present // Debug: Check if draggable elements are present before cleaning
const tempDiv = document.createElement("div"); const tempDiv = document.createElement("div");
tempDiv.innerHTML = htmlContent; tempDiv.innerHTML = htmlContent;
const draggableElements = tempDiv.querySelectorAll( const draggableElements = tempDiv.querySelectorAll(
".draggable-element, .draggable-image-container, .draggable-table-container" ".draggable-element, .draggable-image-container, .draggable-table-container"
); );
draggableElements.forEach((el, index) => {}); console.log(`Found ${draggableElements.length} draggable elements before cleaning`);
// If preview frame is empty, generate the template HTML first // Log detailed information about each draggable element
draggableElements.forEach((el, index) => {
console.log(`Before cleaning - Element ${index}:`, {
tagName: el.tagName,
className: el.className,
position: el.style.position,
left: el.style.left,
top: el.style.top,
width: el.style.width,
height: el.style.height,
zIndex: el.style.zIndex,
outerHTML: el.outerHTML.substring(0, 300) + "..."
});
});
// Only regenerate template if there's truly no content (not just short content)
if ( if (
!htmlContent || !htmlContent ||
htmlContent.trim() === "" || htmlContent.trim() === "" ||
htmlContent.length < 100 (htmlContent.length < 100 && draggableElements.length === 0)
) { ) {
this.showProgress("Generating template content..."); this.showProgress("Generating template content...");
@ -1615,6 +1727,33 @@ export default class PropertyTemplateSelector extends LightningElement {
} }
} }
// Clean HTML content for PDF generation to preserve exact positioning
htmlContent = this.cleanHtmlForPdf(htmlContent);
// Debug: Check if draggable elements are still present after cleaning
const tempDivAfter = document.createElement("div");
tempDivAfter.innerHTML = htmlContent;
const draggableElementsAfter = tempDivAfter.querySelectorAll(
".draggable-element, .draggable-image-container, .draggable-table-container"
);
console.log(`Found ${draggableElementsAfter.length} draggable elements after cleaning`);
// Log positioning information for debugging
draggableElementsAfter.forEach((el, index) => {
console.log(`Element ${index}:`, {
position: el.style.position,
left: el.style.left,
top: el.style.top,
width: el.style.width,
height: el.style.height,
className: el.className,
outerHTML: el.outerHTML.substring(0, 200) + "..."
});
});
// Log the actual HTML being sent to PDF generation
console.log("HTML Content being sent to PDF:", htmlContent.substring(0, 1000) + "...");
// Ensure we have a complete HTML document with page size information // Ensure we have a complete HTML document with page size information
if (!htmlContent.includes("<!DOCTYPE html>")) { if (!htmlContent.includes("<!DOCTYPE html>")) {
htmlContent = `<!DOCTYPE html> htmlContent = `<!DOCTYPE html>
@ -1664,6 +1803,61 @@ export default class PropertyTemplateSelector extends LightningElement {
` `
: "" : ""
} }
/* Draggable elements positioning for PDF */
.draggable-element, .draggable-image-container, .draggable-table-container {
position: absolute !important;
box-sizing: border-box !important;
display: block !important;
border: none !important;
outline: none !important;
margin: 0 !important;
padding: 0 !important;
}
.draggable-element img, .draggable-image-container img {
width: 100% !important;
height: 100% !important;
object-fit: cover !important;
display: block !important;
border: none !important;
outline: none !important;
margin: 0 !important;
padding: 0 !important;
}
.draggable-table-container table {
width: 100% !important;
height: 100% !important;
border-collapse: collapse !important;
border: none !important;
outline: none !important;
margin: 0 !important;
padding: 0 !important;
}
/* Ensure absolute positioned elements are rendered correctly in PDF */
*[style*="position: absolute"] {
position: absolute !important;
}
/* Force positioning for any element with inline styles */
div[style*="left"], div[style*="top"] {
position: absolute !important;
}
/* Ensure images maintain their positioning */
img[style*="left"], img[style*="top"] {
position: absolute !important;
}
/* Remove all borders and ensure clean positioning */
.draggable-element, .draggable-image-container, .draggable-table-container,
.draggable-element *, .draggable-image-container *, .draggable-table-container * {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
</style> </style>
<meta name="page-size" content="${this.selectedPageSize}"> <meta name="page-size" content="${this.selectedPageSize}">
</head> </head>
@ -1837,6 +2031,55 @@ export default class PropertyTemplateSelector extends LightningElement {
body { body {
overflow: visible !important; overflow: visible !important;
} }
/* Draggable elements positioning for PDF */
.draggable-element, .draggable-image-container, .draggable-table-container {
position: absolute !important;
box-sizing: border-box !important;
display: block !important;
border: none !important;
outline: none !important;
margin: 0 !important;
padding: 0 !important;
}
.draggable-element img, .draggable-image-container img {
width: 100% !important;
height: 100% !important;
object-fit: cover !important;
display: block !important;
border: none !important;
outline: none !important;
margin: 0 !important;
padding: 0 !important;
}
.draggable-table-container table {
width: 100% !important;
height: 100% !important;
border-collapse: collapse !important;
border: none !important;
outline: none !important;
margin: 0 !important;
padding: 0 !important;
}
/* Ensure absolute positioned elements are rendered correctly in PDF */
*[style*="position: absolute"] {
position: absolute !important;
}
/* Force positioning for any element with inline styles */
div[style*="left"], div[style*="top"] {
position: absolute !important;
}
/* Ensure images maintain their positioning */
img[style*="left"], img[style*="top"] {
position: absolute !important;
}
/* Remove all borders and ensure clean positioning */
.draggable-element, .draggable-image-container, .draggable-table-container,
.draggable-element *, .draggable-image-container *, .draggable-table-container * {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
</style> </style>
</head> </head>
<body> <body>
@ -2102,6 +2345,16 @@ export default class PropertyTemplateSelector extends LightningElement {
if (editorFrame && editorFrame.innerHTML) { if (editorFrame && editorFrame.innerHTML) {
htmlContent = editorFrame.innerHTML; htmlContent = editorFrame.innerHTML;
// Check if there are draggable elements - if so, don't regenerate template
const tempDiv = document.createElement("div");
tempDiv.innerHTML = htmlContent;
const draggableElements = tempDiv.querySelectorAll(
".draggable-element, .draggable-image-container, .draggable-table-container"
);
if (draggableElements.length === 0 && htmlContent.length < 100) {
// Only regenerate if truly empty and no draggable elements
htmlContent = this.createCompleteTemplateHTML();
}
} else { } else {
htmlContent = this.createCompleteTemplateHTML(); htmlContent = this.createCompleteTemplateHTML();
} }
@ -2452,10 +2705,14 @@ export default class PropertyTemplateSelector extends LightningElement {
const buildYear = data.Build_Year__c || data.buildYear || "N/A"; const buildYear = data.Build_Year__c || data.buildYear || "N/A";
const titleEnglish = const titleEnglish =
data.Title_English__c || data.titleEnglish || "Property Title"; data.Title_English__c || data.titleEnglish || "Property Title";
const descriptionEnglish =
const descriptionEnglish = this.formatDescriptionForPDF(
data.Description_English__c || data.Description_English__c ||
data.descriptionEnglish || data.descriptionEnglish ||
"Property Description"; data.description ||
"please add your description here..."
);
const rentPriceMin = data.Rent_Price_Min__c || data.rentPriceMin || "N/A"; const rentPriceMin = data.Rent_Price_Min__c || data.rentPriceMin || "N/A";
const salePriceMin = data.Sale_Price_Min__c || data.salePriceMin || "N/A"; const salePriceMin = data.Sale_Price_Min__c || data.salePriceMin || "N/A";
@ -2470,186 +2727,183 @@ export default class PropertyTemplateSelector extends LightningElement {
for (let i = imagesPerPage; i < allImages.length; i += imagesPerPage) { for (let i = imagesPerPage; i < allImages.length; i += imagesPerPage) {
const chunk = allImages.slice(i, i + imagesPerPage); const chunk = allImages.slice(i, i + imagesPerPage);
additionalGalleryPagesHTML += ` additionalGalleryPagesHTML += `
<div class="brochure-page" style="font-family: Arial, sans-serif; padding: 20px; max-width: 800px; margin: 0 auto; page-break-before: always;"> <div class="brochure-page a4" style="page-break-before: always;">
<div style="background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;"> <h2>Property Gallery</h2>
<h2 style="color: #0d6efd; border-bottom: 2px solid #0d6efd; padding-bottom: 10px; margin-bottom: 20px; font-size: 1.5rem;">Property Gallery</h2> <div class="gallery-grid">
<div class="gallery-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px;"> ${this.generatePropertyGalleryHTMLForImages(chunk)}
${this.generatePropertyGalleryHTMLForImages(chunk)} </div>
</div> </div>`;
</div>
</div>`;
} }
} }
return ` return `
<div class="brochure-page" style="font-family: Arial, sans-serif; padding: 20px; max-width: 800px; margin: 0 auto;"> <style>
<!-- Header Section --> .brochure-page.a4 {
<div style="position: relative; color: white; padding: 20px; text-align: center; border-radius: 10px; margin-bottom: 20px; overflow: hidden; background: linear-gradient(135deg, #0d6efd 0%, #0b5ed7 100%);"> width: 190mm;
<img src="${this.getExteriorImageUrl()}" alt="Property Header Image" min-height: 277mm;
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; z-index: 1;"> padding: 10mm;
<div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(135deg, rgba(13, 110, 253, 0.82), rgba(11, 94, 215, 0.82)); z-index: 2;"></div> margin: auto;
<div style="position: relative; z-index: 3;"> background: white;
<h1 style="margin: 0; font-size: 2.5rem; text-shadow: 2px 2px 4px rgba(0,0,0,0.5);">${propertyName}</h1> font-family: Arial, sans-serif;
<p style="margin: 10px 0 0 0; font-size: 1.2rem; opacity: 0.9; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);">${location}</p> box-shadow: 0 0 0.5cm rgba(0,0,0,0.2);
<p style="margin: 5px 0 0 0; font-size: 1.5rem; font-weight: bold; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);">${price}</p> box-sizing: border-box;
</div> page-break-after: always;
</div> }
<!-- Basic Information --> @media print {
<div style="background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;"> @page {
<h2 style="color: #0d6efd; border-bottom: 2px solid #0d6efd; padding-bottom: 10px;">Basic Information</h2> size: A4;
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> margin: 10mm;
<div><strong>Property Type:</strong> ${propertyType}</div> }
<div><strong>Status:</strong> ${status}</div>
<div><strong>City:</strong> ${city}</div>
<div><strong>Community:</strong> ${community}</div>
<div><strong>Sub Community:</strong> ${subCommunity}</div>
<div><strong>Furnished:</strong> ${furnished}</div>
</div>
</div>
<!-- Contact Details --> body {
<div style="background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;"> margin: 0;
<h2 style="color: #0d6efd; border-bottom: 2px solid #0d6efd; padding-bottom: 10px;">Contact Details</h2> padding: 0;
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> -webkit-print-color-adjust: exact;
<div><strong>Name:</strong> ${ }
data.contactName || "N/A"
}</div>
<div><strong>Email:</strong> ${
data.contactEmail || "N/A"
}</div>
<div><strong>Phone:</strong> ${
data.contactPhone || "N/A"
}</div>
</div>
</div>
<!-- Location Details --> .brochure-page.a4 {
<div style="background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;"> box-shadow: none;
<h2 style="color: #0d6efd; border-bottom: 2px solid #0d6efd; padding-bottom: 10px;">Location Details</h2> page-break-inside: avoid;
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> }
<div><strong>City (Bayut):</strong> ${ }
data.cityBayut || "N/A"
}</div>
<div><strong>City (Propertyfinder):</strong> ${
data.cityPropertyfinder || "N/A"
}</div>
<div><strong>Community (Bayut):</strong> ${
data.communityBayut || "N/A"
}</div>
<div><strong>Sub Community (Bayut):</strong> ${
data.subCommunityBayut || "N/A"
}</div>
<div><strong>Locality (Bayut):</strong> ${
data.localityBayut || "N/A"
}</div>
<div><strong>Sub Locality (Bayut):</strong> ${
data.subLocalityBayut || "N/A"
}</div>
<div><strong>Tower (Bayut):</strong> ${
data.towerBayut || "N/A"
}</div>
<div><strong>Unit Number:</strong> ${
data.unitNumber || "N/A"
}</div>
</div>
</div>
<!-- Specifications --> .gallery-grid {
<div style="background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;"> display: grid;
<h2 style="color: #0d6efd; border-bottom: 2px solid #0d6efd; padding-bottom: 10px;">Specifications</h2> grid-template-columns: repeat(auto-fit, minmax(60mm, 1fr));
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> gap: 10mm;
<div><strong>Bedrooms:</strong> ${bedrooms}</div> }
<div><strong>Bathrooms:</strong> ${bathrooms}</div>
<div><strong>Size:</strong> ${size} ${sizeUnit}</div>
<div><strong>Parking Spaces:</strong> ${parkingSpaces}</div>
<div><strong>Build Year:</strong> ${buildYear}</div>
<div><strong>Floor:</strong> ${
data.floor || "N/A"
}</div>
</div>
</div>
<!-- Pricing -->
<div style="background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;">
<h2 style="color: #0d6efd; border-bottom: 2px solid #0d6efd; padding-bottom: 10px;">Pricing Information</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div><strong>Rent Price:</strong> ${rentPriceMin}</div>
<div><strong>Sale Price:</strong> ${salePriceMin}</div>
<div><strong>Rent Price (Max):</strong> ${
data.rentPriceMax || "N/A"
}</div>
<div><strong>Sale Price (Max):</strong> ${
data.salePriceMax || "N/A"
}</div>
</div>
</div>
<!-- Rent Availability --> img {
<div style="background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;"> max-width: 100%;
<h2 style="color: #0d6efd; border-bottom: 2px solid #0d6efd; padding-bottom: 10px;">Rent Availability</h2> height: auto;
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> }
<div><strong>Rent Available From:</strong> ${
data.rentAvailableFrom || "N/A"
}</div>
<div><strong>Rent Available To:</strong> ${
data.rentAvailableTo || "N/A"
}</div>
</div>
</div>
<!-- Description --> h1, h2, h3, p {
<div style="background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;"> margin-top: 0;
<h2 style="color: #0d6efd; border-bottom: 2px solid #0d6efd; padding-bottom: 10px; margin-bottom: 20px; font-size: 1.5rem;">Property Description</h2> margin-bottom: 10px;
<div style="margin-bottom: 20px;"> }
<h3 style="color: #333; font-size: 1.2rem; margin-bottom: 10px;">${titleEnglish}</h3> </style>
</div>
<div style="line-height: 1.8; color: #555; font-size: 1rem; text-align: justify; margin-bottom: 20px;">
${descriptionEnglish}
</div>
<div style="border-top: 1px solid #eee; padding-top: 15px;">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; font-size: 0.9rem;">
<div><strong style="color: #0d6efd;">Property Type:</strong> ${propertyType}</div>
<div><strong style="color: #0d6efd;">Status:</strong> ${status}</div>
<div><strong style="color: #0d6efd;">Furnished:</strong> ${furnished}</div>
<div><strong style="color: #0d6efd;">Build Year:</strong> ${buildYear}</div>
</div>
</div>
</div>
<!-- Amenities -->
<div style="background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;">
<h2 style="color: #0d6efd; border-bottom: 2px solid #0d6efd; padding-bottom: 10px;">Amenities & Features</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
<div><strong>Parking Spaces:</strong> ${
data.parkingSpaces || "N/A"
}</div>
<div><strong>Furnished:</strong> ${
data.furnished || "N/A"
}</div>
<div><strong>Offering Type:</strong> ${
data.offeringType || "N/A"
}</div>
<div><strong>Build Year:</strong> ${
data.buildYear || "N/A"
}</div>
</div>
</div>
<div style="background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin-bottom: 20px;"> <div class="brochure-page a4">
<h2 style="color: #0d6efd; border-bottom: 2px solid #0d6efd; padding-bottom: 10px; margin-bottom: 20px; font-size: 1.5rem;">Property Gallery</h2> <!-- Header -->
<div class="gallery-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px;"> <div style="position: relative; color: white; text-align: center; border-radius: 6mm; overflow: hidden; margin-bottom: 10mm;">
${ <img src="${this.getExteriorImageUrl()}" alt="Header Image"
firstChunk.length > 0 style="position: absolute; top: 0; left: 0; width: 100%; height: auto; object-fit: cover; z-index: 1;">
? this.generatePropertyGalleryHTMLForImages( <div style="position: relative; z-index: 2; padding: 20mm 10mm;">
firstChunk <h1>${propertyName}</h1>
) <p>${location}</p>
: this.generatePropertyGalleryHTML() <p style="font-weight: bold; font-size: 1.2rem;">${price}</p>
} </div>
</div> </div>
</div>
</div> <!-- Basic Info -->
${additionalGalleryPagesHTML} <section>
`; <h2>Basic Information</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5mm;">
<div><strong>Property Type:</strong> ${propertyType}</div>
<div><strong>Status:</strong> ${status}</div>
<div><strong>City:</strong> ${city}</div>
<div><strong>Community:</strong> ${community}</div>
<div><strong>Sub Community:</strong> ${subCommunity}</div>
<div><strong>Furnished:</strong> ${furnished}</div>
</div>
</section>
<!-- Contact Details -->
<section>
<h2>Contact Details</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5mm;">
<div><strong>Name:</strong> ${data.contactName || "N/A"}</div>
<div><strong>Email:</strong> ${data.contactEmail || "N/A"}</div>
<div><strong>Phone:</strong> ${data.contactPhone || "N/A"}</div>
</div>
</section>
<!-- Location Details -->
<section>
<h2>Location Details</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5mm;">
<div><strong>City (Bayut):</strong> ${data.cityBayut || "N/A"}</div>
<div><strong>City (Propertyfinder):</strong> ${data.cityPropertyfinder || "N/A"}</div>
<div><strong>Community (Bayut):</strong> ${data.communityBayut || "N/A"}</div>
<div><strong>Sub Community (Bayut):</strong> ${data.subCommunityBayut || "N/A"}</div>
<div><strong>Locality (Bayut):</strong> ${data.localityBayut || "N/A"}</div>
<div><strong>Sub Locality (Bayut):</strong> ${data.subLocalityBayut || "N/A"}</div>
<div><strong>Tower (Bayut):</strong> ${data.towerBayut || "N/A"}</div>
<div><strong>Unit Number:</strong> ${data.unitNumber || "N/A"}</div>
</div>
</section>
<!-- Specifications -->
<section>
<h2>Specifications</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5mm;">
<div><strong>Bedrooms:</strong> ${bedrooms}</div>
<div><strong>Bathrooms:</strong> ${bathrooms}</div>
<div><strong>Size:</strong> ${size} ${sizeUnit}</div>
<div><strong>Parking Spaces:</strong> ${parkingSpaces}</div>
<div><strong>Build Year:</strong> ${buildYear}</div>
<div><strong>Floor:</strong> ${data.floor || "N/A"}</div>
</div>
</section>
<!-- Pricing -->
<section>
<h2>Pricing</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5mm;">
<div><strong>Rent Price:</strong> ${rentPriceMin}</div>
<div><strong>Sale Price:</strong> ${salePriceMin}</div>
<div><strong>Rent Price (Max):</strong> ${data.rentPriceMax || "N/A"}</div>
<div><strong>Sale Price (Max):</strong> ${data.salePriceMax || "N/A"}</div>
</div>
</section>
<!-- Rent Availability -->
<section>
<h2>Rent Availability</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5mm;">
<div><strong>Available From:</strong> ${data.rentAvailableFrom || "N/A"}</div>
<div><strong>Available To:</strong> ${data.rentAvailableTo || "N/A"}</div>
</div>
</section>
<!-- Description -->
<section>
<h2>Property Description</h2>
<h3>${titleEnglish}</h3>
<p style="line-height: 1.6; text-align: justify;">${descriptionEnglish}</p>
</section>
<!-- Amenities -->
<section>
<h2>Amenities & Features</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 5mm;">
<div><strong>Parking Spaces:</strong> ${data.parkingSpaces || "N/A"}</div>
<div><strong>Furnished:</strong> ${data.furnished || "N/A"}</div>
<div><strong>Offering Type:</strong> ${data.offeringType || "N/A"}</div>
<div><strong>Build Year:</strong> ${data.buildYear || "N/A"}</div>
</div>
</section>
<!-- Gallery -->
<section>
<h2>Property Gallery</h2>
<div class="gallery-grid">
${
firstChunk.length > 0
? this.generatePropertyGalleryHTMLForImages(firstChunk)
: this.generatePropertyGalleryHTML()
}
</div>
</section>
</div>
${additionalGalleryPagesHTML}
`;
} }
createModernHomeTemplate() { createModernHomeTemplate() {
const data = this.propertyData || {}; const data = this.propertyData || {};
console.log("data-----------", data); console.log("data-----------", data);
@ -6687,49 +6941,152 @@ ${galleryPagesHTML}
// Property insertion functions // Property insertion functions
insertPropertyName() { insertPropertyName() {
const propertyName = this.propertyData.Name || "Property Name"; const propertyName = this.propertyData.propertyName || this.propertyData.Name || "Property Name";
this.insertTextAtCursor(propertyName); this.insertTextAtCursor(`Name: ${propertyName}`);
} }
insertPropertyPrice() { insertPropertyPrice() {
const price = this.propertyData.Price__c || "$0"; const price = this.propertyData.price || this.propertyData.rentPriceMin || this.propertyData.salePriceMin || "Price on Request";
this.insertTextAtCursor(price); this.insertTextAtCursor(`Price: ${price}`);
} }
insertPropertyType() { insertPropertyType() {
const type = this.propertyData.Property_Type__c || "Property Type"; const type = this.propertyData.propertyType || this.propertyData.Property_Type__c || "Property Type";
this.insertTextAtCursor(type); this.insertTextAtCursor(`Type: ${type}`);
} }
insertPropertyBathrooms() { insertPropertyBathrooms() {
const bathrooms = this.propertyData.Bathrooms__c || "0"; const bathrooms = this.propertyData.bathrooms || this.propertyData.Bathrooms__c || "0";
this.insertTextAtCursor(bathrooms + " Bathrooms"); this.insertTextAtCursor(`Bathrooms: ${bathrooms}`);
} }
insertPropertySqft() { insertPropertySqft() {
const sqft = this.propertyData.Square_Footage__c || "0"; const sqft = this.propertyData.area || this.propertyData.size || this.propertyData.Square_Footage__c || "0";
this.insertTextAtCursor(sqft + " sq ft"); this.insertTextAtCursor(`Square Footage: ${sqft}`);
} }
insertPropertyAddress() { insertPropertyAddress() {
const address = this.propertyData.Location__c || "Property Address"; const address = this.propertyData.location || this.propertyData.Location__c || "Property Address";
this.insertTextAtCursor(address); this.insertTextAtCursor(`Address: ${address}`);
} }
insertPropertyDescription() { insertPropertyDescription() {
const description = const description = this.propertyData.descriptionEnglish || this.propertyData.Description_English__c || this.propertyData.Description__c || "Property Description";
this.propertyData.Description_English__c ||
this.propertyData.pcrm__Description_English__c ||
this.propertyData.Description__c ||
"Property Description";
// Wrap into paragraphs and basic formatting // Wrap into paragraphs and basic formatting
const lines = String(description) const lines = String(description)
.split(/\n+/) .split(/\n+/)
.map((l) => l.trim()) .map((l) => l.trim())
.filter(Boolean); .filter(Boolean);
const html = lines.map((l) => `<p>${l}</p>`).join(""); const html = lines.map((l) => `<p><strong>Description:</strong> ${l}</p>`).join("");
this.insertHtmlAtCursor(html); this.insertHtmlAtCursor(html);
} }
// Additional property insertion methods
insertPropertyBedrooms() {
const bedrooms = this.propertyData.bedrooms || this.propertyData.Bedrooms__c || "0";
this.insertTextAtCursor(`Bedrooms: ${bedrooms}`);
}
insertPropertyStatus() {
const status = this.propertyData.status || this.propertyData.Status__c || "Available";
this.insertTextAtCursor(`Status: ${status}`);
}
insertPropertyCity() {
const city = this.propertyData.city || this.propertyData.City__c || "City";
this.insertTextAtCursor(`City: ${city}`);
}
insertPropertyCommunity() {
const community = this.propertyData.community || this.propertyData.Community__c || "Community";
this.insertTextAtCursor(`Community: ${community}`);
}
insertPropertyFloor() {
const floor = this.propertyData.floor || this.propertyData.Floor__c || "N/A";
this.insertTextAtCursor(`Floor: ${floor}`);
}
insertPropertyBuildYear() {
const buildYear = this.propertyData.buildYear || this.propertyData.yearBuilt || this.propertyData.Build_Year__c || "N/A";
this.insertTextAtCursor(`Build Year: ${buildYear}`);
}
insertPropertyParking() {
const parking = this.propertyData.parking || this.propertyData.parkingSpaces || this.propertyData.Parking_Spaces__c || "N/A";
this.insertTextAtCursor(`Parking: ${parking}`);
}
insertPropertyFurnished() {
const furnished = this.propertyData.furnished || this.propertyData.furnishing || this.propertyData.Furnished__c || "N/A";
this.insertTextAtCursor(`Furnished: ${furnished}`);
}
insertPropertyOfferingType() {
const offeringType = this.propertyData.offeringType || this.propertyData.Offering_Type__c || "N/A";
this.insertTextAtCursor(`Offering Type: ${offeringType}`);
}
insertPropertyRentPrice() {
const rentPrice = this.propertyData.rentPriceMin || this.propertyData.Rent_Price_min__c || "N/A";
this.insertTextAtCursor(`Rent Price: ${rentPrice}`);
}
insertPropertySalePrice() {
const salePrice = this.propertyData.salePriceMin || this.propertyData.Sale_Price_min__c || "N/A";
this.insertTextAtCursor(`Sale Price: ${salePrice}`);
}
insertPropertyContactName() {
const contactName = this.propertyData.contactName || this.propertyData.Contact_Name__c || "Contact Name";
this.insertTextAtCursor(`Contact: ${contactName}`);
}
insertPropertyContactEmail() {
const contactEmail = this.propertyData.contactEmail || this.propertyData.Contact_Email__c || "contact@example.com";
this.insertTextAtCursor(`Email: ${contactEmail}`);
}
insertPropertyContactPhone() {
const contactPhone = this.propertyData.contactPhone || this.propertyData.Contact_Phone__c || "N/A";
this.insertTextAtCursor(`Phone: ${contactPhone}`);
}
insertPropertyReferenceNumber() {
const referenceNumber = this.propertyData.referenceNumber || this.propertyData.Reference_Number__c || "REF-001";
this.insertTextAtCursor(`Reference: ${referenceNumber}`);
}
insertPropertyTitle() {
const title = this.propertyData.titleEnglish || this.propertyData.Title_English__c || "Property Title";
this.insertTextAtCursor(`Title: ${title}`);
}
insertPropertyLocality() {
const locality = this.propertyData.locality || this.propertyData.Locality__c || "Locality";
this.insertTextAtCursor(`Locality: ${locality}`);
}
insertPropertyTower() {
const tower = this.propertyData.tower || this.propertyData.Tower__c || "N/A";
this.insertTextAtCursor(`Tower: ${tower}`);
}
insertPropertyUnitNumber() {
const unitNumber = this.propertyData.unitNumber || this.propertyData.Unit_Number__c || "N/A";
this.insertTextAtCursor(`Unit Number: ${unitNumber}`);
}
insertPropertyRentAvailableFrom() {
const rentAvailableFrom = this.propertyData.rentAvailableFrom || this.propertyData.Rent_Available_From__c || "N/A";
this.insertTextAtCursor(`Available From: ${rentAvailableFrom}`);
}
insertPropertyRentAvailableTo() {
const rentAvailableTo = this.propertyData.rentAvailableTo || this.propertyData.Rent_Available_To__c || "N/A";
this.insertTextAtCursor(`Available To: ${rentAvailableTo}`);
}
// Helper function to insert text at cursor position // Helper function to insert text at cursor position
insertTextAtCursor(text) { insertTextAtCursor(text) {
const selection = window.getSelection(); const selection = window.getSelection();
@ -7368,9 +7725,11 @@ ${galleryPagesHTML}
imageContainer.style.zIndex = "1000"; imageContainer.style.zIndex = "1000";
imageContainer.style.position = "absolute"; imageContainer.style.position = "absolute";
imageContainer.style.overflow = "hidden"; imageContainer.style.overflow = "hidden";
imageContainer.style.border = "2px solid transparent"; imageContainer.style.border = "none";
imageContainer.style.cursor = "move"; imageContainer.style.cursor = "move";
imageContainer.style.userSelect = "none"; imageContainer.style.userSelect = "none";
imageContainer.style.boxSizing = "border-box";
imageContainer.style.borderRadius = "4px";
// Create image element // Create image element
const img = document.createElement("img"); const img = document.createElement("img");
@ -7380,6 +7739,9 @@ ${galleryPagesHTML}
img.style.height = "100%"; img.style.height = "100%";
img.style.objectFit = "cover"; img.style.objectFit = "cover";
img.style.display = "block"; img.style.display = "block";
img.style.border = "none";
img.style.outline = "none";
img.style.borderRadius = "4px";
imageContainer.appendChild(img); imageContainer.appendChild(img);
@ -7427,7 +7789,7 @@ ${galleryPagesHTML}
this.saveUndoState(); this.saveUndoState();
this.setupEditorClickHandler(); this.setupEditorClickHandler();
const imageContainer = document.createElement("div"); const imageContainer = document.createElement("div");
imageContainer.className = "draggable-element"; imageContainer.className = "draggable-image-container";
imageContainer.style.left = "50px"; imageContainer.style.left = "50px";
imageContainer.style.top = "50px"; imageContainer.style.top = "50px";
imageContainer.style.width = "200px"; imageContainer.style.width = "200px";
@ -7435,6 +7797,9 @@ ${galleryPagesHTML}
imageContainer.style.zIndex = "1000"; imageContainer.style.zIndex = "1000";
imageContainer.style.position = "absolute"; imageContainer.style.position = "absolute";
imageContainer.style.overflow = "hidden"; imageContainer.style.overflow = "hidden";
imageContainer.style.border = "none";
imageContainer.style.boxSizing = "border-box";
imageContainer.style.borderRadius = "4px";
const img = document.createElement("img"); const img = document.createElement("img");
img.src = event.target.result; img.src = event.target.result;
@ -7443,6 +7808,9 @@ ${galleryPagesHTML}
img.style.width = "100%"; img.style.width = "100%";
img.style.height = "100%"; img.style.height = "100%";
img.style.objectFit = "cover"; img.style.objectFit = "cover";
img.style.border = "none";
img.style.outline = "none";
img.style.borderRadius = "4px";
imageContainer.appendChild(img); imageContainer.appendChild(img);
@ -8012,7 +8380,7 @@ ${galleryPagesHTML}
imageContainer.style.height = "200px"; imageContainer.style.height = "200px";
imageContainer.style.cursor = "move"; imageContainer.style.cursor = "move";
imageContainer.style.zIndex = "1000"; imageContainer.style.zIndex = "1000";
imageContainer.style.border = "2px dashed #667eea"; imageContainer.style.border = "2px solid transparent";
imageContainer.style.borderRadius = "4px"; imageContainer.style.borderRadius = "4px";
imageContainer.style.overflow = "hidden"; imageContainer.style.overflow = "hidden";
@ -10316,7 +10684,7 @@ ${galleryPagesHTML}
textElement.style.minWidth = "150px"; textElement.style.minWidth = "150px";
textElement.style.minHeight = "30px"; textElement.style.minHeight = "30px";
textElement.style.padding = "8px"; textElement.style.padding = "8px";
textElement.style.border = "2px dashed #4f46e5"; textElement.style.border = "2px solid transparent";
textElement.style.borderRadius = "4px"; textElement.style.borderRadius = "4px";
textElement.style.backgroundColor = "rgba(255, 255, 255, 0.9)"; textElement.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
textElement.style.zIndex = "1000"; textElement.style.zIndex = "1000";