Add PDF navigation to SenderPdfImageEditor

Enhanced SenderPdfImageEditor with page navigation features:
- Added methods to navigate to first, previous, next, last, or specific pages.
- Introduced `_currentPage` to track and validate the current page.
- Implemented `OnParametersSet` to initialize/clamp `_currentPage`.
- Integrated JavaScript interop for scrolling and visible page detection.

Updated SenderPdfImageEditorToolbar:
- Added navigation buttons with enable/disable states.
- Replaced static page display with input and dropdown for page selection.
- Added event callbacks for navigation actions.

Styled new toolbar elements in `envelope-viewer.css` and added:
- Input field and dropdown for page selection.
- Adjusted layout and appearance of navigation controls.

Extended `envelope-editor.js` with:
- `scrollToPdfPage` for smooth scrolling to a specific page.
- `getVisiblePdfPageNumber` to detect the most visible page.
This commit is contained in:
2026-09-30 16:12:38 +02:00
parent 640f0b95fe
commit 8386b85592
4 changed files with 276 additions and 13 deletions

View File

@@ -145,6 +145,24 @@
height: 18px;
}
.sender-image-toolbar__select-wrap {
position: relative;
width: 1.85rem;
height: 2.1rem;
}
.sender-image-toolbar__page-select {
position: absolute;
inset: 0;
opacity: 0;
cursor: pointer;
border: 0;
}
.sender-image-toolbar__page-select:disabled {
cursor: not-allowed;
}
.sender-image-toolbar__value-box {
min-width: 8.15rem;
height: 2.1rem;
@@ -154,6 +172,7 @@
display: inline-flex;
align-items: center;
justify-content: flex-start;
gap: 0.35rem;
padding: 0 0.65rem;
color: #233252;
font-size: 0.72rem;
@@ -161,6 +180,30 @@
letter-spacing: 0.01em;
}
.sender-image-toolbar__page-input {
width: 2.3rem;
border: 0;
outline: none;
background: transparent;
color: inherit;
font-size: inherit;
font-weight: inherit;
text-align: right;
-moz-appearance: textfield;
}
.sender-image-toolbar__page-input::-webkit-outer-spin-button,
.sender-image-toolbar__page-input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.sender-image-toolbar__page-total {
color: #5b6c8f;
font-size: 0.68rem;
font-weight: 600;
}
.sender-image-editor__pages {
max-width: 980px;
margin: 0 auto;

View File

@@ -127,5 +127,63 @@ window.envelopeEditor = {
}
});
});
},
scrollToPdfPage: function (viewerCssClass, pageNumber) {
const viewer = document.querySelector('.' + viewerCssClass);
if (!viewer) {
return;
}
const targetPageNumber = Math.max(1, Number(pageNumber) || 1);
const page = viewer.querySelector('[data-editor-page="' + targetPageNumber + '"]');
if (!page) {
return;
}
const viewerRect = viewer.getBoundingClientRect();
const pageRect = page.getBoundingClientRect();
const targetScrollTop = viewer.scrollTop + (pageRect.top - viewerRect.top) - 8;
viewer.scrollTo({
top: Math.max(0, targetScrollTop),
behavior: 'smooth'
});
},
getVisiblePdfPageNumber: function (viewerCssClass) {
const viewer = document.querySelector('.' + viewerCssClass);
if (!viewer) {
return null;
}
const pages = Array.from(viewer.querySelectorAll('[data-editor-page]'));
if (pages.length === 0) {
return null;
}
const viewerRect = viewer.getBoundingClientRect();
let bestPage = null;
let bestVisibleHeight = -1;
for (const page of pages) {
const rect = page.getBoundingClientRect();
const visibleTop = Math.max(rect.top, viewerRect.top);
const visibleBottom = Math.min(rect.bottom, viewerRect.bottom);
const visibleHeight = Math.max(0, visibleBottom - visibleTop);
if (visibleHeight > bestVisibleHeight) {
bestVisibleHeight = visibleHeight;
bestPage = page;
}
}
if (!bestPage) {
return null;
}
const raw = bestPage.getAttribute('data-editor-page');
const parsed = Number.parseInt(raw || '0', 10);
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
}
};