mirror of
https://github.com/zen-browser/pdf.js.git
synced 2025-07-09 17:55:37 +02:00
Add a new Page scrolling mode (issue 2638, 8952, 10907)
This implements a new Page scrolling mode, essentially bringing (and extending) the functionality from `PDFSinglePageViewer` into the regular `PDFViewer`-class. Compared to `PDFSinglePageViewer`, which as its name suggests will only display one page at a time, in the `PDFViewer`-implementation this new Page scrolling mode also support spreadModes properly (somewhat similar to e.g. Adobe Reader). Given the size and scope of these changes, I've tried to focus on implementing the basic functionality. Hence there's room for further clean-up and/or improvements, including e.g. simplifying the CSS/JS related to PresentationMode and implementing easier page-switching with the mouse-wheel/arrow-keys.
This commit is contained in:
parent
3945965605
commit
511458fbbc
14 changed files with 296 additions and 244 deletions
|
@ -61,6 +61,8 @@ cursor_text_select_tool_label=Text Selection Tool
|
||||||
cursor_hand_tool.title=Enable Hand Tool
|
cursor_hand_tool.title=Enable Hand Tool
|
||||||
cursor_hand_tool_label=Hand Tool
|
cursor_hand_tool_label=Hand Tool
|
||||||
|
|
||||||
|
scroll_page.title=Use Page Scrolling
|
||||||
|
scroll_page_label=Page Scrolling
|
||||||
scroll_vertical.title=Use Vertical Scrolling
|
scroll_vertical.title=Use Vertical Scrolling
|
||||||
scroll_vertical_label=Vertical Scrolling
|
scroll_vertical_label=Vertical Scrolling
|
||||||
scroll_horizontal.title=Use Horizontal Scrolling
|
scroll_horizontal.title=Use Horizontal Scrolling
|
||||||
|
|
|
@ -61,6 +61,8 @@ cursor_text_select_tool_label=Textmarkeringsverktyg
|
||||||
cursor_hand_tool.title=Aktivera handverktyg
|
cursor_hand_tool.title=Aktivera handverktyg
|
||||||
cursor_hand_tool_label=Handverktyg
|
cursor_hand_tool_label=Handverktyg
|
||||||
|
|
||||||
|
scroll_page.title=Använd sidrullning
|
||||||
|
scroll_page_label=Sidrullning
|
||||||
scroll_vertical.title=Använd vertikal rullning
|
scroll_vertical.title=Använd vertikal rullning
|
||||||
scroll_vertical_label=Vertikal rullning
|
scroll_vertical_label=Vertikal rullning
|
||||||
scroll_horizontal.title=Använd horisontell rullning
|
scroll_horizontal.title=Använd horisontell rullning
|
||||||
|
|
14
web/app.js
14
web/app.js
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
import {
|
import {
|
||||||
animationStarted,
|
animationStarted,
|
||||||
apiPageLayoutToSpreadMode,
|
apiPageLayoutToViewerModes,
|
||||||
apiPageModeToSidebarView,
|
apiPageModeToSidebarView,
|
||||||
AutomationEventBus,
|
AutomationEventBus,
|
||||||
AutoPrintRegExp,
|
AutoPrintRegExp,
|
||||||
|
@ -1300,8 +1300,16 @@ const PDFViewerApplication = {
|
||||||
if (pageMode && sidebarView === SidebarView.UNKNOWN) {
|
if (pageMode && sidebarView === SidebarView.UNKNOWN) {
|
||||||
sidebarView = apiPageModeToSidebarView(pageMode);
|
sidebarView = apiPageModeToSidebarView(pageMode);
|
||||||
}
|
}
|
||||||
if (pageLayout && spreadMode === SpreadMode.UNKNOWN) {
|
if (
|
||||||
spreadMode = apiPageLayoutToSpreadMode(pageLayout);
|
pageLayout &&
|
||||||
|
scrollMode === ScrollMode.UNKNOWN &&
|
||||||
|
spreadMode === SpreadMode.UNKNOWN
|
||||||
|
) {
|
||||||
|
const modes = apiPageLayoutToViewerModes(pageLayout);
|
||||||
|
// TODO: Try to improve page-switching when using the mouse-wheel
|
||||||
|
// and/or arrow-keys before allowing the document to control this.
|
||||||
|
// scrollMode = modes.scrollMode;
|
||||||
|
spreadMode = modes.spreadMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setInitialView(hash, {
|
this.setInitialView(hash, {
|
||||||
|
|
|
@ -445,14 +445,6 @@ class BaseViewer {
|
||||||
return this.pdfDocument ? this._pagesCapability.promise : null;
|
return this.pdfDocument ? this._pagesCapability.promise : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
get _viewerElement() {
|
|
||||||
// In most viewers, e.g. `PDFViewer`, this should return `this.viewer`.
|
|
||||||
throw new Error("Not implemented: _viewerElement");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
@ -538,6 +530,10 @@ class BaseViewer {
|
||||||
this._firstPageCapability.resolve(firstPdfPage);
|
this._firstPageCapability.resolve(firstPdfPage);
|
||||||
this._optionalContentConfigPromise = optionalContentConfigPromise;
|
this._optionalContentConfigPromise = optionalContentConfigPromise;
|
||||||
|
|
||||||
|
const viewerElement =
|
||||||
|
this._scrollMode === ScrollMode.PAGE
|
||||||
|
? this._scrollModePageState.shadowViewer
|
||||||
|
: this.viewer;
|
||||||
const scale = this.currentScale;
|
const scale = this.currentScale;
|
||||||
const viewport = firstPdfPage.getViewport({
|
const viewport = firstPdfPage.getViewport({
|
||||||
scale: scale * PixelsPerInch.PDF_TO_CSS_UNITS,
|
scale: scale * PixelsPerInch.PDF_TO_CSS_UNITS,
|
||||||
|
@ -552,7 +548,7 @@ class BaseViewer {
|
||||||
|
|
||||||
for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
||||||
const pageView = new PDFPageView({
|
const pageView = new PDFPageView({
|
||||||
container: this._viewerElement,
|
container: viewerElement,
|
||||||
eventBus: this.eventBus,
|
eventBus: this.eventBus,
|
||||||
id: pageNum,
|
id: pageNum,
|
||||||
scale,
|
scale,
|
||||||
|
@ -582,7 +578,12 @@ class BaseViewer {
|
||||||
firstPageView.setPdfPage(firstPdfPage);
|
firstPageView.setPdfPage(firstPdfPage);
|
||||||
this.linkService.cachePageRef(1, firstPdfPage.ref);
|
this.linkService.cachePageRef(1, firstPdfPage.ref);
|
||||||
}
|
}
|
||||||
if (this._spreadMode !== SpreadMode.NONE) {
|
|
||||||
|
if (this._scrollMode === ScrollMode.PAGE) {
|
||||||
|
// Since the pages are placed in a `DocumentFragment`, ensure that
|
||||||
|
// the current page becomes visible upon loading of the document.
|
||||||
|
this._ensurePageViewVisible();
|
||||||
|
} else if (this._spreadMode !== SpreadMode.NONE) {
|
||||||
this._updateSpreadMode();
|
this._updateSpreadMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,8 +685,16 @@ class BaseViewer {
|
||||||
this._onePageRenderedCapability = createPromiseCapability();
|
this._onePageRenderedCapability = createPromiseCapability();
|
||||||
this._pagesCapability = createPromiseCapability();
|
this._pagesCapability = createPromiseCapability();
|
||||||
this._scrollMode = ScrollMode.VERTICAL;
|
this._scrollMode = ScrollMode.VERTICAL;
|
||||||
|
this._previousScrollMode = ScrollMode.UNKNOWN;
|
||||||
this._spreadMode = SpreadMode.NONE;
|
this._spreadMode = SpreadMode.NONE;
|
||||||
|
|
||||||
|
this._scrollModePageState = {
|
||||||
|
shadowViewer: document.createDocumentFragment(),
|
||||||
|
previousPageNumber: 1,
|
||||||
|
scrollDown: true,
|
||||||
|
pages: [],
|
||||||
|
};
|
||||||
|
|
||||||
if (this._onBeforeDraw) {
|
if (this._onBeforeDraw) {
|
||||||
this.eventBus._off("pagerender", this._onBeforeDraw);
|
this.eventBus._off("pagerender", this._onBeforeDraw);
|
||||||
this._onBeforeDraw = null;
|
this._onBeforeDraw = null;
|
||||||
|
@ -700,6 +709,71 @@ class BaseViewer {
|
||||||
this._updateScrollMode();
|
this._updateScrollMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ensurePageViewVisible() {
|
||||||
|
if (this._scrollMode !== ScrollMode.PAGE) {
|
||||||
|
throw new Error("_ensurePageViewVisible: Invalid scrollMode value.");
|
||||||
|
}
|
||||||
|
const pageNumber = this._currentPageNumber,
|
||||||
|
state = this._scrollModePageState,
|
||||||
|
viewer = this.viewer;
|
||||||
|
|
||||||
|
// Remove the currently active pages, if any, from the viewer.
|
||||||
|
if (viewer.hasChildNodes()) {
|
||||||
|
// Temporarily remove all the pages from the DOM.
|
||||||
|
viewer.textContent = "";
|
||||||
|
|
||||||
|
for (const pageView of this._pages) {
|
||||||
|
state.shadowViewer.appendChild(pageView.div);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.pages.length = 0;
|
||||||
|
|
||||||
|
if (this._spreadMode === SpreadMode.NONE) {
|
||||||
|
// Finally, append the new page to the viewer.
|
||||||
|
const pageView = this._pages[pageNumber - 1];
|
||||||
|
viewer.appendChild(pageView.div);
|
||||||
|
|
||||||
|
state.pages.push(pageView);
|
||||||
|
} else {
|
||||||
|
const pageIndexSet = new Set(),
|
||||||
|
parity = this._spreadMode - 1;
|
||||||
|
|
||||||
|
// Determine the pageIndices in the new spread.
|
||||||
|
if (pageNumber % 2 !== parity) {
|
||||||
|
// Left-hand side page.
|
||||||
|
pageIndexSet.add(pageNumber - 1);
|
||||||
|
pageIndexSet.add(pageNumber);
|
||||||
|
} else {
|
||||||
|
// Right-hand side page.
|
||||||
|
pageIndexSet.add(pageNumber - 2);
|
||||||
|
pageIndexSet.add(pageNumber - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, append the new pages to the viewer and apply the spreadMode.
|
||||||
|
let spread = null;
|
||||||
|
for (let i = 0, ii = this._pages.length; i < ii; ++i) {
|
||||||
|
if (!pageIndexSet.has(i)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (spread === null) {
|
||||||
|
spread = document.createElement("div");
|
||||||
|
spread.className = "spread";
|
||||||
|
viewer.appendChild(spread);
|
||||||
|
} else if (i % 2 === parity) {
|
||||||
|
spread = spread.cloneNode(false);
|
||||||
|
viewer.appendChild(spread);
|
||||||
|
}
|
||||||
|
const pageView = this._pages[i];
|
||||||
|
spread.appendChild(pageView.div);
|
||||||
|
|
||||||
|
state.pages.push(pageView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.scrollDown = pageNumber >= state.previousPageNumber;
|
||||||
|
state.previousPageNumber = pageNumber;
|
||||||
|
}
|
||||||
|
|
||||||
_scrollUpdate() {
|
_scrollUpdate() {
|
||||||
if (this.pagesCount === 0) {
|
if (this.pagesCount === 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -708,6 +782,29 @@ class BaseViewer {
|
||||||
}
|
}
|
||||||
|
|
||||||
_scrollIntoView({ pageDiv, pageSpot = null, pageNumber = null }) {
|
_scrollIntoView({ pageDiv, pageSpot = null, pageNumber = null }) {
|
||||||
|
if (this._scrollMode === ScrollMode.PAGE) {
|
||||||
|
if (pageNumber) {
|
||||||
|
// Ensure that `this._currentPageNumber` is correct.
|
||||||
|
this._setCurrentPageNumber(pageNumber);
|
||||||
|
}
|
||||||
|
this._ensurePageViewVisible();
|
||||||
|
// Ensure that rendering always occurs, to avoid showing a blank page,
|
||||||
|
// even if the current position doesn't change when the page is scrolled.
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pageSpot && !this.isInPresentationMode) {
|
||||||
|
const left = pageDiv.offsetLeft + pageDiv.clientLeft;
|
||||||
|
const right = left + pageDiv.clientWidth;
|
||||||
|
const { scrollLeft, clientWidth } = this.container;
|
||||||
|
if (
|
||||||
|
this._scrollMode === ScrollMode.HORIZONTAL ||
|
||||||
|
left < scrollLeft ||
|
||||||
|
right > scrollLeft + clientWidth
|
||||||
|
) {
|
||||||
|
pageSpot = { left: 0, top: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
scrollIntoView(pageDiv, pageSpot);
|
scrollIntoView(pageDiv, pageSpot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,8 +869,7 @@ class BaseViewer {
|
||||||
get _pageWidthScaleFactor() {
|
get _pageWidthScaleFactor() {
|
||||||
if (
|
if (
|
||||||
this._spreadMode !== SpreadMode.NONE &&
|
this._spreadMode !== SpreadMode.NONE &&
|
||||||
this._scrollMode !== ScrollMode.HORIZONTAL &&
|
this._scrollMode !== ScrollMode.HORIZONTAL
|
||||||
!this.isInPresentationMode
|
|
||||||
) {
|
) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -794,7 +890,7 @@ class BaseViewer {
|
||||||
let hPadding = noPadding ? 0 : SCROLLBAR_PADDING;
|
let hPadding = noPadding ? 0 : SCROLLBAR_PADDING;
|
||||||
let vPadding = noPadding ? 0 : VERTICAL_PADDING;
|
let vPadding = noPadding ? 0 : VERTICAL_PADDING;
|
||||||
|
|
||||||
if (!noPadding && this._isScrollModeHorizontal) {
|
if (!noPadding && this._scrollMode === ScrollMode.HORIZONTAL) {
|
||||||
[hPadding, vPadding] = [vPadding, hPadding]; // Swap the padding values.
|
[hPadding, vPadding] = [vPadding, hPadding]; // Swap the padding values.
|
||||||
}
|
}
|
||||||
const pageWidthScale =
|
const pageWidthScale =
|
||||||
|
@ -1047,10 +1143,6 @@ class BaseViewer {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateHelper(visiblePages) {
|
|
||||||
throw new Error("Not implemented: _updateHelper");
|
|
||||||
}
|
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
const visible = this._getVisiblePages();
|
const visible = this._getVisiblePages();
|
||||||
const visiblePages = visible.views,
|
const visiblePages = visible.views,
|
||||||
|
@ -1064,7 +1156,28 @@ class BaseViewer {
|
||||||
|
|
||||||
this.renderingQueue.renderHighestPriority(visible);
|
this.renderingQueue.renderHighestPriority(visible);
|
||||||
|
|
||||||
this._updateHelper(visiblePages); // Run any class-specific update code.
|
if (!this.isInPresentationMode) {
|
||||||
|
const isSimpleLayout =
|
||||||
|
this._spreadMode === SpreadMode.NONE &&
|
||||||
|
(this._scrollMode === ScrollMode.PAGE ||
|
||||||
|
this._scrollMode === ScrollMode.VERTICAL);
|
||||||
|
let currentId = this._currentPageNumber;
|
||||||
|
let stillFullyVisible = false;
|
||||||
|
|
||||||
|
for (const page of visiblePages) {
|
||||||
|
if (page.percent < 100) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (page.id === currentId && isSimpleLayout) {
|
||||||
|
stillFullyVisible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!stillFullyVisible) {
|
||||||
|
currentId = visiblePages[0].id;
|
||||||
|
}
|
||||||
|
this._setCurrentPageNumber(currentId);
|
||||||
|
}
|
||||||
|
|
||||||
this._updateLocation(visible.first);
|
this._updateLocation(visible.first);
|
||||||
this.eventBus.dispatch("updateviewarea", {
|
this.eventBus.dispatch("updateviewarea", {
|
||||||
|
@ -1081,14 +1194,6 @@ class BaseViewer {
|
||||||
this.container.focus();
|
this.container.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
get _isScrollModeHorizontal() {
|
|
||||||
// Used to ensure that pre-rendering of the next/previous page works
|
|
||||||
// correctly, since Scroll/Spread modes are ignored in Presentation Mode.
|
|
||||||
return this.isInPresentationMode
|
|
||||||
? false
|
|
||||||
: this._scrollMode === ScrollMode.HORIZONTAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
get _isContainerRtl() {
|
get _isContainerRtl() {
|
||||||
return getComputedStyle(this.container).direction === "rtl";
|
return getComputedStyle(this.container).direction === "rtl";
|
||||||
}
|
}
|
||||||
|
@ -1115,9 +1220,8 @@ class BaseViewer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method for `this._getVisiblePages`. Should only ever be used when
|
* Helper method for `this._getVisiblePages`. Should only ever be used when
|
||||||
* the viewer can only display a single page at a time, for example in:
|
* the viewer can only display a single page at a time, for example:
|
||||||
* - `PDFSinglePageViewer`.
|
* - When PresentationMode is active.
|
||||||
* - `PDFViewer` with Presentation Mode active.
|
|
||||||
*/
|
*/
|
||||||
_getCurrentVisiblePage() {
|
_getCurrentVisiblePage() {
|
||||||
if (!this.pagesCount) {
|
if (!this.pagesCount) {
|
||||||
|
@ -1138,12 +1242,24 @@ class BaseViewer {
|
||||||
}
|
}
|
||||||
|
|
||||||
_getVisiblePages() {
|
_getVisiblePages() {
|
||||||
|
if (this.isInPresentationMode) {
|
||||||
|
// The algorithm in `getVisibleElements` doesn't work in all browsers and
|
||||||
|
// configurations (e.g. Chrome) when PresentationMode is active.
|
||||||
|
return this._getCurrentVisiblePage();
|
||||||
|
}
|
||||||
|
const views =
|
||||||
|
this._scrollMode === ScrollMode.PAGE
|
||||||
|
? this._scrollModePageState.pages
|
||||||
|
: this._pages,
|
||||||
|
horizontal = this._scrollMode === ScrollMode.HORIZONTAL,
|
||||||
|
rtl = horizontal && this._isContainerRtl;
|
||||||
|
|
||||||
return getVisibleElements({
|
return getVisibleElements({
|
||||||
scrollEl: this.container,
|
scrollEl: this.container,
|
||||||
views: this._pages,
|
views,
|
||||||
sortByVisibility: true,
|
sortByVisibility: true,
|
||||||
horizontal: this._isScrollModeHorizontal,
|
horizontal,
|
||||||
rtl: this._isScrollModeHorizontal && this._isContainerRtl,
|
rtl,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1245,15 +1361,25 @@ class BaseViewer {
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
get _scrollAhead() {
|
||||||
|
switch (this._scrollMode) {
|
||||||
|
case ScrollMode.PAGE:
|
||||||
|
return this._scrollModePageState.scrollDown;
|
||||||
|
case ScrollMode.HORIZONTAL:
|
||||||
|
return this.scroll.right;
|
||||||
|
}
|
||||||
|
return this.scroll.down;
|
||||||
|
}
|
||||||
|
|
||||||
forceRendering(currentlyVisiblePages) {
|
forceRendering(currentlyVisiblePages) {
|
||||||
const visiblePages = currentlyVisiblePages || this._getVisiblePages();
|
const visiblePages = currentlyVisiblePages || this._getVisiblePages();
|
||||||
const scrollAhead = this._isScrollModeHorizontal
|
const scrollAhead = this._scrollAhead;
|
||||||
? this.scroll.right
|
|
||||||
: this.scroll.down;
|
|
||||||
const preRenderExtra =
|
const preRenderExtra =
|
||||||
this._scrollMode === ScrollMode.VERTICAL &&
|
|
||||||
this._spreadMode !== SpreadMode.NONE &&
|
this._spreadMode !== SpreadMode.NONE &&
|
||||||
!this.isInPresentationMode;
|
this._scrollMode !== ScrollMode.HORIZONTAL;
|
||||||
|
|
||||||
const pageView = this.renderingQueue.getHighestPriority(
|
const pageView = this.renderingQueue.getHighestPriority(
|
||||||
visiblePages,
|
visiblePages,
|
||||||
|
@ -1492,6 +1618,8 @@ class BaseViewer {
|
||||||
if (!isValidScrollMode(mode)) {
|
if (!isValidScrollMode(mode)) {
|
||||||
throw new Error(`Invalid scroll mode: ${mode}`);
|
throw new Error(`Invalid scroll mode: ${mode}`);
|
||||||
}
|
}
|
||||||
|
this._previousScrollMode = this._scrollMode;
|
||||||
|
|
||||||
this._scrollMode = mode;
|
this._scrollMode = mode;
|
||||||
this.eventBus.dispatch("scrollmodechanged", { source: this, mode });
|
this.eventBus.dispatch("scrollmodechanged", { source: this, mode });
|
||||||
|
|
||||||
|
@ -1511,6 +1639,14 @@ class BaseViewer {
|
||||||
if (!this.pdfDocument || !pageNumber) {
|
if (!this.pdfDocument || !pageNumber) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scrollMode === ScrollMode.PAGE) {
|
||||||
|
this._ensurePageViewVisible();
|
||||||
|
} else if (this._previousScrollMode === ScrollMode.PAGE) {
|
||||||
|
// Ensure that the current spreadMode is still applied correctly when
|
||||||
|
// the *previous* scrollMode was `ScrollMode.PAGE`.
|
||||||
|
this._updateSpreadMode();
|
||||||
|
}
|
||||||
// Non-numeric scale values can be sensitive to the scroll orientation.
|
// Non-numeric scale values can be sensitive to the scroll orientation.
|
||||||
// Call this before re-scrolling to the current page, to ensure that any
|
// Call this before re-scrolling to the current page, to ensure that any
|
||||||
// changes in scale don't move the current page.
|
// changes in scale don't move the current page.
|
||||||
|
@ -1552,32 +1688,40 @@ class BaseViewer {
|
||||||
}
|
}
|
||||||
const viewer = this.viewer,
|
const viewer = this.viewer,
|
||||||
pages = this._pages;
|
pages = this._pages;
|
||||||
// Temporarily remove all the pages from the DOM.
|
|
||||||
viewer.textContent = "";
|
|
||||||
|
|
||||||
if (this._spreadMode === SpreadMode.NONE) {
|
if (this._scrollMode === ScrollMode.PAGE) {
|
||||||
for (let i = 0, iMax = pages.length; i < iMax; ++i) {
|
this._ensurePageViewVisible();
|
||||||
viewer.appendChild(pages[i].div);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const parity = this._spreadMode - 1;
|
// Temporarily remove all the pages from the DOM.
|
||||||
let spread = null;
|
viewer.textContent = "";
|
||||||
for (let i = 0, iMax = pages.length; i < iMax; ++i) {
|
|
||||||
if (spread === null) {
|
if (this._spreadMode === SpreadMode.NONE) {
|
||||||
spread = document.createElement("div");
|
for (let i = 0, ii = pages.length; i < ii; ++i) {
|
||||||
spread.className = "spread";
|
viewer.appendChild(pages[i].div);
|
||||||
viewer.appendChild(spread);
|
}
|
||||||
} else if (i % 2 === parity) {
|
} else {
|
||||||
spread = spread.cloneNode(false);
|
const parity = this._spreadMode - 1;
|
||||||
viewer.appendChild(spread);
|
let spread = null;
|
||||||
|
for (let i = 0, ii = pages.length; i < ii; ++i) {
|
||||||
|
if (spread === null) {
|
||||||
|
spread = document.createElement("div");
|
||||||
|
spread.className = "spread";
|
||||||
|
viewer.appendChild(spread);
|
||||||
|
} else if (i % 2 === parity) {
|
||||||
|
spread = spread.cloneNode(false);
|
||||||
|
viewer.appendChild(spread);
|
||||||
|
}
|
||||||
|
spread.appendChild(pages[i].div);
|
||||||
}
|
}
|
||||||
spread.appendChild(pages[i].div);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pageNumber) {
|
if (!pageNumber) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Non-numeric scale values can be sensitive to the scroll orientation.
|
||||||
|
// Call this before re-scrolling to the current page, to ensure that any
|
||||||
|
// changes in scale don't move the current page.
|
||||||
if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
|
if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
|
||||||
this._setScale(this._currentScaleValue, true);
|
this._setScale(this._currentScaleValue, true);
|
||||||
}
|
}
|
||||||
|
@ -1589,9 +1733,6 @@ class BaseViewer {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_getPageAdvance(currentPageNumber, previous = false) {
|
_getPageAdvance(currentPageNumber, previous = false) {
|
||||||
if (this.isInPresentationMode) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
switch (this._scrollMode) {
|
switch (this._scrollMode) {
|
||||||
case ScrollMode.WRAPPED: {
|
case ScrollMode.WRAPPED: {
|
||||||
const { views } = this._getVisiblePages(),
|
const { views } = this._getVisiblePages(),
|
||||||
|
@ -1655,6 +1796,7 @@ class BaseViewer {
|
||||||
case ScrollMode.HORIZONTAL: {
|
case ScrollMode.HORIZONTAL: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ScrollMode.PAGE:
|
||||||
case ScrollMode.VERTICAL: {
|
case ScrollMode.VERTICAL: {
|
||||||
if (this._spreadMode === SpreadMode.NONE) {
|
if (this._spreadMode === SpreadMode.NONE) {
|
||||||
break; // Normal vertical scrolling.
|
break; // Normal vertical scrolling.
|
||||||
|
|
1
web/images/secondaryToolbarButton-scrollPage.svg
Normal file
1
web/images/secondaryToolbarButton-scrollPage.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"><path d="M9.5 4c1 0 1.5.5 1.5 1.5v5c0 1-.5 1.5-1.5 1.5h-3c-1 0-1.5-.5-1.5-1.5v-5C5 4.5 5.5 4 6.5 4z"/></svg>
|
After Width: | Height: | Size: 171 B |
|
@ -13,7 +13,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { normalizeWheelEventDelta, PresentationModeState } from "./ui_utils.js";
|
import {
|
||||||
|
normalizeWheelEventDelta,
|
||||||
|
PresentationModeState,
|
||||||
|
ScrollMode,
|
||||||
|
SpreadMode,
|
||||||
|
} from "./ui_utils.js";
|
||||||
|
|
||||||
const DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1500; // in ms
|
const DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1500; // in ms
|
||||||
const DELAY_BEFORE_HIDING_CONTROLS = 3000; // in ms
|
const DELAY_BEFORE_HIDING_CONTROLS = 3000; // in ms
|
||||||
|
@ -84,8 +89,10 @@ class PDFPresentationMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.args = {
|
this.args = {
|
||||||
page: this.pdfViewer.currentPageNumber,
|
pageNumber: this.pdfViewer.currentPageNumber,
|
||||||
previousScale: this.pdfViewer.currentScaleValue,
|
scaleValue: this.pdfViewer.currentScaleValue,
|
||||||
|
scrollMode: this.pdfViewer.scrollMode,
|
||||||
|
spreadMode: this.pdfViewer.spreadMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -203,7 +210,9 @@ class PDFPresentationMode {
|
||||||
// Ensure that the correct page is scrolled into view when entering
|
// Ensure that the correct page is scrolled into view when entering
|
||||||
// Presentation Mode, by waiting until fullscreen mode in enabled.
|
// Presentation Mode, by waiting until fullscreen mode in enabled.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.pdfViewer.currentPageNumber = this.args.page;
|
this.pdfViewer.scrollMode = ScrollMode.PAGE;
|
||||||
|
this.pdfViewer.spreadMode = SpreadMode.NONE;
|
||||||
|
this.pdfViewer.currentPageNumber = this.args.pageNumber;
|
||||||
this.pdfViewer.currentScaleValue = "page-fit";
|
this.pdfViewer.currentScaleValue = "page-fit";
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
|
@ -221,7 +230,7 @@ class PDFPresentationMode {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_exit() {
|
_exit() {
|
||||||
const page = this.pdfViewer.currentPageNumber;
|
const pageNumber = this.pdfViewer.currentPageNumber;
|
||||||
this.container.classList.remove(ACTIVE_SELECTOR);
|
this.container.classList.remove(ACTIVE_SELECTOR);
|
||||||
|
|
||||||
// Ensure that the correct page is scrolled into view when exiting
|
// Ensure that the correct page is scrolled into view when exiting
|
||||||
|
@ -231,8 +240,10 @@ class PDFPresentationMode {
|
||||||
this._removeFullscreenChangeListeners();
|
this._removeFullscreenChangeListeners();
|
||||||
this._notifyStateChange();
|
this._notifyStateChange();
|
||||||
|
|
||||||
this.pdfViewer.currentScaleValue = this.args.previousScale;
|
this.pdfViewer.scrollMode = this.args.scrollMode;
|
||||||
this.pdfViewer.currentPageNumber = page;
|
this.pdfViewer.spreadMode = this.args.spreadMode;
|
||||||
|
this.pdfViewer.currentScaleValue = this.args.scaleValue;
|
||||||
|
this.pdfViewer.currentPageNumber = pageNumber;
|
||||||
this.args = null;
|
this.args = null;
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createPromiseCapability, shadow } from "pdfjs-lib";
|
import { createPromiseCapability, shadow } from "pdfjs-lib";
|
||||||
import { apiPageLayoutToSpreadMode } from "./ui_utils.js";
|
import { apiPageLayoutToViewerModes } from "./ui_utils.js";
|
||||||
import { RenderingStates } from "./pdf_rendering_queue.js";
|
import { RenderingStates } from "./pdf_rendering_queue.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -287,7 +287,11 @@ class PDFScriptingManager {
|
||||||
console.error(value);
|
console.error(value);
|
||||||
break;
|
break;
|
||||||
case "layout":
|
case "layout":
|
||||||
this._pdfViewer.spreadMode = apiPageLayoutToSpreadMode(value);
|
if (isInPresentationMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const modes = apiPageLayoutToViewerModes(value);
|
||||||
|
this._pdfViewer.spreadMode = modes.spreadMode;
|
||||||
break;
|
break;
|
||||||
case "page-num":
|
case "page-num":
|
||||||
this._pdfViewer.currentPageNumber = value + 1;
|
this._pdfViewer.currentPageNumber = value + 1;
|
||||||
|
|
|
@ -13,118 +13,25 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { ScrollMode, SpreadMode } from "./ui_utils.js";
|
||||||
import { BaseViewer } from "./base_viewer.js";
|
import { BaseViewer } from "./base_viewer.js";
|
||||||
import { shadow } from "pdfjs-lib";
|
|
||||||
|
|
||||||
class PDFSinglePageViewer extends BaseViewer {
|
class PDFSinglePageViewer extends BaseViewer {
|
||||||
constructor(options) {
|
|
||||||
super(options);
|
|
||||||
|
|
||||||
this.eventBus._on("pagesinit", evt => {
|
|
||||||
// Since the pages are placed in a `DocumentFragment`, make sure that
|
|
||||||
// the current page becomes visible upon loading of the document.
|
|
||||||
this._ensurePageViewVisible();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get _viewerElement() {
|
|
||||||
// Since we only want to display *one* page at a time when using the
|
|
||||||
// `PDFSinglePageViewer`, we cannot append them to the `viewer` DOM element.
|
|
||||||
// Instead, they are placed in a `DocumentFragment`, and only the current
|
|
||||||
// page is displayed in the viewer (refer to `this._ensurePageViewVisible`).
|
|
||||||
return shadow(this, "_viewerElement", this._shadowViewer);
|
|
||||||
}
|
|
||||||
|
|
||||||
get _pageWidthScaleFactor() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_resetView() {
|
_resetView() {
|
||||||
super._resetView();
|
super._resetView();
|
||||||
this._previousPageNumber = 1;
|
this._scrollMode = ScrollMode.PAGE;
|
||||||
this._shadowViewer = document.createDocumentFragment();
|
this._spreadMode = SpreadMode.NONE;
|
||||||
this._updateScrollDown = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ensurePageViewVisible() {
|
// eslint-disable-next-line accessor-pairs
|
||||||
const pageView = this._pages[this._currentPageNumber - 1];
|
set scrollMode(mode) {}
|
||||||
const previousPageView = this._pages[this._previousPageNumber - 1];
|
|
||||||
|
|
||||||
const viewerNodes = this.viewer.childNodes;
|
|
||||||
switch (viewerNodes.length) {
|
|
||||||
case 0: // Should *only* occur on initial loading.
|
|
||||||
this.viewer.appendChild(pageView.div);
|
|
||||||
break;
|
|
||||||
case 1: // The normal page-switching case.
|
|
||||||
if (viewerNodes[0] !== previousPageView.div) {
|
|
||||||
throw new Error(
|
|
||||||
"_ensurePageViewVisible: Unexpected previously visible page."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (pageView === previousPageView) {
|
|
||||||
break; // The correct page is already visible.
|
|
||||||
}
|
|
||||||
// Switch visible pages, and reset the viewerContainer scroll position.
|
|
||||||
this._shadowViewer.appendChild(previousPageView.div);
|
|
||||||
this.viewer.appendChild(pageView.div);
|
|
||||||
|
|
||||||
this.container.scrollTop = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error(
|
|
||||||
"_ensurePageViewVisible: Only one page should be visible at a time."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this._previousPageNumber = this._currentPageNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
_scrollUpdate() {
|
|
||||||
if (this._updateScrollDown) {
|
|
||||||
this._updateScrollDown();
|
|
||||||
}
|
|
||||||
super._scrollUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
_scrollIntoView({ pageDiv, pageSpot = null, pageNumber = null }) {
|
|
||||||
if (pageNumber) {
|
|
||||||
// Ensure that `this._currentPageNumber` is correct.
|
|
||||||
this._setCurrentPageNumber(pageNumber);
|
|
||||||
}
|
|
||||||
const scrolledDown = this._currentPageNumber >= this._previousPageNumber;
|
|
||||||
|
|
||||||
this._ensurePageViewVisible();
|
|
||||||
// Ensure that rendering always occurs, to avoid showing a blank page,
|
|
||||||
// even if the current position doesn't change when the page is scrolled.
|
|
||||||
this.update();
|
|
||||||
|
|
||||||
super._scrollIntoView({ pageDiv, pageSpot, pageNumber });
|
|
||||||
|
|
||||||
// Since scrolling is tracked using `requestAnimationFrame`, update the
|
|
||||||
// scroll direction during the next `this._scrollUpdate` invocation.
|
|
||||||
this._updateScrollDown = () => {
|
|
||||||
this.scroll.down = scrolledDown;
|
|
||||||
this._updateScrollDown = null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_getVisiblePages() {
|
|
||||||
return this._getCurrentVisiblePage();
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateHelper(visiblePages) {}
|
|
||||||
|
|
||||||
get _isScrollModeHorizontal() {
|
|
||||||
// The Scroll/Spread modes are never used in `PDFSinglePageViewer`.
|
|
||||||
return shadow(this, "_isScrollModeHorizontal", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateScrollMode() {}
|
_updateScrollMode() {}
|
||||||
|
|
||||||
_updateSpreadMode() {}
|
// eslint-disable-next-line accessor-pairs
|
||||||
|
set spreadMode(mode) {}
|
||||||
|
|
||||||
_getPageAdvance() {
|
_updateSpreadMode() {}
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { PDFSinglePageViewer };
|
export { PDFSinglePageViewer };
|
||||||
|
|
|
@ -13,65 +13,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ScrollMode, SpreadMode } from "./ui_utils.js";
|
|
||||||
import { BaseViewer } from "./base_viewer.js";
|
import { BaseViewer } from "./base_viewer.js";
|
||||||
import { shadow } from "pdfjs-lib";
|
|
||||||
|
|
||||||
class PDFViewer extends BaseViewer {
|
class PDFViewer extends BaseViewer {}
|
||||||
get _viewerElement() {
|
|
||||||
return shadow(this, "_viewerElement", this.viewer);
|
|
||||||
}
|
|
||||||
|
|
||||||
_scrollIntoView({ pageDiv, pageSpot = null, pageNumber = null }) {
|
|
||||||
if (!pageSpot && !this.isInPresentationMode) {
|
|
||||||
const left = pageDiv.offsetLeft + pageDiv.clientLeft;
|
|
||||||
const right = left + pageDiv.clientWidth;
|
|
||||||
const { scrollLeft, clientWidth } = this.container;
|
|
||||||
if (
|
|
||||||
this._isScrollModeHorizontal ||
|
|
||||||
left < scrollLeft ||
|
|
||||||
right > scrollLeft + clientWidth
|
|
||||||
) {
|
|
||||||
pageSpot = { left: 0, top: 0 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super._scrollIntoView({ pageDiv, pageSpot, pageNumber });
|
|
||||||
}
|
|
||||||
|
|
||||||
_getVisiblePages() {
|
|
||||||
if (this.isInPresentationMode) {
|
|
||||||
// The algorithm in `getVisibleElements` doesn't work in all browsers and
|
|
||||||
// configurations (e.g. Chrome) when Presentation Mode is active.
|
|
||||||
return this._getCurrentVisiblePage();
|
|
||||||
}
|
|
||||||
return super._getVisiblePages();
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateHelper(visiblePages) {
|
|
||||||
if (this.isInPresentationMode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let currentId = this._currentPageNumber;
|
|
||||||
let stillFullyVisible = false;
|
|
||||||
|
|
||||||
for (const page of visiblePages) {
|
|
||||||
if (page.percent < 100) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
page.id === currentId &&
|
|
||||||
this._scrollMode === ScrollMode.VERTICAL &&
|
|
||||||
this._spreadMode === SpreadMode.NONE
|
|
||||||
) {
|
|
||||||
stillFullyVisible = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!stillFullyVisible) {
|
|
||||||
currentId = visiblePages[0].id;
|
|
||||||
}
|
|
||||||
this._setCurrentPageNumber(currentId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { PDFViewer };
|
export { PDFViewer };
|
||||||
|
|
|
@ -93,6 +93,12 @@ class SecondaryToolbar {
|
||||||
eventDetails: { tool: CursorTool.HAND },
|
eventDetails: { tool: CursorTool.HAND },
|
||||||
close: true,
|
close: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
element: options.scrollPageButton,
|
||||||
|
eventName: "switchscrollmode",
|
||||||
|
eventDetails: { mode: ScrollMode.PAGE },
|
||||||
|
close: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
element: options.scrollVerticalButton,
|
element: options.scrollVerticalButton,
|
||||||
eventName: "switchscrollmode",
|
eventName: "switchscrollmode",
|
||||||
|
@ -247,6 +253,10 @@ class SecondaryToolbar {
|
||||||
|
|
||||||
_bindScrollModeListener(buttons) {
|
_bindScrollModeListener(buttons) {
|
||||||
function scrollModeChanged({ mode }) {
|
function scrollModeChanged({ mode }) {
|
||||||
|
buttons.scrollPageButton.classList.toggle(
|
||||||
|
"toggled",
|
||||||
|
mode === ScrollMode.PAGE
|
||||||
|
);
|
||||||
buttons.scrollVerticalButton.classList.toggle(
|
buttons.scrollVerticalButton.classList.toggle(
|
||||||
"toggled",
|
"toggled",
|
||||||
mode === ScrollMode.VERTICAL
|
mode === ScrollMode.VERTICAL
|
||||||
|
|
|
@ -57,6 +57,7 @@ const ScrollMode = {
|
||||||
VERTICAL: 0, // Default value.
|
VERTICAL: 0, // Default value.
|
||||||
HORIZONTAL: 1,
|
HORIZONTAL: 1,
|
||||||
WRAPPED: 2,
|
WRAPPED: 2,
|
||||||
|
PAGE: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SpreadMode = {
|
const SpreadMode = {
|
||||||
|
@ -952,21 +953,32 @@ function getActiveOrFocusedElement() {
|
||||||
* necessary Scroll/Spread modes (since SinglePage, TwoPageLeft,
|
* necessary Scroll/Spread modes (since SinglePage, TwoPageLeft,
|
||||||
* and TwoPageRight all suggests using non-continuous scrolling).
|
* and TwoPageRight all suggests using non-continuous scrolling).
|
||||||
* @param {string} mode - The API PageLayout value.
|
* @param {string} mode - The API PageLayout value.
|
||||||
* @returns {number} A value from {SpreadMode}.
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
function apiPageLayoutToSpreadMode(layout) {
|
function apiPageLayoutToViewerModes(layout) {
|
||||||
|
let scrollMode = ScrollMode.VERTICAL,
|
||||||
|
spreadMode = SpreadMode.NONE;
|
||||||
|
|
||||||
switch (layout) {
|
switch (layout) {
|
||||||
case "SinglePage":
|
case "SinglePage":
|
||||||
|
scrollMode = ScrollMode.PAGE;
|
||||||
|
break;
|
||||||
case "OneColumn":
|
case "OneColumn":
|
||||||
return SpreadMode.NONE;
|
break;
|
||||||
case "TwoColumnLeft":
|
|
||||||
case "TwoPageLeft":
|
case "TwoPageLeft":
|
||||||
return SpreadMode.ODD;
|
scrollMode = ScrollMode.PAGE;
|
||||||
case "TwoColumnRight":
|
/* falls through */
|
||||||
|
case "TwoColumnLeft":
|
||||||
|
spreadMode = SpreadMode.ODD;
|
||||||
|
break;
|
||||||
case "TwoPageRight":
|
case "TwoPageRight":
|
||||||
return SpreadMode.EVEN;
|
scrollMode = ScrollMode.PAGE;
|
||||||
|
/* falls through */
|
||||||
|
case "TwoColumnRight":
|
||||||
|
spreadMode = SpreadMode.EVEN;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return SpreadMode.NONE; // Default value.
|
return { scrollMode, spreadMode };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -995,7 +1007,7 @@ function apiPageModeToSidebarView(mode) {
|
||||||
|
|
||||||
export {
|
export {
|
||||||
animationStarted,
|
animationStarted,
|
||||||
apiPageLayoutToSpreadMode,
|
apiPageLayoutToViewerModes,
|
||||||
apiPageModeToSidebarView,
|
apiPageModeToSidebarView,
|
||||||
approximateFraction,
|
approximateFraction,
|
||||||
AutomationEventBus,
|
AutomationEventBus,
|
||||||
|
|
|
@ -94,6 +94,7 @@
|
||||||
--secondaryToolbarButton-rotateCw-icon: url(images/secondaryToolbarButton-rotateCw.svg);
|
--secondaryToolbarButton-rotateCw-icon: url(images/secondaryToolbarButton-rotateCw.svg);
|
||||||
--secondaryToolbarButton-selectTool-icon: url(images/secondaryToolbarButton-selectTool.svg);
|
--secondaryToolbarButton-selectTool-icon: url(images/secondaryToolbarButton-selectTool.svg);
|
||||||
--secondaryToolbarButton-handTool-icon: url(images/secondaryToolbarButton-handTool.svg);
|
--secondaryToolbarButton-handTool-icon: url(images/secondaryToolbarButton-handTool.svg);
|
||||||
|
--secondaryToolbarButton-scrollPage-icon: url(images/secondaryToolbarButton-scrollPage.svg);
|
||||||
--secondaryToolbarButton-scrollVertical-icon: url(images/secondaryToolbarButton-scrollVertical.svg);
|
--secondaryToolbarButton-scrollVertical-icon: url(images/secondaryToolbarButton-scrollVertical.svg);
|
||||||
--secondaryToolbarButton-scrollHorizontal-icon: url(images/secondaryToolbarButton-scrollHorizontal.svg);
|
--secondaryToolbarButton-scrollHorizontal-icon: url(images/secondaryToolbarButton-scrollHorizontal.svg);
|
||||||
--secondaryToolbarButton-scrollWrapped-icon: url(images/secondaryToolbarButton-scrollWrapped.svg);
|
--secondaryToolbarButton-scrollWrapped-icon: url(images/secondaryToolbarButton-scrollWrapped.svg);
|
||||||
|
@ -1196,6 +1197,11 @@ html[dir="rtl"] .secondaryToolbarButton > span {
|
||||||
mask-image: var(--secondaryToolbarButton-handTool-icon);
|
mask-image: var(--secondaryToolbarButton-handTool-icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.secondaryToolbarButton.scrollPage::before {
|
||||||
|
-webkit-mask-image: var(--secondaryToolbarButton-scrollPage-icon);
|
||||||
|
mask-image: var(--secondaryToolbarButton-scrollPage-icon);
|
||||||
|
}
|
||||||
|
|
||||||
.secondaryToolbarButton.scrollVertical::before {
|
.secondaryToolbarButton.scrollVertical::before {
|
||||||
-webkit-mask-image: var(--secondaryToolbarButton-scrollVertical-icon);
|
-webkit-mask-image: var(--secondaryToolbarButton-scrollVertical-icon);
|
||||||
mask-image: var(--secondaryToolbarButton-scrollVertical-icon);
|
mask-image: var(--secondaryToolbarButton-scrollVertical-icon);
|
||||||
|
|
|
@ -196,31 +196,34 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||||
|
|
||||||
<div class="horizontalToolbarSeparator"></div>
|
<div class="horizontalToolbarSeparator"></div>
|
||||||
|
|
||||||
<button id="scrollVertical" class="secondaryToolbarButton scrollModeButtons scrollVertical toggled" title="Use Vertical Scrolling" tabindex="62" data-l10n-id="scroll_vertical">
|
<button id="scrollPage" class="secondaryToolbarButton scrollModeButtons scrollPage" title="Use Page Scrolling" tabindex="62" data-l10n-id="scroll_page">
|
||||||
|
<span data-l10n-id="scroll_page_label">Page Scrolling</span>
|
||||||
|
</button>
|
||||||
|
<button id="scrollVertical" class="secondaryToolbarButton scrollModeButtons scrollVertical toggled" title="Use Vertical Scrolling" tabindex="63" data-l10n-id="scroll_vertical">
|
||||||
<span data-l10n-id="scroll_vertical_label">Vertical Scrolling</span>
|
<span data-l10n-id="scroll_vertical_label">Vertical Scrolling</span>
|
||||||
</button>
|
</button>
|
||||||
<button id="scrollHorizontal" class="secondaryToolbarButton scrollModeButtons scrollHorizontal" title="Use Horizontal Scrolling" tabindex="63" data-l10n-id="scroll_horizontal">
|
<button id="scrollHorizontal" class="secondaryToolbarButton scrollModeButtons scrollHorizontal" title="Use Horizontal Scrolling" tabindex="64" data-l10n-id="scroll_horizontal">
|
||||||
<span data-l10n-id="scroll_horizontal_label">Horizontal Scrolling</span>
|
<span data-l10n-id="scroll_horizontal_label">Horizontal Scrolling</span>
|
||||||
</button>
|
</button>
|
||||||
<button id="scrollWrapped" class="secondaryToolbarButton scrollModeButtons scrollWrapped" title="Use Wrapped Scrolling" tabindex="64" data-l10n-id="scroll_wrapped">
|
<button id="scrollWrapped" class="secondaryToolbarButton scrollModeButtons scrollWrapped" title="Use Wrapped Scrolling" tabindex="65" data-l10n-id="scroll_wrapped">
|
||||||
<span data-l10n-id="scroll_wrapped_label">Wrapped Scrolling</span>
|
<span data-l10n-id="scroll_wrapped_label">Wrapped Scrolling</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="horizontalToolbarSeparator scrollModeButtons"></div>
|
<div class="horizontalToolbarSeparator scrollModeButtons"></div>
|
||||||
|
|
||||||
<button id="spreadNone" class="secondaryToolbarButton spreadModeButtons spreadNone toggled" title="Do not join page spreads" tabindex="65" data-l10n-id="spread_none">
|
<button id="spreadNone" class="secondaryToolbarButton spreadModeButtons spreadNone toggled" title="Do not join page spreads" tabindex="66" data-l10n-id="spread_none">
|
||||||
<span data-l10n-id="spread_none_label">No Spreads</span>
|
<span data-l10n-id="spread_none_label">No Spreads</span>
|
||||||
</button>
|
</button>
|
||||||
<button id="spreadOdd" class="secondaryToolbarButton spreadModeButtons spreadOdd" title="Join page spreads starting with odd-numbered pages" tabindex="66" data-l10n-id="spread_odd">
|
<button id="spreadOdd" class="secondaryToolbarButton spreadModeButtons spreadOdd" title="Join page spreads starting with odd-numbered pages" tabindex="67" data-l10n-id="spread_odd">
|
||||||
<span data-l10n-id="spread_odd_label">Odd Spreads</span>
|
<span data-l10n-id="spread_odd_label">Odd Spreads</span>
|
||||||
</button>
|
</button>
|
||||||
<button id="spreadEven" class="secondaryToolbarButton spreadModeButtons spreadEven" title="Join page spreads starting with even-numbered pages" tabindex="67" data-l10n-id="spread_even">
|
<button id="spreadEven" class="secondaryToolbarButton spreadModeButtons spreadEven" title="Join page spreads starting with even-numbered pages" tabindex="68" data-l10n-id="spread_even">
|
||||||
<span data-l10n-id="spread_even_label">Even Spreads</span>
|
<span data-l10n-id="spread_even_label">Even Spreads</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="horizontalToolbarSeparator spreadModeButtons"></div>
|
<div class="horizontalToolbarSeparator spreadModeButtons"></div>
|
||||||
|
|
||||||
<button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="68" data-l10n-id="document_properties">
|
<button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="69" data-l10n-id="document_properties">
|
||||||
<span data-l10n-id="document_properties_label">Document Properties…</span>
|
<span data-l10n-id="document_properties_label">Document Properties…</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -114,6 +114,7 @@ function getViewerConfiguration() {
|
||||||
pageRotateCcwButton: document.getElementById("pageRotateCcw"),
|
pageRotateCcwButton: document.getElementById("pageRotateCcw"),
|
||||||
cursorSelectToolButton: document.getElementById("cursorSelectTool"),
|
cursorSelectToolButton: document.getElementById("cursorSelectTool"),
|
||||||
cursorHandToolButton: document.getElementById("cursorHandTool"),
|
cursorHandToolButton: document.getElementById("cursorHandTool"),
|
||||||
|
scrollPageButton: document.getElementById("scrollPage"),
|
||||||
scrollVerticalButton: document.getElementById("scrollVertical"),
|
scrollVerticalButton: document.getElementById("scrollVertical"),
|
||||||
scrollHorizontalButton: document.getElementById("scrollHorizontal"),
|
scrollHorizontalButton: document.getElementById("scrollHorizontal"),
|
||||||
scrollWrappedButton: document.getElementById("scrollWrapped"),
|
scrollWrappedButton: document.getElementById("scrollWrapped"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue