Merge pull request #6945 from Snuffleupagus/page-labels-viewer
Add support for PageLabels in the viewer (issue 6902, bug 793632)
This commit is contained in:
commit
e9c63a2b32
@ -89,6 +89,10 @@
|
||||
],
|
||||
"default": 0
|
||||
},
|
||||
"disablePageLabels": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"disableTelemetry": {
|
||||
"title": "Disable telemetry",
|
||||
"type": "boolean",
|
||||
|
@ -18,12 +18,15 @@ previous_label=Previous
|
||||
next.title=Next Page
|
||||
next_label=Next
|
||||
|
||||
# LOCALIZATION NOTE (page_label, page_of):
|
||||
# These strings are concatenated to form the "Page: X of Y" string.
|
||||
# Do not translate "{{pageCount}}", it will be substituted with a number
|
||||
# representing the total number of pages.
|
||||
page_label=Page:
|
||||
page_of=of {{pageCount}}
|
||||
# LOCALIZATION NOTE (page.title): The tooltip for the pageNumber input.
|
||||
page.title=Page
|
||||
# LOCALIZATION NOTE (of_pages): "{{pagesCount}}" will be replaced by a number
|
||||
# representing the total number of pages in the document.
|
||||
of_pages=of {{pagesCount}}
|
||||
# LOCALIZATION NOTE (page_of_pages): "{{pageNumber}}" and "{{pagesCount}}"
|
||||
# will be replaced by a number representing the currently visible page,
|
||||
# respectively a number representing the total number of pages in the document.
|
||||
+page_of_pages=({{pageNumber}} of {{pagesCount}})
|
||||
|
||||
zoom_out.title=Zoom Out
|
||||
zoom_out_label=Zoom Out
|
||||
|
@ -18,12 +18,15 @@ previous_label=Föregående
|
||||
next.title=Nästa sida
|
||||
next_label=Nästa
|
||||
|
||||
# LOCALIZATION NOTE (page_label, page_of):
|
||||
# These strings are concatenated to form the "Page: X of Y" string.
|
||||
# Do not translate "{{pageCount}}", it will be substituted with a number
|
||||
# representing the total number of pages.
|
||||
page_label=Sida:
|
||||
page_of=av {{pageCount}}
|
||||
# LOCALIZATION NOTE (page.title): The tooltip for the pageNumber input.
|
||||
page.title=Sida
|
||||
# LOCALIZATION NOTE (of_pages): "{{pagesCount}}" will be replaced by a number
|
||||
# representing the total number of pages in the document.
|
||||
of_pages=av {{pagesCount}}
|
||||
# LOCALIZATION NOTE (page_of_pages): "{{pageNumber}}" and "{{pagesCount}}"
|
||||
# will be replaced by a number representing the currently active visible page,
|
||||
# respectively a number representing the total number of pages in the document.
|
||||
page_of_pages=({{pageNumber}} av {{pagesCount}})
|
||||
|
||||
zoom_out.title=Zooma ut
|
||||
zoom_out_label=Zooma ut
|
||||
|
64
web/app.js
64
web/app.js
@ -178,10 +178,12 @@ var PDFViewerApplication = {
|
||||
preferencePdfBugEnabled: false,
|
||||
preferenceShowPreviousViewOnLoad: true,
|
||||
preferenceDefaultZoomValue: '',
|
||||
preferenceDisablePageLabels: false,
|
||||
isViewerEmbedded: (window.parent !== window),
|
||||
url: '',
|
||||
baseUrl: '',
|
||||
externalServices: DefaultExernalServices,
|
||||
hasPageLabels: false,
|
||||
|
||||
// called once when the document is loaded
|
||||
initialize: function pdfViewInitialize(appConfig) {
|
||||
@ -380,6 +382,9 @@ var PDFViewerApplication = {
|
||||
// before the various viewer components are initialized.
|
||||
self.pdfViewer.renderInteractiveForms = value;
|
||||
}),
|
||||
Preferences.get('disablePageLabels').then(function resolved(value) {
|
||||
self.preferenceDisablePageLabels = value;
|
||||
}),
|
||||
// TODO move more preferences and other async stuff here
|
||||
]).catch(function (reason) { });
|
||||
|
||||
@ -567,6 +572,7 @@ var PDFViewerApplication = {
|
||||
}
|
||||
this.store = null;
|
||||
this.isInitialViewSet = false;
|
||||
this.hasPageLabels = false;
|
||||
|
||||
this.pdfSidebar.reset();
|
||||
this.pdfOutlineViewer.reset();
|
||||
@ -879,7 +885,8 @@ var PDFViewerApplication = {
|
||||
|
||||
this.pageRotation = 0;
|
||||
|
||||
this.pdfThumbnailViewer.setDocument(pdfDocument);
|
||||
var pdfThumbnailViewer = this.pdfThumbnailViewer;
|
||||
pdfThumbnailViewer.setDocument(pdfDocument);
|
||||
|
||||
firstPagePromise.then(function(pdfPage) {
|
||||
downloadedPromise.then(function () {
|
||||
@ -959,6 +966,33 @@ var PDFViewerApplication = {
|
||||
});
|
||||
});
|
||||
|
||||
pdfDocument.getPageLabels().then(function (labels) {
|
||||
if (!labels || self.preferenceDisablePageLabels) {
|
||||
return;
|
||||
}
|
||||
var i = 0, numLabels = labels.length;
|
||||
if (numLabels !== self.pagesCount) {
|
||||
console.error('The number of Page Labels does not match ' +
|
||||
'the number of pages in the document.');
|
||||
return;
|
||||
}
|
||||
// Ignore page labels that correspond to standard page numbering.
|
||||
while (i < numLabels && labels[i] === (i + 1).toString()) {
|
||||
i++;
|
||||
}
|
||||
if (i === numLabels) {
|
||||
return;
|
||||
}
|
||||
|
||||
pdfViewer.setPageLabels(labels);
|
||||
pdfThumbnailViewer.setPageLabels(labels);
|
||||
|
||||
self.hasPageLabels = true;
|
||||
self._updateUIToolbar({
|
||||
resetNumPages: true,
|
||||
});
|
||||
});
|
||||
|
||||
pagesPromise.then(function() {
|
||||
if (self.supportsPrinting) {
|
||||
pdfDocument.getJavaScript().then(function(javaScript) {
|
||||
@ -1186,6 +1220,7 @@ var PDFViewerApplication = {
|
||||
/**
|
||||
* @typedef UpdateUIToolbarParameters
|
||||
* @property {number} pageNumber
|
||||
* @property {string} pageLabel
|
||||
* @property {string} scaleValue
|
||||
* @property {number} scale
|
||||
* @property {boolean} resetNumPages
|
||||
@ -1226,11 +1261,25 @@ var PDFViewerApplication = {
|
||||
var pagesCount = this.pagesCount;
|
||||
|
||||
if (resetNumPages) {
|
||||
toolbarConfig.numPages.textContent =
|
||||
mozL10n.get('page_of', { pageCount: pagesCount }, 'of {{pageCount}}');
|
||||
if (this.hasPageLabels) {
|
||||
toolbarConfig.pageNumber.type = 'text';
|
||||
} else {
|
||||
toolbarConfig.pageNumber.type = 'number';
|
||||
toolbarConfig.numPages.textContent = mozL10n.get('of_pages',
|
||||
{ pagesCount: pagesCount }, 'of {{pagesCount}}');
|
||||
}
|
||||
toolbarConfig.pageNumber.max = pagesCount;
|
||||
}
|
||||
toolbarConfig.pageNumber.value = pageNumber;
|
||||
|
||||
if (this.hasPageLabels) {
|
||||
toolbarConfig.pageNumber.value = params.pageLabel ||
|
||||
this.pdfViewer.currentPageLabel;
|
||||
toolbarConfig.numPages.textContent = mozL10n.get('page_of_pages',
|
||||
{ pageNumber: pageNumber, pagesCount: pagesCount },
|
||||
'({{pageNumber}} of {{pagesCount}})');
|
||||
} else {
|
||||
toolbarConfig.pageNumber.value = pageNumber;
|
||||
}
|
||||
|
||||
toolbarConfig.previous.disabled = (pageNumber <= 1);
|
||||
toolbarConfig.next.disabled = (pageNumber >= pagesCount);
|
||||
@ -1495,11 +1544,13 @@ function webViewerInitialized() {
|
||||
});
|
||||
|
||||
appConfig.toolbar.pageNumber.addEventListener('change', function() {
|
||||
PDFViewerApplication.page = (this.value | 0);
|
||||
var pdfViewer = PDFViewerApplication.pdfViewer;
|
||||
pdfViewer.currentPageLabel = this.value;
|
||||
|
||||
// Ensure that the page number input displays the correct value, even if the
|
||||
// value entered by the user was invalid (e.g. a floating point number).
|
||||
if (this.value !== PDFViewerApplication.page.toString()) {
|
||||
if (this.value !== pdfViewer.currentPageNumber.toString() &&
|
||||
this.value !== pdfViewer.currentPageLabel) {
|
||||
PDFViewerApplication._updateUIToolbar({});
|
||||
}
|
||||
});
|
||||
@ -1930,6 +1981,7 @@ function webViewerPageChanging(e) {
|
||||
|
||||
PDFViewerApplication._updateUIToolbar({
|
||||
pageNumber: page,
|
||||
pageLabel: e.pageLabel,
|
||||
});
|
||||
|
||||
if (PDFViewerApplication.pdfSidebar.isThumbnailViewVisible) {
|
||||
|
@ -13,5 +13,6 @@
|
||||
"useOnlyCssZoom": false,
|
||||
"externalLinkTarget": 0,
|
||||
"enhanceTextSelection": false,
|
||||
"renderInteractiveForms": false
|
||||
"renderInteractiveForms": false,
|
||||
"disablePageLabels": false
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ var PDFPageView = (function PDFPageViewClosure() {
|
||||
|
||||
this.id = id;
|
||||
this.renderingId = 'page' + id;
|
||||
this.pageLabel = null;
|
||||
|
||||
this.rotation = 0;
|
||||
this.scale = scale || DEFAULT_SCALE;
|
||||
@ -554,6 +555,19 @@ var PDFPageView = (function PDFPageViewClosure() {
|
||||
}
|
||||
return promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string|null} label
|
||||
*/
|
||||
setPageLabel: function PDFView_setPageLabel(label) {
|
||||
this.pageLabel = (typeof label === 'string' ? label : null);
|
||||
|
||||
if (this.pageLabel !== null) {
|
||||
this.div.setAttribute('data-page-label', this.pageLabel);
|
||||
} else {
|
||||
this.div.removeAttribute('data-page-label');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return PDFPageView;
|
||||
|
@ -91,6 +91,7 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() {
|
||||
|
||||
this.id = id;
|
||||
this.renderingId = 'thumbnail' + id;
|
||||
this.pageLabel = null;
|
||||
|
||||
this.pdfPage = null;
|
||||
this.rotation = 0;
|
||||
@ -120,6 +121,7 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() {
|
||||
linkService.page = id;
|
||||
return false;
|
||||
};
|
||||
this.anchor = anchor;
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.id = 'thumbnailContainer' + id;
|
||||
@ -247,7 +249,7 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() {
|
||||
}
|
||||
var id = this.renderingId;
|
||||
var className = 'thumbnailImage';
|
||||
var ariaLabel = mozL10n.get('thumb_page_canvas', { page: this.id },
|
||||
var ariaLabel = mozL10n.get('thumb_page_canvas', { page: this.pageId },
|
||||
'Thumbnail of Page {{page}}');
|
||||
|
||||
if (this.disableCanvasToImageConversion) {
|
||||
@ -395,7 +397,32 @@ var PDFThumbnailView = (function PDFThumbnailViewClosure() {
|
||||
ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight,
|
||||
0, 0, canvas.width, canvas.height);
|
||||
this._convertCanvasToImage();
|
||||
}
|
||||
},
|
||||
|
||||
get pageId() {
|
||||
return (this.pageLabel !== null ? this.pageLabel : this.id);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string|null} label
|
||||
*/
|
||||
setPageLabel: function PDFThumbnailView_setPageLabel(label) {
|
||||
this.pageLabel = (typeof label === 'string' ? label : null);
|
||||
|
||||
this.anchor.title = mozL10n.get('thumb_page_title', { page: this.pageId },
|
||||
'Page {{page}}');
|
||||
|
||||
if (this.renderingState !== RenderingStates.FINISHED) {
|
||||
return;
|
||||
}
|
||||
var ariaLabel = mozL10n.get('thumb_page_canvas', { page: this.pageId },
|
||||
'Thumbnail of Page {{page}}');
|
||||
if (this.image) {
|
||||
this.image.setAttribute('aria-label', ariaLabel);
|
||||
} else if (this.disableCanvasToImageConversion && this.canvas) {
|
||||
this.canvas.setAttribute('aria-label', ariaLabel);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return PDFThumbnailView;
|
||||
|
@ -133,6 +133,7 @@ var PDFThumbnailViewer = (function PDFThumbnailViewerClosure() {
|
||||
*/
|
||||
_resetView: function PDFThumbnailViewer_resetView() {
|
||||
this.thumbnails = [];
|
||||
this._pageLabels = null;
|
||||
this._pagesRotation = 0;
|
||||
this._pagesRequests = [];
|
||||
|
||||
@ -179,6 +180,30 @@ var PDFThumbnailViewer = (function PDFThumbnailViewerClosure() {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array|null} labels
|
||||
*/
|
||||
setPageLabels: function PDFThumbnailViewer_setPageLabels(labels) {
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
if (!labels) {
|
||||
this._pageLabels = null;
|
||||
} else if (!(labels instanceof Array &&
|
||||
this.pdfDocument.numPages === labels.length)) {
|
||||
this._pageLabels = null;
|
||||
console.error('PDFThumbnailViewer_setPageLabels: Invalid page labels.');
|
||||
} else {
|
||||
this._pageLabels = labels;
|
||||
}
|
||||
// Update all the `PDFThumbnailView` instances.
|
||||
for (var i = 0, ii = this.thumbnails.length; i < ii; i++) {
|
||||
var thumbnailView = this.thumbnails[i];
|
||||
var label = this._pageLabels && this._pageLabels[i];
|
||||
thumbnailView.setPageLabel(label);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {PDFThumbnailView} thumbView
|
||||
* @returns {PDFPage}
|
||||
|
@ -211,6 +211,7 @@ var PDFViewer = (function pdfViewer() {
|
||||
var arg = {
|
||||
source: this,
|
||||
pageNumber: val,
|
||||
pageLabel: this._pageLabels && this._pageLabels[val - 1],
|
||||
};
|
||||
this._currentPageNumber = val;
|
||||
this.eventBus.dispatch('pagechanging', arg);
|
||||
@ -221,6 +222,28 @@ var PDFViewer = (function pdfViewer() {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {string|null} Returns the current page label,
|
||||
* or `null` if no page labels exist.
|
||||
*/
|
||||
get currentPageLabel() {
|
||||
return this._pageLabels && this._pageLabels[this._currentPageNumber - 1];
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} val - The page label.
|
||||
*/
|
||||
set currentPageLabel(val) {
|
||||
var pageNumber = val | 0; // Fallback page number.
|
||||
if (this._pageLabels) {
|
||||
var i = this._pageLabels.indexOf(val);
|
||||
if (i >= 0) {
|
||||
pageNumber = i + 1;
|
||||
}
|
||||
}
|
||||
this.currentPageNumber = pageNumber;
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
@ -414,11 +437,36 @@ var PDFViewer = (function pdfViewer() {
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array|null} labels
|
||||
*/
|
||||
setPageLabels: function PDFViewer_setPageLabels(labels) {
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
if (!labels) {
|
||||
this._pageLabels = null;
|
||||
} else if (!(labels instanceof Array &&
|
||||
this.pdfDocument.numPages === labels.length)) {
|
||||
this._pageLabels = null;
|
||||
console.error('PDFViewer_setPageLabels: Invalid page labels.');
|
||||
} else {
|
||||
this._pageLabels = labels;
|
||||
}
|
||||
// Update all the `PDFPageView` instances.
|
||||
for (var i = 0, ii = this._pages.length; i < ii; i++) {
|
||||
var pageView = this._pages[i];
|
||||
var label = this._pageLabels && this._pageLabels[i];
|
||||
pageView.setPageLabel(label);
|
||||
}
|
||||
},
|
||||
|
||||
_resetView: function () {
|
||||
this._pages = [];
|
||||
this._currentPageNumber = 1;
|
||||
this._currentScale = UNKNOWN_SCALE;
|
||||
this._currentScaleValue = null;
|
||||
this._pageLabels = null;
|
||||
this._buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE);
|
||||
this._location = null;
|
||||
this._pagesRotation = 0;
|
||||
|
@ -1939,7 +1939,7 @@ html[dir='rtl'] #documentPropertiesOverlay .row > * {
|
||||
}
|
||||
|
||||
@media all and (max-width: 510px) {
|
||||
#scaleSelectContainer, #pageNumberLabel {
|
||||
#scaleSelectContainer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
@ -194,8 +194,7 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||
<span data-l10n-id="next_label">Next</span>
|
||||
</button>
|
||||
</div>
|
||||
<label id="pageNumberLabel" class="toolbarLabel" for="pageNumber" data-l10n-id="page_label">Page: </label>
|
||||
<input type="number" id="pageNumber" class="toolbarField pageNumber" value="1" size="4" min="1" tabindex="15">
|
||||
<input type="number" id="pageNumber" class="toolbarField pageNumber" title="Page" value="1" size="4" min="1" tabindex="15" data-l10n-id="page">
|
||||
<span id="numPages" class="toolbarLabel"></span>
|
||||
</div>
|
||||
<div id="toolbarViewerRight">
|
||||
@ -236,7 +235,7 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||
</button>
|
||||
</div>
|
||||
<span id="scaleSelectContainer" class="dropdownToolbarButton">
|
||||
<select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="zoom">
|
||||
<select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="zoom">
|
||||
<option id="pageAutoOption" title="" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
|
||||
<option id="pageActualOption" title="" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
|
||||
<option id="pageFitOption" title="" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option>
|
||||
|
Loading…
Reference in New Issue
Block a user