Re-factor SimpleLinkService to extend PDFLinkService

Rather than having to maintain a dummy `IPDFLinkService` implementation, we can simply let it extend the primary `PDFLinkService` class instead.
Note how *some* methods already checked for an active PDF document, and those checks only needed to be used consistently throughout `PDFLinkService` in order for this to work.
This commit is contained in:
Jonas Jenwald 2024-04-26 12:32:46 +02:00
parent 90d4b9c2c0
commit 8c3d571939

View File

@ -28,57 +28,6 @@ const LinkTarget = {
TOP: 4, TOP: 4,
}; };
/**
* @typedef {Object} ExternalLinkParameters
* @property {string} url - An absolute URL.
* @property {LinkTarget} [target] - The link target. The default value is
* `LinkTarget.NONE`.
* @property {string} [rel] - The link relationship. The default value is
* `DEFAULT_LINK_REL`.
* @property {boolean} [enabled] - Whether the link should be enabled. The
* default value is true.
*/
/**
* Adds various attributes (href, title, target, rel) to hyperlinks.
* @param {HTMLAnchorElement} link - The link element.
* @param {ExternalLinkParameters} params
*/
function addLinkAttributes(link, { url, target, rel, enabled = true } = {}) {
if (!url || typeof url !== "string") {
throw new Error('A valid "url" parameter must provided.');
}
if (enabled) {
link.href = link.title = url;
} else {
link.href = "";
link.title = `Disabled: ${url}`;
link.onclick = () => false;
}
let targetStr = ""; // LinkTarget.NONE
switch (target) {
case LinkTarget.NONE:
break;
case LinkTarget.SELF:
targetStr = "_self";
break;
case LinkTarget.BLANK:
targetStr = "_blank";
break;
case LinkTarget.PARENT:
targetStr = "_parent";
break;
case LinkTarget.TOP:
targetStr = "_top";
break;
}
link.target = targetStr;
link.rel = typeof rel === "string" ? rel : DEFAULT_LINK_REL;
}
/** /**
* @typedef {Object} PDFLinkServiceOptions * @typedef {Object} PDFLinkServiceOptions
* @property {EventBus} eventBus - The application event bus. * @property {EventBus} eventBus - The application event bus.
@ -98,6 +47,8 @@ function addLinkAttributes(link, { url, target, rel, enabled = true } = {}) {
* @implements {IPDFLinkService} * @implements {IPDFLinkService}
*/ */
class PDFLinkService { class PDFLinkService {
externalLinkEnabled = true;
#pagesRefCache = new Map(); #pagesRefCache = new Map();
/** /**
@ -112,7 +63,6 @@ class PDFLinkService {
this.eventBus = eventBus; this.eventBus = eventBus;
this.externalLinkTarget = externalLinkTarget; this.externalLinkTarget = externalLinkTarget;
this.externalLinkRel = externalLinkRel; this.externalLinkRel = externalLinkRel;
this.externalLinkEnabled = true;
this._ignoreDestinationZoom = ignoreDestinationZoom; this._ignoreDestinationZoom = ignoreDestinationZoom;
this.baseUrl = null; this.baseUrl = null;
@ -146,35 +96,39 @@ class PDFLinkService {
* @type {number} * @type {number}
*/ */
get page() { get page() {
return this.pdfViewer.currentPageNumber; return this.pdfDocument ? this.pdfViewer.currentPageNumber : 1;
} }
/** /**
* @param {number} value * @param {number} value
*/ */
set page(value) { set page(value) {
this.pdfViewer.currentPageNumber = value; if (this.pdfDocument) {
this.pdfViewer.currentPageNumber = value;
}
} }
/** /**
* @type {number} * @type {number}
*/ */
get rotation() { get rotation() {
return this.pdfViewer.pagesRotation; return this.pdfDocument ? this.pdfViewer.pagesRotation : 0;
} }
/** /**
* @param {number} value * @param {number} value
*/ */
set rotation(value) { set rotation(value) {
this.pdfViewer.pagesRotation = value; if (this.pdfDocument) {
this.pdfViewer.pagesRotation = value;
}
} }
/** /**
* @type {boolean} * @type {boolean}
*/ */
get isInPresentationMode() { get isInPresentationMode() {
return this.pdfViewer.isInPresentationMode; return this.pdfDocument ? this.pdfViewer.isInPresentationMode : false;
} }
#goToDestinationHelper(rawDest, namedDest = null, explicitDest) { #goToDestinationHelper(rawDest, namedDest = null, explicitDest) {
@ -294,18 +248,46 @@ class PDFLinkService {
} }
/** /**
* Wrapper around the `addLinkAttributes` helper function. * Adds various attributes (href, title, target, rel) to hyperlinks.
* @param {HTMLAnchorElement} link * @param {HTMLAnchorElement} link
* @param {string} url * @param {string} url
* @param {boolean} [newWindow] * @param {boolean} [newWindow]
*/ */
addLinkAttributes(link, url, newWindow = false) { addLinkAttributes(link, url, newWindow = false) {
addLinkAttributes(link, { if (!url || typeof url !== "string") {
url, throw new Error('A valid "url" parameter must provided.');
target: newWindow ? LinkTarget.BLANK : this.externalLinkTarget, }
rel: this.externalLinkRel, const target = newWindow ? LinkTarget.BLANK : this.externalLinkTarget,
enabled: this.externalLinkEnabled, rel = this.externalLinkRel;
});
if (this.externalLinkEnabled) {
link.href = link.title = url;
} else {
link.href = "";
link.title = `Disabled: ${url}`;
link.onclick = () => false;
}
let targetStr = ""; // LinkTarget.NONE
switch (target) {
case LinkTarget.NONE:
break;
case LinkTarget.SELF:
targetStr = "_self";
break;
case LinkTarget.BLANK:
targetStr = "_blank";
break;
case LinkTarget.PARENT:
targetStr = "_parent";
break;
case LinkTarget.TOP:
targetStr = "_top";
break;
}
link.target = targetStr;
link.rel = typeof rel === "string" ? rel : DEFAULT_LINK_REL;
} }
/** /**
@ -467,6 +449,9 @@ class PDFLinkService {
* @param {string} action * @param {string} action
*/ */
executeNamedAction(action) { executeNamedAction(action) {
if (!this.pdfDocument) {
return;
}
// See PDF reference, table 8.45 - Named action // See PDF reference, table 8.45 - Named action
switch (action) { switch (action) {
case "GoBack": case "GoBack":
@ -507,9 +492,11 @@ class PDFLinkService {
* @param {Object} action * @param {Object} action
*/ */
async executeSetOCGState(action) { async executeSetOCGState(action) {
const pdfDocument = this.pdfDocument; if (!this.pdfDocument) {
const optionalContentConfig = return;
await this.pdfViewer.optionalContentConfigPromise; }
const pdfDocument = this.pdfDocument,
optionalContentConfig = await this.pdfViewer.optionalContentConfigPromise;
if (pdfDocument !== this.pdfDocument) { if (pdfDocument !== this.pdfDocument) {
return; // The document was closed while the optional content resolved. return; // The document was closed while the optional content resolved.
@ -603,98 +590,8 @@ class PDFLinkService {
/** /**
* @implements {IPDFLinkService} * @implements {IPDFLinkService}
*/ */
class SimpleLinkService { class SimpleLinkService extends PDFLinkService {
constructor() { setDocument(pdfDocument, baseUrl = null) {}
this.externalLinkEnabled = true;
}
/**
* @type {number}
*/
get pagesCount() {
return 0;
}
/**
* @type {number}
*/
get page() {
return 0;
}
/**
* @param {number} value
*/
set page(value) {}
/**
* @type {number}
*/
get rotation() {
return 0;
}
/**
* @param {number} value
*/
set rotation(value) {}
/**
* @type {boolean}
*/
get isInPresentationMode() {
return false;
}
/**
* @param {string|Array} dest - The named, or explicit, PDF destination.
*/
async goToDestination(dest) {}
/**
* @param {number|string} val - The page number, or page label.
*/
goToPage(val) {}
/**
* @param {HTMLAnchorElement} link
* @param {string} url
* @param {boolean} [newWindow]
*/
addLinkAttributes(link, url, newWindow = false) {
addLinkAttributes(link, { url, enabled: this.externalLinkEnabled });
}
/**
* @param dest - The PDF destination object.
* @returns {string} The hyperlink to the PDF object.
*/
getDestinationHash(dest) {
return "#";
}
/**
* @param hash - The PDF parameters/hash.
* @returns {string} The hyperlink to the PDF object.
*/
getAnchorUrl(hash) {
return "#";
}
/**
* @param {string} hash
*/
setHash(hash) {}
/**
* @param {string} action
*/
executeNamedAction(action) {}
/**
* @param {Object} action
*/
executeSetOCGState(action) {}
/** /**
* @param {number} pageNum - page number. * @param {number} pageNum - page number.