bullets font preserved
This commit is contained in:
parent
8b183d96be
commit
c978c48fb6
@ -1211,12 +1211,12 @@
|
|||||||
Image
|
Image
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar-group">
|
<!-- <div class="toolbar-group">
|
||||||
<button class="toolbar-button" onclick={addNewPageWithDataType} disabled>
|
<button class="toolbar-button" onclick={addNewPageWithDataType} disabled>
|
||||||
<lightning-icon icon-name="utility:page" size="x-small"></lightning-icon>
|
<lightning-icon icon-name="utility:page" size="x-small"></lightning-icon>
|
||||||
Add Page
|
Add Page
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div> -->
|
||||||
<div class="toolbar-group">
|
<div class="toolbar-group">
|
||||||
<button class="toolbar-button" onclick={toggleSelectorMode}>
|
<button class="toolbar-button" onclick={toggleSelectorMode}>
|
||||||
<lightning-icon icon-name="utility:target" size="x-small"></lightning-icon>
|
<lightning-icon icon-name="utility:target" size="x-small"></lightning-icon>
|
||||||
|
|||||||
@ -5493,7 +5493,6 @@ export default class PropertyTemplateSelector extends LightningElement {
|
|||||||
<div class="specifications-section">
|
<div class="specifications-section">
|
||||||
<h2 class="section-title">Specifications</h2>
|
<h2 class="section-title">Specifications</h2>
|
||||||
<div class="spec-list">
|
<div class="spec-list">
|
||||||
<div class="spec-item"><strong>Status:</strong> <span>${status}</span></div>
|
|
||||||
<div class="spec-item"><strong>Type:</strong> <span>${propertyType}</span></div>
|
<div class="spec-item"><strong>Type:</strong> <span>${propertyType}</span></div>
|
||||||
<div class="spec-item"><strong>Floor:</strong> <span>${floor}</span></div>
|
<div class="spec-item"><strong>Floor:</strong> <span>${floor}</span></div>
|
||||||
<div class="spec-item"><strong>Parking:</strong> <span>${parking}</span></div>
|
<div class="spec-item"><strong>Parking:</strong> <span>${parking}</span></div>
|
||||||
@ -5512,6 +5511,7 @@ export default class PropertyTemplateSelector extends LightningElement {
|
|||||||
|
|
||||||
<footer class="page-footer">
|
<footer class="page-footer">
|
||||||
<div class="reference-id">
|
<div class="reference-id">
|
||||||
|
|
||||||
<strong>Agent:</strong> ${agentName} | ${agentEmail} | ${agentPhone}
|
<strong>Agent:</strong> ${agentName} | ${agentEmail} | ${agentPhone}
|
||||||
</div>
|
</div>
|
||||||
<div class="company-logo">
|
<div class="company-logo">
|
||||||
@ -11128,6 +11128,26 @@ ${galleryPagesHTML}
|
|||||||
createNewList(listType, selectedText, range) {
|
createNewList(listType, selectedText, range) {
|
||||||
const list = document.createElement(listType);
|
const list = document.createElement(listType);
|
||||||
|
|
||||||
|
// Get the font size from the current selection context
|
||||||
|
let contextFontSize = null;
|
||||||
|
let contextFontFamily = null;
|
||||||
|
let contextFontWeight = null;
|
||||||
|
let contextColor = null;
|
||||||
|
|
||||||
|
if (range && range.startContainer) {
|
||||||
|
const startElement = range.startContainer.nodeType === Node.TEXT_NODE
|
||||||
|
? range.startContainer.parentElement
|
||||||
|
: range.startContainer;
|
||||||
|
|
||||||
|
if (startElement) {
|
||||||
|
const computedStyle = window.getComputedStyle(startElement);
|
||||||
|
contextFontSize = computedStyle.fontSize;
|
||||||
|
contextFontFamily = computedStyle.fontFamily;
|
||||||
|
contextFontWeight = computedStyle.fontWeight;
|
||||||
|
contextColor = computedStyle.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedText) {
|
if (selectedText) {
|
||||||
// Try to detect if we have multiple lines by checking the range
|
// Try to detect if we have multiple lines by checking the range
|
||||||
let lines = [];
|
let lines = [];
|
||||||
@ -11180,16 +11200,18 @@ ${galleryPagesHTML}
|
|||||||
// Multiple lines selected - create list items for each line
|
// Multiple lines selected - create list items for each line
|
||||||
lines.forEach((line) => {
|
lines.forEach((line) => {
|
||||||
const li = document.createElement("li");
|
const li = document.createElement("li");
|
||||||
// Preserve HTML formatting and font size
|
// Preserve HTML formatting and apply context styling
|
||||||
li.innerHTML = line.trim();
|
li.innerHTML = line.trim();
|
||||||
|
this.applyContextStyling(li, contextFontSize, contextFontFamily, contextFontWeight, contextColor);
|
||||||
li.contentEditable = true;
|
li.contentEditable = true;
|
||||||
list.appendChild(li);
|
list.appendChild(li);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Single line selected
|
// Single line selected
|
||||||
const li = document.createElement("li");
|
const li = document.createElement("li");
|
||||||
// Preserve HTML formatting and font size
|
// Preserve HTML formatting and apply context styling
|
||||||
li.innerHTML = selectedText || "List item";
|
li.innerHTML = selectedText || "List item";
|
||||||
|
this.applyContextStyling(li, contextFontSize, contextFontFamily, contextFontWeight, contextColor);
|
||||||
li.contentEditable = true;
|
li.contentEditable = true;
|
||||||
list.appendChild(li);
|
list.appendChild(li);
|
||||||
}
|
}
|
||||||
@ -11200,8 +11222,9 @@ ${galleryPagesHTML}
|
|||||||
// Multiple lines detected in current paragraph
|
// Multiple lines detected in current paragraph
|
||||||
selectedLines.forEach((line) => {
|
selectedLines.forEach((line) => {
|
||||||
const li = document.createElement("li");
|
const li = document.createElement("li");
|
||||||
// Preserve HTML formatting and font size
|
// Preserve HTML formatting and apply context styling
|
||||||
li.innerHTML = line.trim();
|
li.innerHTML = line.trim();
|
||||||
|
this.applyContextStyling(li, contextFontSize, contextFontFamily, contextFontWeight, contextColor);
|
||||||
li.contentEditable = true;
|
li.contentEditable = true;
|
||||||
list.appendChild(li);
|
list.appendChild(li);
|
||||||
});
|
});
|
||||||
@ -11209,6 +11232,7 @@ ${galleryPagesHTML}
|
|||||||
// Default single list item
|
// Default single list item
|
||||||
const li = document.createElement("li");
|
const li = document.createElement("li");
|
||||||
li.innerHTML = "List item";
|
li.innerHTML = "List item";
|
||||||
|
this.applyContextStyling(li, contextFontSize, contextFontFamily, contextFontWeight, contextColor);
|
||||||
li.contentEditable = true;
|
li.contentEditable = true;
|
||||||
list.appendChild(li);
|
list.appendChild(li);
|
||||||
}
|
}
|
||||||
@ -11237,6 +11261,22 @@ ${galleryPagesHTML}
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply context styling to list items
|
||||||
|
applyContextStyling(li, contextFontSize, contextFontFamily, contextFontWeight, contextColor) {
|
||||||
|
if (contextFontSize && contextFontSize !== "inherit") {
|
||||||
|
li.style.fontSize = contextFontSize;
|
||||||
|
}
|
||||||
|
if (contextFontFamily && contextFontFamily !== "inherit") {
|
||||||
|
li.style.fontFamily = contextFontFamily;
|
||||||
|
}
|
||||||
|
if (contextFontWeight && contextFontWeight !== "inherit") {
|
||||||
|
li.style.fontWeight = contextFontWeight;
|
||||||
|
}
|
||||||
|
if (contextColor && contextColor !== "inherit") {
|
||||||
|
li.style.color = contextColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Apply styling to list and items
|
// Apply styling to list and items
|
||||||
styleList(list) {
|
styleList(list) {
|
||||||
if (list.tagName === "UL") list.style.listStyleType = "disc";
|
if (list.tagName === "UL") list.style.listStyleType = "disc";
|
||||||
@ -11244,15 +11284,43 @@ ${galleryPagesHTML}
|
|||||||
list.style.paddingLeft = "22px";
|
list.style.paddingLeft = "22px";
|
||||||
list.style.margin = "0 0 8px 0";
|
list.style.margin = "0 0 8px 0";
|
||||||
list.style.lineHeight = "1.6";
|
list.style.lineHeight = "1.6";
|
||||||
|
|
||||||
|
// Get the font size from the parent element to preserve it
|
||||||
|
const parentElement = list.parentElement;
|
||||||
|
let parentFontSize = null;
|
||||||
|
|
||||||
|
if (parentElement) {
|
||||||
|
const computedStyle = window.getComputedStyle(parentElement);
|
||||||
|
parentFontSize = computedStyle.fontSize;
|
||||||
|
}
|
||||||
|
|
||||||
const items = list.querySelectorAll("li");
|
const items = list.querySelectorAll("li");
|
||||||
items.forEach((li) => {
|
items.forEach((li) => {
|
||||||
li.style.margin = "4px 0";
|
li.style.margin = "4px 0";
|
||||||
li.style.paddingLeft = "4px";
|
li.style.paddingLeft = "4px";
|
||||||
// Preserve original font size - don't override it
|
|
||||||
if (!li.style.fontSize) {
|
// Preserve font size from parent element
|
||||||
// Only set default font size if none exists
|
if (parentFontSize && parentFontSize !== "inherit") {
|
||||||
|
li.style.fontSize = parentFontSize;
|
||||||
|
} else if (!li.style.fontSize) {
|
||||||
|
// Fallback to inherit if no parent font size found
|
||||||
li.style.fontSize = "inherit";
|
li.style.fontSize = "inherit";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Preserve other text styling from parent
|
||||||
|
if (parentElement) {
|
||||||
|
const computedStyle = window.getComputedStyle(parentElement);
|
||||||
|
if (computedStyle.fontFamily && computedStyle.fontFamily !== "inherit") {
|
||||||
|
li.style.fontFamily = computedStyle.fontFamily;
|
||||||
|
}
|
||||||
|
if (computedStyle.fontWeight && computedStyle.fontWeight !== "inherit") {
|
||||||
|
li.style.fontWeight = computedStyle.fontWeight;
|
||||||
|
}
|
||||||
|
if (computedStyle.color && computedStyle.color !== "inherit") {
|
||||||
|
li.style.color = computedStyle.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!li.hasAttribute("contenteditable")) li.contentEditable = true;
|
if (!li.hasAttribute("contenteditable")) li.contentEditable = true;
|
||||||
li.addEventListener("keydown", (e) => {
|
li.addEventListener("keydown", (e) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
@ -11270,6 +11338,22 @@ ${galleryPagesHTML}
|
|||||||
newLi.contentEditable = true;
|
newLi.contentEditable = true;
|
||||||
newLi.style.margin = "4px 0";
|
newLi.style.margin = "4px 0";
|
||||||
newLi.style.paddingLeft = "4px";
|
newLi.style.paddingLeft = "4px";
|
||||||
|
|
||||||
|
// Preserve styling from current list item
|
||||||
|
const computedStyle = window.getComputedStyle(currentLi);
|
||||||
|
if (computedStyle.fontSize && computedStyle.fontSize !== "inherit") {
|
||||||
|
newLi.style.fontSize = computedStyle.fontSize;
|
||||||
|
}
|
||||||
|
if (computedStyle.fontFamily && computedStyle.fontFamily !== "inherit") {
|
||||||
|
newLi.style.fontFamily = computedStyle.fontFamily;
|
||||||
|
}
|
||||||
|
if (computedStyle.fontWeight && computedStyle.fontWeight !== "inherit") {
|
||||||
|
newLi.style.fontWeight = computedStyle.fontWeight;
|
||||||
|
}
|
||||||
|
if (computedStyle.color && computedStyle.color !== "inherit") {
|
||||||
|
newLi.style.color = computedStyle.color;
|
||||||
|
}
|
||||||
|
|
||||||
newLi.addEventListener("keydown", (e) => {
|
newLi.addEventListener("keydown", (e) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -12810,122 +12894,334 @@ ${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("=== CLICK EVENT DETECTED ===");
|
console.log("=== NEW COORDINATE-BASED CLICK HANDLER ===");
|
||||||
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 details:", {
|
console.log("Target element:", e.target);
|
||||||
tagName: e.target.tagName,
|
|
||||||
className: e.target.className,
|
// Prevent default behavior
|
||||||
id: e.target.id,
|
e.preventDefault();
|
||||||
src: e.target.src
|
e.stopPropagation();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Use the new coordinate-based image detection
|
||||||
|
const clickedImage = this.detectImageAtCoordinates(e.clientX, e.clientY, editor);
|
||||||
|
|
||||||
|
if (!clickedImage) {
|
||||||
|
console.log("❌ NO IMAGE FOUND AT CLICK LOCATION");
|
||||||
|
this.showError("No image found at the clicked location. Please click directly on an image.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("✅ IMAGE FOUND:", clickedImage);
|
||||||
|
console.log("Image details:", {
|
||||||
|
tagName: clickedImage.tagName,
|
||||||
|
src: clickedImage.src,
|
||||||
|
className: clickedImage.className,
|
||||||
|
isBackgroundImage: clickedImage.isBackgroundImage,
|
||||||
|
originalElement: clickedImage.originalElement
|
||||||
});
|
});
|
||||||
|
|
||||||
// Enhanced image detection - check multiple ways to find images
|
// Store the selected image element
|
||||||
let clickedImage = null;
|
this.selectedImageElement = clickedImage;
|
||||||
|
|
||||||
// Method 1: Direct image click
|
// Check if this is the same image as the last click
|
||||||
console.log("=== METHOD 1: Direct image click ===");
|
const isSameImage = this.isSameImageAsLast(clickedImage);
|
||||||
if (
|
|
||||||
e.target.tagName === "IMG" &&
|
if (isSameImage) {
|
||||||
e.target.src &&
|
this.imageClickCount++;
|
||||||
e.target.src.trim() !== ""
|
console.log("Same image clicked, count:", this.imageClickCount);
|
||||||
) {
|
|
||||||
clickedImage = e.target;
|
|
||||||
console.log("✅ Method 1 SUCCESS: Direct IMG click detected", clickedImage);
|
|
||||||
} else {
|
} else {
|
||||||
console.log("❌ Method 1 FAILED: Not a direct IMG click");
|
this.imageClickCount = 1;
|
||||||
|
this.lastClickedImage = clickedImage;
|
||||||
|
console.log("Different image clicked, reset count to 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method 2: Click on element containing an image (children)
|
// Set timeout to reset counter
|
||||||
console.log("=== METHOD 2: Element containing image ===");
|
this.clickTimeout = setTimeout(() => {
|
||||||
if (!clickedImage && e.target.querySelector) {
|
this.imageClickCount = 0;
|
||||||
const containedImg = e.target.querySelector("img");
|
this.lastClickedImage = null;
|
||||||
if (
|
this.clearImageSelectionFeedback();
|
||||||
containedImg &&
|
console.log("Click counter reset");
|
||||||
containedImg.src &&
|
}, 1000);
|
||||||
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)
|
// Check if image can be replaced
|
||||||
console.log("=== METHOD 3: Parent traversal ===");
|
if (this.canReplaceImage(clickedImage)) {
|
||||||
if (!clickedImage) {
|
console.log("Image can be replaced, opening replacement dialog");
|
||||||
let currentElement = e.target;
|
this.openImageReplacement(clickedImage);
|
||||||
let traversalCount = 0;
|
} else {
|
||||||
while (currentElement && currentElement !== editor && traversalCount < 10) {
|
console.log("Image cannot be replaced, showing error");
|
||||||
traversalCount++;
|
this.showError("This image cannot be replaced. Please try clicking on a different image.");
|
||||||
console.log(`Traversal step ${traversalCount}:`, {
|
}
|
||||||
tagName: currentElement.tagName,
|
} catch (error) {
|
||||||
className: currentElement.className,
|
console.error("Error in image detection:", error);
|
||||||
id: currentElement.id
|
this.showError("An error occurred while processing the image click.");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// Check if current element is an IMG
|
|
||||||
if (
|
editor.hasClickHandler = true;
|
||||||
currentElement.tagName === "IMG" &&
|
|
||||||
currentElement.src &&
|
|
||||||
currentElement.src.trim() !== ""
|
|
||||||
) {
|
|
||||||
clickedImage = currentElement;
|
|
||||||
console.log("✅ Method 3 SUCCESS: Found IMG in parent traversal", clickedImage);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
// 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 {
|
|
||||||
console.log("❌ Method 3 SKIPPED: Already found image");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method 4: Check for background images in the element hierarchy (enhanced for property cards)
|
addDeselectFunctionality() {
|
||||||
console.log("=== METHOD 4: Background image detection ===");
|
for (let child of currentElement.children) {
|
||||||
if (!clickedImage) {
|
elementsToCheck.push(child);
|
||||||
let currentElement = e.target;
|
}
|
||||||
let heroBackgroundImage = null;
|
}
|
||||||
let otherBackgroundImage = null;
|
|
||||||
|
for (let element of elementsToCheck) {
|
||||||
|
const computedStyle = window.getComputedStyle(element);
|
||||||
|
const backgroundImage = computedStyle.backgroundImage;
|
||||||
|
|
||||||
|
if (
|
||||||
|
backgroundImage &&
|
||||||
|
backgroundImage !== "none" &&
|
||||||
|
backgroundImage !== "initial"
|
||||||
|
) {
|
||||||
|
// Check if this is a hero section
|
||||||
|
const isHeroSection = element.classList.contains('hero') ||
|
||||||
|
element.classList.contains('p1-image-side') ||
|
||||||
|
element.classList.contains('p2-image') ||
|
||||||
|
element.classList.contains('cover-page') ||
|
||||||
|
element.classList.contains('banner');
|
||||||
|
|
||||||
|
if (isHeroSection) {
|
||||||
|
// Create a virtual IMG element for hero background images
|
||||||
|
const virtualImg = document.createElement("img");
|
||||||
|
virtualImg.src = backgroundImage.replace(
|
||||||
|
/url\(['"]?(.+?)['"]?\)/,
|
||||||
|
"$1"
|
||||||
|
);
|
||||||
|
virtualImg.isBackgroundImage = true;
|
||||||
|
virtualImg.style.backgroundImage = backgroundImage;
|
||||||
|
virtualImg.originalElement = element;
|
||||||
|
heroBackgroundImage = virtualImg;
|
||||||
|
console.log("✅ Method 4 SUCCESS: Found HERO background image in clicked area", virtualImg);
|
||||||
|
break; // Prioritize hero sections - break immediately
|
||||||
|
} else if (element === currentElement) {
|
||||||
|
// Store the clicked element's background image as priority
|
||||||
|
const virtualImg = document.createElement("img");
|
||||||
|
virtualImg.src = backgroundImage.replace(
|
||||||
|
/url\(['"]?(.+?)['"]?\)/,
|
||||||
|
"$1"
|
||||||
|
);
|
||||||
|
virtualImg.isBackgroundImage = true;
|
||||||
|
virtualImg.style.backgroundImage = backgroundImage;
|
||||||
|
virtualImg.originalElement = element;
|
||||||
|
clickedElementBackgroundImage = virtualImg;
|
||||||
|
console.log("✅ Method 4: Found clicked element background image", virtualImg);
|
||||||
|
} else {
|
||||||
|
// Store other background images for fallback
|
||||||
|
if (!otherBackgroundImage) {
|
||||||
|
const virtualImg = document.createElement("img");
|
||||||
|
virtualImg.src = backgroundImage.replace(
|
||||||
|
/url\(['"]?(.+?)['"]?\)/,
|
||||||
|
"$1"
|
||||||
|
);
|
||||||
|
virtualImg.isBackgroundImage = true;
|
||||||
|
virtualImg.style.backgroundImage = backgroundImage;
|
||||||
|
virtualImg.originalElement = element;
|
||||||
|
otherBackgroundImage = virtualImg;
|
||||||
|
console.log("✅ Method 4: Found other background image", virtualImg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no hero image found in clicked area, traverse up the DOM tree
|
||||||
|
if (!heroBackgroundImage) {
|
||||||
|
console.log("No hero image found in clicked area, traversing up DOM tree...");
|
||||||
|
currentElement = e.target.parentElement;
|
||||||
|
|
||||||
while (currentElement && currentElement !== editor) {
|
while (currentElement && currentElement !== editor) {
|
||||||
// Check for background images on any element (not just positioned ones)
|
// Check for background images on any element (not just positioned ones)
|
||||||
@ -12940,7 +13236,9 @@ ${galleryPagesHTML}
|
|||||||
// Check if this is a hero section
|
// Check if this is a hero section
|
||||||
const isHeroSection = currentElement.classList.contains('hero') ||
|
const isHeroSection = currentElement.classList.contains('hero') ||
|
||||||
currentElement.classList.contains('p1-image-side') ||
|
currentElement.classList.contains('p1-image-side') ||
|
||||||
currentElement.classList.contains('p2-image');
|
currentElement.classList.contains('p2-image') ||
|
||||||
|
currentElement.classList.contains('cover-page') ||
|
||||||
|
currentElement.classList.contains('banner');
|
||||||
|
|
||||||
if (isHeroSection) {
|
if (isHeroSection) {
|
||||||
// Create a virtual IMG element for hero background images
|
// Create a virtual IMG element for hero background images
|
||||||
@ -12953,7 +13251,7 @@ ${galleryPagesHTML}
|
|||||||
virtualImg.style.backgroundImage = backgroundImage;
|
virtualImg.style.backgroundImage = backgroundImage;
|
||||||
virtualImg.originalElement = currentElement;
|
virtualImg.originalElement = currentElement;
|
||||||
heroBackgroundImage = virtualImg;
|
heroBackgroundImage = virtualImg;
|
||||||
console.log("✅ Method 4 SUCCESS: Found HERO background image", virtualImg);
|
console.log("✅ Method 4 SUCCESS: Found HERO background image in parent", virtualImg);
|
||||||
break; // Prioritize hero sections - break immediately
|
break; // Prioritize hero sections - break immediately
|
||||||
} else {
|
} else {
|
||||||
// Store other background images for fallback
|
// Store other background images for fallback
|
||||||
@ -12967,7 +13265,7 @@ ${galleryPagesHTML}
|
|||||||
virtualImg.style.backgroundImage = backgroundImage;
|
virtualImg.style.backgroundImage = backgroundImage;
|
||||||
virtualImg.originalElement = currentElement;
|
virtualImg.originalElement = currentElement;
|
||||||
otherBackgroundImage = virtualImg;
|
otherBackgroundImage = virtualImg;
|
||||||
console.log("✅ Method 4: Found other background image", virtualImg);
|
console.log("✅ Method 4: Found other background image in parent", virtualImg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13030,11 +13328,15 @@ ${galleryPagesHTML}
|
|||||||
|
|
||||||
currentElement = currentElement.parentElement;
|
currentElement = currentElement.parentElement;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Use hero background image if found, otherwise fall back to other background image
|
// Use hero background image if found, otherwise fall back to clicked element's background image, then other background image
|
||||||
if (heroBackgroundImage) {
|
if (heroBackgroundImage) {
|
||||||
clickedImage = heroBackgroundImage;
|
clickedImage = heroBackgroundImage;
|
||||||
console.log("✅ Method 4 SUCCESS: Using HERO background image", clickedImage);
|
console.log("✅ Method 4 SUCCESS: Using HERO background image", clickedImage);
|
||||||
|
} else if (clickedElementBackgroundImage) {
|
||||||
|
clickedImage = clickedElementBackgroundImage;
|
||||||
|
console.log("✅ Method 4 SUCCESS: Using clicked element background image", clickedImage);
|
||||||
} else if (otherBackgroundImage) {
|
} else if (otherBackgroundImage) {
|
||||||
clickedImage = otherBackgroundImage;
|
clickedImage = otherBackgroundImage;
|
||||||
console.log("✅ Method 4 SUCCESS: Using other background image", clickedImage);
|
console.log("✅ Method 4 SUCCESS: Using other background image", clickedImage);
|
||||||
@ -15432,7 +15734,8 @@ ${galleryPagesHTML}
|
|||||||
tagName: imageElement.tagName,
|
tagName: imageElement.tagName,
|
||||||
className: imageElement.className,
|
className: imageElement.className,
|
||||||
parentClassName: imageElement.parentElement?.className,
|
parentClassName: imageElement.parentElement?.className,
|
||||||
isBackgroundImage: imageElement.isBackgroundImage
|
isBackgroundImage: imageElement.isBackgroundImage,
|
||||||
|
originalElement: imageElement.originalElement?.className
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check if image is in footer
|
// Check if image is in footer
|
||||||
@ -15468,6 +15771,21 @@ ${galleryPagesHTML}
|
|||||||
console.log("Background image of footer element:", parentElement.className);
|
console.log("Background image of footer element:", parentElement.className);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Additional check: if the background image is in a footer section but not a hero section
|
||||||
|
if (parentElement) {
|
||||||
|
const isInFooterSection = parentElement.closest('footer, .page-footer, .p1-footer, .agent-footer');
|
||||||
|
const isHeroSection = parentElement.classList.contains('hero') ||
|
||||||
|
parentElement.classList.contains('p1-image-side') ||
|
||||||
|
parentElement.classList.contains('p2-image') ||
|
||||||
|
parentElement.classList.contains('cover-page') ||
|
||||||
|
parentElement.classList.contains('banner');
|
||||||
|
|
||||||
|
if (isInFooterSection && !isHeroSection) {
|
||||||
|
console.log("Background image is in footer section but not hero section:", parentElement.className);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Image is NOT footer/background - can be replaced");
|
console.log("Image is NOT footer/background - can be replaced");
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user