image replace stable
This commit is contained in:
parent
c978c48fb6
commit
0c721ef7ed
18473
backup_propertyTemplateSelector.js
Normal file
18473
backup_propertyTemplateSelector.js
Normal file
File diff suppressed because one or more lines are too long
@ -488,7 +488,7 @@ export default class PropertyTemplateSelector extends LightningElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get isModernHomeTemplateSelected() {
|
get isModernHomeTemplateSelected() {
|
||||||
return this.selectedTemplateId === "modern-home-template";
|
return this.selectedTemplateId === "modern-home-template" || this.selectedTemplateId === "modern-home-a3-template";
|
||||||
}
|
}
|
||||||
|
|
||||||
get isGrandOakVillaTemplateSelected() {
|
get isGrandOakVillaTemplateSelected() {
|
||||||
@ -1317,6 +1317,11 @@ export default class PropertyTemplateSelector extends LightningElement {
|
|||||||
// Force proper HTML rendering after content changes
|
// Force proper HTML rendering after content changes
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.forceHTMLRendering();
|
this.forceHTMLRendering();
|
||||||
|
|
||||||
|
// Add pencil icon to hero section for modern home template
|
||||||
|
if (this.selectedTemplateId === 'modern-home-template' || this.selectedTemplateId === 'modern-home-a3-template') {
|
||||||
|
this.addPencilIconToHeroSection();
|
||||||
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1685,6 +1690,11 @@ export default class PropertyTemplateSelector extends LightningElement {
|
|||||||
this.forceImageReload();
|
this.forceImageReload();
|
||||||
// Force proper HTML rendering to match PDF exactly
|
// Force proper HTML rendering to match PDF exactly
|
||||||
this.forceHTMLRendering();
|
this.forceHTMLRendering();
|
||||||
|
|
||||||
|
// Add pencil icon to hero section for modern home template
|
||||||
|
if (this.selectedTemplateId === 'modern-home-template' || this.selectedTemplateId === 'modern-home-a3-template') {
|
||||||
|
this.addPencilIconToHeroSection();
|
||||||
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1751,6 +1761,11 @@ export default class PropertyTemplateSelector extends LightningElement {
|
|||||||
this.forceImageReload();
|
this.forceImageReload();
|
||||||
// Force proper HTML rendering to match PDF exactly
|
// Force proper HTML rendering to match PDF exactly
|
||||||
this.forceHTMLRendering();
|
this.forceHTMLRendering();
|
||||||
|
|
||||||
|
// Add pencil icon to hero section for modern home template
|
||||||
|
if (this.selectedTemplateId === 'modern-home-template' || this.selectedTemplateId === 'modern-home-a3-template') {
|
||||||
|
this.addPencilIconToHeroSection();
|
||||||
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.error = "Error loading template: " + error.message;
|
this.error = "Error loading template: " + error.message;
|
||||||
@ -5042,6 +5057,44 @@ export default class PropertyTemplateSelector extends LightningElement {
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pencil icon styles - only visible in editor */
|
||||||
|
.hero-edit-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
z-index: 1000;
|
||||||
|
background: rgba(0,0,0,0.7);
|
||||||
|
color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-edit-icon:hover {
|
||||||
|
background: rgba(0,0,0,0.9);
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show pencil icon only in editor mode */
|
||||||
|
.enhanced-editor-content .hero-edit-icon {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide pencil icon in PDF generation */
|
||||||
|
@media print {
|
||||||
|
.hero-edit-icon {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
.hero-overlay {
|
.hero-overlay {
|
||||||
background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.1) 100%);
|
background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.1) 100%);
|
||||||
padding: 40px;
|
padding: 40px;
|
||||||
@ -8137,34 +8190,7 @@ ${galleryPagesHTML}
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="floorplan-showcase">
|
|
||||||
<div class="floorplan-image-p5 penthouse"></div>
|
|
||||||
<div class="floorplan-info-p5">
|
|
||||||
<h4>${propertyName}</h4>
|
|
||||||
<div class="floorplan-stats-p5">
|
|
||||||
<div class="stat">
|
|
||||||
<div class="value">${this.propertyData.size
|
|
||||||
}</div>
|
|
||||||
<div class="label">SQ. FT.</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat">
|
|
||||||
<div class="value">${this.propertyData.bedrooms
|
|
||||||
}</div>
|
|
||||||
<div class="label">BEDROOMS</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat">
|
|
||||||
<div class="value">${this.propertyData.bathrooms
|
|
||||||
}</div>
|
|
||||||
<div class="label">BATHROOMS</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat">
|
|
||||||
<div class="value">${this.propertyData.floor
|
|
||||||
}</div>
|
|
||||||
<div class="label">Floors</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<h3 class="section-title">Additional Information</h3>
|
<h3 class="section-title">Additional Information</h3>
|
||||||
<div class="additional-specs-grid">
|
<div class="additional-specs-grid">
|
||||||
@ -12894,266 +12920,130 @@ ${galleryPagesHTML}
|
|||||||
editorContent.dispatchEvent(new Event("input", { bubbles: true }));
|
editorContent.dispatchEvent(new Event("input", { bubbles: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// NEW: Coordinate-based image detection with visual feedback
|
|
||||||
detectImageAtCoordinates(clickX, clickY, editor) {
|
|
||||||
console.log("=== NEW COORDINATE-BASED IMAGE DETECTION ===");
|
|
||||||
console.log("Click coordinates:", { x: clickX, y: clickY });
|
|
||||||
|
|
||||||
let clickedImage = null;
|
|
||||||
let bestMatch = null;
|
|
||||||
let bestScore = -1;
|
|
||||||
|
|
||||||
// Clear any existing visual feedback
|
|
||||||
this.clearImageSelectionFeedback();
|
|
||||||
|
|
||||||
// Method 1: Find all images and background images in the editor
|
|
||||||
const allImages = [];
|
|
||||||
|
|
||||||
// Get all IMG elements
|
|
||||||
const imgElements = editor.querySelectorAll("img");
|
|
||||||
imgElements.forEach(img => {
|
|
||||||
if (img.src && img.src.trim() !== "") {
|
|
||||||
allImages.push({
|
|
||||||
element: img,
|
|
||||||
type: 'img',
|
|
||||||
rect: img.getBoundingClientRect(),
|
|
||||||
src: img.src
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get all elements with background images
|
|
||||||
const allElements = editor.querySelectorAll("*");
|
|
||||||
allElements.forEach(el => {
|
|
||||||
const computedStyle = window.getComputedStyle(el);
|
|
||||||
const backgroundImage = computedStyle.backgroundImage;
|
|
||||||
|
|
||||||
if (backgroundImage && backgroundImage !== "none" && backgroundImage !== "initial") {
|
|
||||||
const rect = el.getBoundingClientRect();
|
|
||||||
if (rect.width > 0 && rect.height > 0) { // Only consider visible elements
|
|
||||||
const virtualImg = document.createElement("img");
|
|
||||||
virtualImg.src = backgroundImage.replace(/url\(['"]?(.+?)['"]?\)/, "$1");
|
|
||||||
virtualImg.isBackgroundImage = true;
|
|
||||||
virtualImg.originalElement = el;
|
|
||||||
|
|
||||||
allImages.push({
|
|
||||||
element: virtualImg,
|
|
||||||
type: 'background',
|
|
||||||
rect: rect,
|
|
||||||
src: virtualImg.src,
|
|
||||||
originalElement: el
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`Found ${allImages.length} images to check`);
|
|
||||||
|
|
||||||
// Method 2: Score each image based on click proximity and element importance
|
|
||||||
allImages.forEach((imageData, index) => {
|
|
||||||
const rect = imageData.rect;
|
|
||||||
const centerX = rect.left + rect.width / 2;
|
|
||||||
const centerY = rect.top + rect.height / 2;
|
|
||||||
|
|
||||||
// Calculate distance from click point to image center
|
|
||||||
const distance = Math.sqrt(
|
|
||||||
Math.pow(clickX - centerX, 2) + Math.pow(clickY - centerY, 2)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Calculate if click is within image bounds
|
|
||||||
const isWithinBounds = (
|
|
||||||
clickX >= rect.left &&
|
|
||||||
clickX <= rect.right &&
|
|
||||||
clickY >= rect.top &&
|
|
||||||
clickY <= rect.bottom
|
|
||||||
);
|
|
||||||
|
|
||||||
// Calculate image area (larger images get higher priority)
|
|
||||||
const area = rect.width * rect.height;
|
|
||||||
|
|
||||||
// Calculate importance score based on element classes and position
|
|
||||||
let importanceScore = 0;
|
|
||||||
const originalElement = imageData.originalElement || imageData.element;
|
|
||||||
|
|
||||||
if (originalElement) {
|
|
||||||
const className = originalElement.className || '';
|
|
||||||
|
|
||||||
// Hero section images get highest priority
|
|
||||||
if (className.includes('hero') || className.includes('p1-image-side') ||
|
|
||||||
className.includes('p2-image') || className.includes('cover-page') ||
|
|
||||||
className.includes('banner')) {
|
|
||||||
importanceScore += 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Content images get medium priority
|
|
||||||
if (className.includes('content') || className.includes('main') ||
|
|
||||||
className.includes('section') || className.includes('card') ||
|
|
||||||
className.includes('property') || className.includes('image')) {
|
|
||||||
importanceScore += 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Footer images get negative priority (should be avoided)
|
|
||||||
if (className.includes('footer') || className.includes('page-footer') ||
|
|
||||||
className.includes('p1-footer') || className.includes('agent-footer') ||
|
|
||||||
className.includes('company-logo') || className.includes('footer-logo')) {
|
|
||||||
importanceScore -= 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate final score
|
|
||||||
let score = 0;
|
|
||||||
|
|
||||||
if (isWithinBounds) {
|
|
||||||
// Click is within image bounds - high priority
|
|
||||||
score = 1000 + importanceScore + (area / 1000); // Larger images get slight bonus
|
|
||||||
} else {
|
|
||||||
// Click is outside image bounds - lower priority based on distance
|
|
||||||
score = Math.max(0, 1000 - distance + importanceScore + (area / 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Image ${index}:`, {
|
|
||||||
type: imageData.type,
|
|
||||||
src: imageData.src.substring(0, 50) + '...',
|
|
||||||
className: originalElement?.className || 'N/A',
|
|
||||||
isWithinBounds,
|
|
||||||
distance: Math.round(distance),
|
|
||||||
area: Math.round(area),
|
|
||||||
importanceScore,
|
|
||||||
score: Math.round(score)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (score > bestScore) {
|
|
||||||
bestScore = score;
|
|
||||||
bestMatch = imageData;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Method 3: If we have a good match, use it
|
|
||||||
if (bestMatch && bestScore > 0) {
|
|
||||||
clickedImage = bestMatch.element;
|
|
||||||
console.log("✅ BEST MATCH FOUND:", {
|
|
||||||
type: bestMatch.type,
|
|
||||||
src: bestMatch.src.substring(0, 50) + '...',
|
|
||||||
score: Math.round(bestScore),
|
|
||||||
isWithinBounds: (
|
|
||||||
clickX >= bestMatch.rect.left &&
|
|
||||||
clickX <= bestMatch.rect.right &&
|
|
||||||
clickY >= bestMatch.rect.top &&
|
|
||||||
clickY <= bestMatch.rect.bottom
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add visual feedback to show which image is selected
|
|
||||||
this.showImageSelectionFeedback(bestMatch.originalElement || bestMatch.element);
|
|
||||||
} else {
|
|
||||||
console.log("❌ NO SUITABLE IMAGE FOUND");
|
|
||||||
}
|
|
||||||
|
|
||||||
return clickedImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add visual feedback to show which image is selected
|
|
||||||
showImageSelectionFeedback(element) {
|
|
||||||
if (!element) return;
|
|
||||||
|
|
||||||
// Remove any existing feedback
|
|
||||||
this.clearImageSelectionFeedback();
|
|
||||||
|
|
||||||
// Add highlight to the selected element
|
|
||||||
element.style.outline = "3px solid #007bff";
|
|
||||||
element.style.outlineOffset = "2px";
|
|
||||||
element.style.boxShadow = "0 0 10px rgba(0, 123, 255, 0.5)";
|
|
||||||
|
|
||||||
// Store reference for cleanup
|
|
||||||
this.selectedElementForFeedback = element;
|
|
||||||
|
|
||||||
console.log("Visual feedback added to selected image");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear visual feedback
|
|
||||||
clearImageSelectionFeedback() {
|
|
||||||
if (this.selectedElementForFeedback) {
|
|
||||||
this.selectedElementForFeedback.style.outline = "";
|
|
||||||
this.selectedElementForFeedback.style.outlineOffset = "";
|
|
||||||
this.selectedElementForFeedback.style.boxShadow = "";
|
|
||||||
this.selectedElementForFeedback = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup editor click handler to deselect elements
|
// Setup editor click handler to deselect elements
|
||||||
setupEditorClickHandler() {
|
setupEditorClickHandler() {
|
||||||
const editor = this.template.querySelector(".enhanced-editor-content");
|
const editor = this.template.querySelector(".enhanced-editor-content");
|
||||||
if (editor && !editor.hasClickHandler) {
|
if (editor && !editor.hasClickHandler) {
|
||||||
editor.addEventListener("click", (e) => {
|
editor.addEventListener("click", (e) => {
|
||||||
console.log("=== NEW COORDINATE-BASED CLICK HANDLER ===");
|
console.log("=== CLICK EVENT DETECTED ===");
|
||||||
|
console.log("Click target:", e.target);
|
||||||
console.log("Click coordinates:", { x: e.clientX, y: e.clientY });
|
console.log("Click coordinates:", { x: e.clientX, y: e.clientY });
|
||||||
console.log("Target element:", e.target);
|
console.log("Target details:", {
|
||||||
|
tagName: e.target.tagName,
|
||||||
|
className: e.target.className,
|
||||||
|
id: e.target.id,
|
||||||
|
src: e.target.src
|
||||||
|
});
|
||||||
|
|
||||||
// Prevent default behavior
|
// Enhanced image detection - check multiple ways to find images
|
||||||
e.preventDefault();
|
let clickedImage = null;
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
try {
|
// Method 1: Direct image click
|
||||||
// Use the new coordinate-based image detection
|
console.log("=== METHOD 1: Direct image click ===");
|
||||||
const clickedImage = this.detectImageAtCoordinates(e.clientX, e.clientY, editor);
|
if (
|
||||||
|
e.target.tagName === "IMG" &&
|
||||||
|
e.target.src &&
|
||||||
|
e.target.src.trim() !== ""
|
||||||
|
) {
|
||||||
|
clickedImage = e.target;
|
||||||
|
console.log("✅ Method 1 SUCCESS: Direct IMG click detected", clickedImage);
|
||||||
|
} else {
|
||||||
|
console.log("❌ Method 1 FAILED: Not a direct IMG click");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method 2: Click on element containing an image (children)
|
||||||
|
console.log("=== METHOD 2: Element containing image ===");
|
||||||
|
if (!clickedImage && e.target.querySelector) {
|
||||||
|
const containedImg = e.target.querySelector("img");
|
||||||
|
if (
|
||||||
|
containedImg &&
|
||||||
|
containedImg.src &&
|
||||||
|
containedImg.src.trim() !== ""
|
||||||
|
) {
|
||||||
|
clickedImage = containedImg;
|
||||||
|
console.log("✅ Method 2 SUCCESS: Container with IMG detected", clickedImage);
|
||||||
|
} else {
|
||||||
|
console.log("❌ Method 2 FAILED: No IMG in container");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("❌ Method 2 SKIPPED: No querySelector or already found image");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method 3: Click on element that is inside a container with an image (parent traversal)
|
||||||
|
console.log("=== METHOD 3: Parent traversal ===");
|
||||||
if (!clickedImage) {
|
if (!clickedImage) {
|
||||||
console.log("❌ NO IMAGE FOUND AT CLICK LOCATION");
|
let currentElement = e.target;
|
||||||
this.showError("No image found at the clicked location. Please click directly on an image.");
|
let traversalCount = 0;
|
||||||
return;
|
while (currentElement && currentElement !== editor && traversalCount < 10) {
|
||||||
}
|
traversalCount++;
|
||||||
|
console.log(`Traversal step ${traversalCount}:`, {
|
||||||
console.log("✅ IMAGE FOUND:", clickedImage);
|
tagName: currentElement.tagName,
|
||||||
console.log("Image details:", {
|
className: currentElement.className,
|
||||||
tagName: clickedImage.tagName,
|
id: currentElement.id
|
||||||
src: clickedImage.src,
|
|
||||||
className: clickedImage.className,
|
|
||||||
isBackgroundImage: clickedImage.isBackgroundImage,
|
|
||||||
originalElement: clickedImage.originalElement
|
|
||||||
});
|
});
|
||||||
|
// Check if current element is an IMG
|
||||||
// Store the selected image element
|
if (
|
||||||
this.selectedImageElement = clickedImage;
|
currentElement.tagName === "IMG" &&
|
||||||
|
currentElement.src &&
|
||||||
// Check if this is the same image as the last click
|
currentElement.src.trim() !== ""
|
||||||
const isSameImage = this.isSameImageAsLast(clickedImage);
|
) {
|
||||||
|
clickedImage = currentElement;
|
||||||
if (isSameImage) {
|
console.log("✅ Method 3 SUCCESS: Found IMG in parent traversal", clickedImage);
|
||||||
this.imageClickCount++;
|
break;
|
||||||
console.log("Same image clicked, count:", this.imageClickCount);
|
}
|
||||||
|
// Check if current element contains an IMG
|
||||||
|
if (
|
||||||
|
currentElement.querySelector &&
|
||||||
|
currentElement.querySelector("img")
|
||||||
|
) {
|
||||||
|
const img = currentElement.querySelector("img");
|
||||||
|
if (img && img.src && img.src.trim() !== "") {
|
||||||
|
clickedImage = img;
|
||||||
|
console.log("✅ Method 3 SUCCESS: Found IMG in container during traversal", clickedImage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check siblings for IMG elements only if current element is positioned
|
||||||
|
if (
|
||||||
|
currentElement.parentElement &&
|
||||||
|
(currentElement.style.position === "absolute" ||
|
||||||
|
currentElement.style.position === "relative" ||
|
||||||
|
currentElement.classList.contains("draggable-element"))
|
||||||
|
) {
|
||||||
|
const siblingImg =
|
||||||
|
currentElement.parentElement.querySelector("img");
|
||||||
|
if (
|
||||||
|
siblingImg &&
|
||||||
|
siblingImg.src &&
|
||||||
|
siblingImg.src.trim() !== ""
|
||||||
|
) {
|
||||||
|
clickedImage = siblingImg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentElement = currentElement.parentElement;
|
||||||
|
}
|
||||||
|
if (!clickedImage) {
|
||||||
|
console.log("❌ Method 3 FAILED: No IMG found in parent traversal");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.imageClickCount = 1;
|
console.log("❌ Method 3 SKIPPED: Already found image");
|
||||||
this.lastClickedImage = clickedImage;
|
|
||||||
console.log("Different image clicked, reset count to 1");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set timeout to reset counter
|
// Method 4: Check for background images in the element hierarchy (enhanced for property cards)
|
||||||
this.clickTimeout = setTimeout(() => {
|
console.log("=== METHOD 4: Background image detection ===");
|
||||||
this.imageClickCount = 0;
|
if (!clickedImage) {
|
||||||
this.lastClickedImage = null;
|
let currentElement = e.target;
|
||||||
this.clearImageSelectionFeedback();
|
let heroBackgroundImage = null;
|
||||||
console.log("Click counter reset");
|
let otherBackgroundImage = null;
|
||||||
}, 1000);
|
let clickedElementBackgroundImage = null;
|
||||||
|
|
||||||
// Check if image can be replaced
|
// First, check the clicked element and its immediate children for background images
|
||||||
if (this.canReplaceImage(clickedImage)) {
|
console.log("Checking clicked element and immediate children first...");
|
||||||
console.log("Image can be replaced, opening replacement dialog");
|
const elementsToCheck = [currentElement];
|
||||||
this.openImageReplacement(clickedImage);
|
|
||||||
} else {
|
|
||||||
console.log("Image cannot be replaced, showing error");
|
|
||||||
this.showError("This image cannot be replaced. Please try clicking on a different image.");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error in image detection:", error);
|
|
||||||
this.showError("An error occurred while processing the image click.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
editor.hasClickHandler = true;
|
// Add immediate children that might have background images
|
||||||
}
|
if (currentElement.children) {
|
||||||
}
|
|
||||||
|
|
||||||
addDeselectFunctionality() {
|
|
||||||
for (let child of currentElement.children) {
|
for (let child of currentElement.children) {
|
||||||
elementsToCheck.push(child);
|
elementsToCheck.push(child);
|
||||||
}
|
}
|
||||||
@ -15637,6 +15527,12 @@ ${galleryPagesHTML}
|
|||||||
console.log("Clicked image:", clickedImage);
|
console.log("Clicked image:", clickedImage);
|
||||||
console.log("Event:", event);
|
console.log("Event:", event);
|
||||||
|
|
||||||
|
// Disable 3-click functionality for modern home template
|
||||||
|
if (this.isModernHomeTemplateSelected) {
|
||||||
|
console.log("❌ 3-click functionality disabled for modern home template");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Prevent replacement if file dialog is open
|
// Prevent replacement if file dialog is open
|
||||||
if (this.isFileDialogOpen) {
|
if (this.isFileDialogOpen) {
|
||||||
console.log("❌ File dialog open, ignoring image click");
|
console.log("❌ File dialog open, ignoring image click");
|
||||||
@ -17010,6 +16906,180 @@ ${galleryPagesHTML}
|
|||||||
return 'https://via.placeholder.com/400x300?text=No+Image+Available';
|
return 'https://via.placeholder.com/400x300?text=No+Image+Available';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method to add pencil icon to hero section and second page image for image replacement
|
||||||
|
addPencilIconToHeroSection() {
|
||||||
|
console.log('addPencilIconToHeroSection called for template:', this.selectedTemplateId);
|
||||||
|
|
||||||
|
// Wait for the template to be loaded in the editor content
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log('Looking for enhanced-editor-content...');
|
||||||
|
const editorContent = this.template.querySelector('.enhanced-editor-content');
|
||||||
|
if (editorContent) {
|
||||||
|
console.log('Enhanced editor content found');
|
||||||
|
|
||||||
|
// Add CSS styles for the pencil icon if not already added
|
||||||
|
if (!document.querySelector('#hero-edit-icon-styles')) {
|
||||||
|
console.log('Adding CSS styles for pencil icon');
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.id = 'hero-edit-icon-styles';
|
||||||
|
style.textContent = `
|
||||||
|
.hero-edit-icon, .visual-header-edit-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
z-index: 1000;
|
||||||
|
background: rgba(0,0,0,0.7);
|
||||||
|
color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-edit-icon:hover, .visual-header-edit-icon:hover {
|
||||||
|
background: rgba(0,0,0,0.9);
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide pencil icon in PDF generation */
|
||||||
|
@media print {
|
||||||
|
.hero-edit-icon, .visual-header-edit-icon {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add pencil icon to hero section (page 1)
|
||||||
|
console.log('Looking for hero section...');
|
||||||
|
const heroSection = editorContent.querySelector('.hero');
|
||||||
|
if (heroSection) {
|
||||||
|
console.log('Hero section found');
|
||||||
|
if (!heroSection.querySelector('.hero-edit-icon')) {
|
||||||
|
console.log('Creating pencil icon for hero section...');
|
||||||
|
// Create pencil icon element
|
||||||
|
const pencilIcon = document.createElement('div');
|
||||||
|
pencilIcon.className = 'hero-edit-icon';
|
||||||
|
pencilIcon.innerHTML = '<i class="fa-solid fa-pencil" style="font-size: 16px;"></i>';
|
||||||
|
pencilIcon.title = 'Replace Hero Image';
|
||||||
|
pencilIcon.onclick = () => {
|
||||||
|
console.log('Hero pencil icon clicked');
|
||||||
|
// Trigger image replacement for hero section
|
||||||
|
this.handleHeroImageReplacement();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add the pencil icon to the hero section
|
||||||
|
heroSection.appendChild(pencilIcon);
|
||||||
|
console.log('Pencil icon added to hero section successfully');
|
||||||
|
} else {
|
||||||
|
console.log('Hero section pencil icon already exists');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Hero section not found in editor content');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add pencil icon to visual header (page 2)
|
||||||
|
console.log('Looking for visual header...');
|
||||||
|
const visualHeader = editorContent.querySelector('.visual-header');
|
||||||
|
if (visualHeader) {
|
||||||
|
console.log('Visual header found');
|
||||||
|
if (!visualHeader.querySelector('.visual-header-edit-icon')) {
|
||||||
|
console.log('Creating pencil icon for visual header...');
|
||||||
|
// Create pencil icon element
|
||||||
|
const pencilIcon = document.createElement('div');
|
||||||
|
pencilIcon.className = 'visual-header-edit-icon';
|
||||||
|
pencilIcon.innerHTML = '<i class="fa-solid fa-pencil" style="font-size: 16px;"></i>';
|
||||||
|
pencilIcon.title = 'Replace Page 2 Image';
|
||||||
|
pencilIcon.onclick = () => {
|
||||||
|
console.log('Visual header pencil icon clicked');
|
||||||
|
// Trigger image replacement for visual header
|
||||||
|
this.handleVisualHeaderImageReplacement();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add the pencil icon to the visual header
|
||||||
|
visualHeader.appendChild(pencilIcon);
|
||||||
|
console.log('Pencil icon added to visual header successfully');
|
||||||
|
} else {
|
||||||
|
console.log('Visual header pencil icon already exists');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Visual header not found in editor content');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Enhanced editor content not found');
|
||||||
|
}
|
||||||
|
}, 1500); // Increased timeout to ensure content is loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle hero image replacement
|
||||||
|
handleHeroImageReplacement() {
|
||||||
|
// Find the hero section background image
|
||||||
|
const editorContent = this.template.querySelector('.enhanced-editor-content');
|
||||||
|
if (editorContent) {
|
||||||
|
const heroSection = editorContent.querySelector('.hero');
|
||||||
|
if (heroSection) {
|
||||||
|
// Get the computed background image
|
||||||
|
const computedStyle = window.getComputedStyle(heroSection);
|
||||||
|
const backgroundImage = computedStyle.backgroundImage;
|
||||||
|
|
||||||
|
if (backgroundImage && backgroundImage !== 'none') {
|
||||||
|
// Create a virtual image element for the hero background
|
||||||
|
const virtualImg = document.createElement('img');
|
||||||
|
virtualImg.src = backgroundImage.replace(/url\(['"]?(.+?)['"]?\)/, '$1');
|
||||||
|
virtualImg.isBackgroundImage = true;
|
||||||
|
virtualImg.originalElement = heroSection;
|
||||||
|
|
||||||
|
// Open image replacement for this virtual image
|
||||||
|
this.openImageReplacement(virtualImg);
|
||||||
|
} else {
|
||||||
|
console.log('No background image found on hero section');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Hero section not found');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Enhanced editor content not found');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle visual header image replacement (page 2)
|
||||||
|
handleVisualHeaderImageReplacement() {
|
||||||
|
// Find the visual header background image
|
||||||
|
const editorContent = this.template.querySelector('.enhanced-editor-content');
|
||||||
|
if (editorContent) {
|
||||||
|
const visualHeader = editorContent.querySelector('.visual-header');
|
||||||
|
if (visualHeader) {
|
||||||
|
// Get the computed background image
|
||||||
|
const computedStyle = window.getComputedStyle(visualHeader);
|
||||||
|
const backgroundImage = computedStyle.backgroundImage;
|
||||||
|
|
||||||
|
if (backgroundImage && backgroundImage !== 'none') {
|
||||||
|
// Create a virtual image element for the visual header background
|
||||||
|
const virtualImg = document.createElement('img');
|
||||||
|
virtualImg.src = backgroundImage.replace(/url\(['"]?(.+?)['"]?\)/, '$1');
|
||||||
|
virtualImg.isBackgroundImage = true;
|
||||||
|
virtualImg.originalElement = visualHeader;
|
||||||
|
|
||||||
|
// Open image replacement for this virtual image
|
||||||
|
this.openImageReplacement(virtualImg);
|
||||||
|
} else {
|
||||||
|
console.log('No background image found on visual header');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Visual header not found');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Enhanced editor content not found');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Method to replace background-image URLs in CSS at runtime
|
// Method to replace background-image URLs in CSS at runtime
|
||||||
replaceBackgroundImagesInHTML(htmlContent) {
|
replaceBackgroundImagesInHTML(htmlContent) {
|
||||||
if (!this.realPropertyImages || this.realPropertyImages.length === 0) {
|
if (!this.realPropertyImages || this.realPropertyImages.length === 0) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user