Refactor `EnvelopeSenderEditorPage.razor` to enhance the structure and behavior of the PDF editor wrapper: - Add `class="pdf-editor-wrapper"` and update `overflow` to `auto`. - Update `DxPdfViewer`'s `CssClass` to `sender-editor-pdf-viewer`. - Introduce `OnAfterRenderAsync` to synchronize the overlay with the viewer. Add new styles in `envelope-viewer.css` for better layout: - Ensure `.pdf-editor-wrapper` and `.sender-editor-pdf-viewer` occupy full dimensions. - Center and align content within the PDF viewer. Enhance `envelope-editor.js` with `syncOverlayToPage`: - Dynamically adjust overlay position and size relative to the viewer. - Use `MutationObserver` and event listeners for real-time synchronization. - Handle delayed rendering with scheduled sync attempts. These changes improve overlay alignment, user experience, and code maintainability.
93 lines
3.2 KiB
JavaScript
93 lines
3.2 KiB
JavaScript
window.envelopeEditor = {
|
|
_overlaySyncState: {},
|
|
|
|
/**
|
|
* Returns click coordinates relative to the overlay element.
|
|
* @param {string} overlayId - The id of the overlay div
|
|
* @param {number} clientX - MouseEventArgs.ClientX from Blazor
|
|
* @param {number} clientY - MouseEventArgs.ClientY from Blazor
|
|
* @returns {{ relX, relY, containerW, containerH }}
|
|
*/
|
|
getClickCoords: function (overlayId, clientX, clientY) {
|
|
const el = document.getElementById(overlayId);
|
|
if (!el) return null;
|
|
|
|
const rect = el.getBoundingClientRect();
|
|
return {
|
|
relX: clientX - rect.left,
|
|
relY: clientY - rect.top,
|
|
containerW: rect.width,
|
|
containerH: rect.height
|
|
};
|
|
},
|
|
|
|
syncOverlayToPage: function (wrapperId, overlayId) {
|
|
const wrapper = document.getElementById(wrapperId);
|
|
const overlay = document.getElementById(overlayId);
|
|
|
|
if (!wrapper || !overlay) {
|
|
return;
|
|
}
|
|
|
|
const existing = window.envelopeEditor._overlaySyncState[overlayId];
|
|
if (existing) {
|
|
return existing.sync();
|
|
}
|
|
|
|
const findTarget = (currentWrapper) => {
|
|
const page = currentWrapper.querySelector(".dxbrv-report-preview-content");
|
|
if (page) {
|
|
return page;
|
|
}
|
|
|
|
return currentWrapper.querySelector(".dxbrv-report-preview-content-img") ||
|
|
currentWrapper.querySelector("img.dxbrv-report-preview-content-img") ||
|
|
currentWrapper.querySelector(".dxbrv-document-surface img");
|
|
};
|
|
|
|
const sync = () => {
|
|
const currentWrapper = document.getElementById(wrapperId);
|
|
const currentOverlay = document.getElementById(overlayId);
|
|
|
|
if (!currentWrapper || !currentOverlay) {
|
|
return;
|
|
}
|
|
|
|
const target = findTarget(currentWrapper);
|
|
if (!target) {
|
|
currentOverlay.style.left = "0px";
|
|
currentOverlay.style.top = "0px";
|
|
currentOverlay.style.width = "0px";
|
|
currentOverlay.style.height = "0px";
|
|
return;
|
|
}
|
|
|
|
const wrapperRect = currentWrapper.getBoundingClientRect();
|
|
const targetRect = target.getBoundingClientRect();
|
|
|
|
currentOverlay.style.left = `${targetRect.left - wrapperRect.left + currentWrapper.scrollLeft}px`;
|
|
currentOverlay.style.top = `${targetRect.top - wrapperRect.top + currentWrapper.scrollTop}px`;
|
|
currentOverlay.style.width = `${targetRect.width}px`;
|
|
currentOverlay.style.height = `${targetRect.height}px`;
|
|
};
|
|
|
|
const scheduleSync = () => requestAnimationFrame(sync);
|
|
|
|
const observer = new MutationObserver(scheduleSync);
|
|
observer.observe(wrapper, { childList: true, subtree: true, attributes: true });
|
|
|
|
wrapper.addEventListener("scroll", scheduleSync, { passive: true });
|
|
window.addEventListener("resize", scheduleSync);
|
|
|
|
window.envelopeEditor._overlaySyncState[overlayId] = {
|
|
sync,
|
|
observer
|
|
};
|
|
|
|
sync();
|
|
setTimeout(sync, 50);
|
|
setTimeout(sync, 150);
|
|
setTimeout(sync, 400);
|
|
}
|
|
};
|