Printing Error Ionic iOS

I’m getting the following error when clicking the Print button from the Print Modal in the setWatermarkOptions method:

"TypeError: n is not a function. (In ‘n()’, ‘n’ is an instance of Object)

gs — webviewer-ui.min.js:33259
(anonymous function) — webviewerui.min.js:60875
promiseReactionJob"

The error is occurring on the line highlighted below from webviewer-ui.min

})), Pj(Tj(e), “closePrintModal”, (function() {
e.setState({
count: -1
}),
e.props.closeElement(“printModal”)
})), Pj(Tj(e), “setWatermarkModalVisibility”, (function(t) {
e.setState({
isWatermarkModalVisible: t
})
})), Pj(Tj(e), “setWatermarkModalOption”, (function(t) {
e.setState({
watermarkModalOption: t
})
})), e.allPages = u.a.createRef(), e.currentPage = u.a.createRef(), e.customPages = u.a.createRef(), e.customInput = u.a.createRef(), e.includeComments = u.a.createRef(), e.pendingCanvases = [], e.state = {
allowWatermarkModal: !1,
count: -1,
pagesToPrint: [],
isWatermarkModalVisible: !1,
watermarkModalOption: null,
existingWatermarks: null,
includeAnnotations: !0,
includeComments: !1
}, e

I don’t get this error when running in the browser. The error has only started to happen since moving to the latest UI. My forked webviewer-ui repository is at https://github.com/daveywc/webviewer-ui. Diego has access to it.

Kind regards,

David

Hi David,

Thanks for contacting us regarding WebViewer, and sorry for the delay for approving the posts.

I have a few questions regarding this error:

  1. I’m able to access your fork, and I’m wondering if the master branch is where you are seeing this error?

  2. Just to confirm if the highlighted line is actually what causes the issue. I’m asking because I didn’t see anything related to the “n()” function call. I looked at the code and it doesn’t looks like this line is getting called when the Print button is clicked.

  3. You mentioned this issue happens in the latest UI, I’m wondering if you can reproduce it using the legacy UI? The legacy UI can be found in branches starting with legacy. For example, “legacy/7.1” is the legacy UI used for WebViewer 7.1

  4. Are there any ways you can share to us so that we can reproduce?

Best Regards,
Zhijie Zhang
Software developer
PDFTron Systems Inc.

Hi Zhilje,

  1. I’m able to access your fork, and I’m wondering if the master branch is where you are seeing this error? Yes it is the master branch.

  2. Just to confirm if the highlighted line is actually what causes the issue. I’m asking because I didn’t see anything related to the “n()” function call. I looked at the code and it doesn’t looks like this line is getting called when the Print button is clicked. I’ve tried to replicate the error again today after synching my fork with your master branch and I am no longer getting the error message. In the developer console I do see the following message “Canvas area exceeds the maximum limit (width * height > 16777216).”. This seems to be the source of the error. I will provide some more details below on what I am trying to do below.

  3. You mentioned this issue happens in the latest UI, I’m wondering if you can reproduce it using the legacy UI? The legacy UI can be found in branches starting with legacy. For example, “legacy/7.1” is the legacy UI used for WebViewer 7.1. This turned out to be a very good question… see below.

  4. Are there any ways you can share to us so that we can reproduce? In order to reproduce the problem I could provide you with a copy of an ipa that you can run on an iOS device. In order to do that I would need to know your Device ID (UDID) before I build the ipa file. Or we can do a screen sharing session and I can show you my code. This may be easier.

I am trying to implement printing on an iOS device in an Ionic App as per: https://groups.google.com/g/pdfnet-webviewer/c/0pyZ8l8GluA/m/GSzmrJDsCwAJ. When I review this thread it doesn’t look like we ever got a solution that worked completely.

The structure of your code is different in the latest UI. What I’ve done is to Replace printPages in components\helpers\print.js with the following (in the old UI this replacement was done in components/PrintModal\PrintModal.js):

export const printPages = pages => {
let isCordovaPrinter = window.parent.cordova && window.parent.cordova.plugins.printer;
let printHandler;
if (isCordovaPrinter) { /
printHandler = document.createElement(‘div’);
printHandler.style.display = ‘block’;
printHandler.style.height = ‘100%’;
} else {
printHandler = document.getElementById(‘print-handler’);
printHandler.innerHTML = ‘’;
}

const fragment = document.createDocumentFragment();
pages.forEach((page, index) => { // error Canvas area exceeds the maximum limit…". happens in this code block
if (isCordovaPrinter) {
page.style.display = ‘block’;
page.style.maxWidth = ‘100%’;
page.style.maxHeight = ‘100%’;
page.style.width = ‘100%’;
page.style.height = ‘100%’;
page.style.objectFit = ‘contain’;
if (index > 0) {
page.style.pageBreakAfter = ‘always’;
}
}
fragment.appendChild(page);
});

printHandler.appendChild(fragment);

if (isCordovaPrinter) {
const html = document.createElement(‘html’);
html.style.width = ‘100%’;
html.style.height = ‘100%’;
html.style.padding = 0;
html.style.margin = 0;
const body = document.createElement(‘body’);
body.style.width = ‘100%’;
body.style.height = ‘100%’;
body.style.padding = 0;
body.style.margin = 0;
body.appendChild(printHandler);
html.appendChild(body);
window.parent.cordova.plugins.printer.print(html, ‘Document.html’);
} else if (isSafari && !isChromeOniOS) {
// Print for Safari browser. Makes Safari 11 consistently work.
document.execCommand(‘print’);
} else {
window.print();
}
};

So I guess what I am really after is a solution that will work for printing on iOS within an Ionic application.

Note that if I remove my code to use the Cordova printer plugin i.e. just use Print.js as it is, then the process just fails silently when it gets to:

export const printPages = pages => {
const printHandler = document.getElementById(‘print-handler’);
printHandler.innerHTML = ‘’;

Kind regards,

David

Hi David,

Thanks for sharing detailed information.

I went through the forum post that you linked and it seems that Justin helped you and you were able to get the printing work(though not perfectly) on iOS within an Ionic application in the legacy UI.

One thing I would like to mention is that we’ve changed how we branching in the webviewer-ui repository. The master branch is actually the experimental branch now, which means it’s not safe to use in the production. The same applies to the legacy/master branch, which is the experimental branch for the legacy UI. Instead of building on the master(or legacy/master) branch I would recommend you modifying the stable branches. The stable branches are branches that only have numbers and dots in the names. For example, 7.1 is the stable branch of the new UI in WebViewer version 7.1, and legacy/7.1 is the stable branch of the legacy UI in WebViewer verion 7.1.

Since the code was working in the legacy UI in an older WebViewer version, I think the first step is to verify if the same cordova printing code works in the legacy UI in the latest WebViewer version. The latest stable legacy UI branch is legacy/7.1.

In the new UI the structure of the PrintModal.js has changed. I believe we moved some functions to another file, but I don’t think we’ve changed how the code works. If the code works in legacy/7.1 then I think it should also work in 7.1 if ported carefully.

You mentioned the “Canvas area exceeds the maximum limit (width * height > 16777216)” error in the console, I’m wondering if you’ve seen this error in the legacy UI before? I googled this error and it looks like it hitting the physical memory limitation for an iOS device. I think what Justin suggested in another post still applies. We need to limit the number of pages that can be printed.

Best Regards,
Zhijie Zhang
Software Developer
PDFTron Systems Inc.

Hi Zhijie,

I will stop building against the master branch from now on. I will also try what you have suggested in regards to the legacy branch and let you know how I go.

When did the change to make master experimental happen? Was that communicated to those of us who have been building a custom UI from master for some time?

Kind regards,

David

I’m getting the same error now using either the 7.1 or the legacy/7.1 branch: Canvas area exceeds the maximum limit (width * height > 16777216).

On the legacy/7.1 branch it never even makes it into the printPages method. If I pick “Current” then it seems to just fail in createPagesAndPrint when it gets to Promise.all(creatingPages). I’m just working with a small 2 page document, when I’m getting this error. So limiting the pages to be printed isn’t going to help.

createPagesAndPrint = e => {
e.preventDefault();

if (this.state.pagesToPrint.length < 1) {
return;
}

this.setState({ count: 0 });
this.setPrintQuality();

if (this.state.allowWatermarkModal) {
core.setWatermark(this.state.watermarkModalOption);
} else {
core.setWatermark(this.state.existingWatermarks);
}

const creatingPages = this.creatingPages();
Promise.all(creatingPages). // FAILS HERE
.then(pages => {
this.printPages(pages);
this.resetPrintQuality();
})
.catch(e => {
console.error(e);
this.setState({ count: -1 });
});
};

If I pick to print a specific page then it makes it past there but eventually just crashes the app completely.

Do you have any other suggestions?

Kind regards,

David

Hi David,

Thanks for sharing the information you have so far.

I’d like to confirm that the error message Canvas area exceeds the maximum limit (width * height > 16777216) doesn’t occur in the older WebViewer UI version, and only in 7.1(and legacy/7.1)?

The error sounds a bit strange. If I’m understanding correctly Width * Height > 16777216 indicates that the canvas area is at least 16777216, which is very big.

To help us troubleshoot further, do you think it’s relatively easy for you to provide us with a simple Ionic application(perhaps with some instructions) that we can install on our iPad and see the error?

Thanks,
Zhijie Zhang
Software Developer
PDFTron Systems Inc.

Hi Zhijie,

Could you send me the UDID from the iPad that you want to install on. Then I can do an adhoc build that will work on that device. You will then need to debug in Safari using the dev tools. I will send some instructions with the link to download the app.

Kind regards,

David

Hi David,

I’m not very sure if UDID is something that I can share publicly, so I set an email to you including it.

Thanks,
Zhijie Zhang
Software Developer
PDFTron Systems Inc.

Hi Zhiljie,

You can download a build that should work on your iPhone from: https://hsfilesgeneral.blob.core.windows.net/general/docsontapv2a-master-724cb2-development.ipa. I just usually drag and drop onto the device in iTunes to install.

I can also give you access to the GitHub repositories for the app and for my custom build of WebViewerUI if you give me an email address to use. Diego Felix already has access to both.

harbour-software/docsontapv2a: Upgrading Docs On Tap V2 to Ionic 4/5 and Capacitor (github.com)

Kind regards,

David

When first run you need to enter demo@harboursoftware.com.au as the email address to get a verification code. The code will be auto populated for you.

Also… if you do happen to be looking at the repository for our app (docsontapv2a) then be aware that I’ve pushed up a change to hide the print button until we can get this fixed - only did that a couple of hours ago. I had to make an iOS/Android release to fix another issue. Couldn’t wait any longer, so just decided to temporarily hide the print button.

Hi David,

Thanks for sharing the build. I’m able to install it on my iPhone and run it.

I’m able to see the canvas memory limit warning in the Safari console when I hit the print button.

I noticed that the print quality has been set to High in the print modal. High print quality will result in a canvas that has 3 times bigger size than the one in the Normal print quality.
Strangely when I tried to set print quality to Normal and then print, the app just closed. I’m not very sure why printing in Normal quality will cause the app to close. Do you have any ideas about this?

If this can be somehow fixed then you could try printing in Normal quality and see if you still see the canvas memory limit warning.

I’m not sure if what I’ve been doing is the best way to debug the issue. Do you know how I can build your custom UI in a very very basic Ionic application to reproduce the issue? Ideally I would need to be able to change the source code, rebuild it, and then see how things work. I guess as the first step I would need to access your repository. I will send my email to you.

Thanks,
Zhijie Zhang

Software Developer
PDFTron Systems Inc.

Hi David,

I just want to follow up to see if having printing quality to be Normal is an option to you? As I’ve mentioned above that High quality will make a canvas that’s 3 times bigger than a Normal quality canvas, which is likely the reason why we see the warning in Safari.

Thanks,
Zhijie Zhang
Software Developer
PDFTron Systems Inc.

Hi Zhijie,

I cannot remember the reason that we are setting the print quality to high. I think that there were quality issues in the printing at some stage. Anyway I’ve modified our code to leave the print quality at normal on mobile platforms. That seems to have fixed the canvas size issue. I’m trying to debug further and work out why it still isn’t printing.

Kind regards,

David

So after a day of debugging I’ve determined that the printing does not work with the method used to convert the document pages into html using documentFragment. I think it is the same error mentioned here: https://github.com/katzer/cordova-plugin-printer/issues/261

By trial and error I worked out that following 2 attempts to print work:

window.parent.cordova.plugins.printer.print(‘

Hello World!

’, printOptions);
window.parent.cordova.plugins.printer.print(“base64://iVBORw0KGgoAAAANSUhEUgAAAxkAAARiCAYAAADIoTpzAAAAAXNSR0IArs…”, printOptions);

But this doesn’t work: window.parent.cordova.plugins.printer.print(html, printOptions);

The base64:// option that worked was the exact same base64 string that ended up in the “html” variable that didn’t work. It was just attempting to print a single page document. It basically crashes the app.

I’ve updated the code in my webviewer-ui fork: https://github.com/harbour-software/webviewer-ui with the above 3 options (2 that work, one that doesn’t).

Do you have any ideas on how else to handle the output that needs to be printed.

Kind regards,

David

Hi David,

Thanks for the detailed information.

I just wanted to let you know that I was just back from vacation and am still catching up on some other stuff. I should have some time tomorrow to take a look at this.

Thanks,
Zhijie Zhang
Software Developer
PDFTron Systems Inc.

Hi David,

Sorry for the delay in the reply. Unfortunately I’ve underestimated things on my end and I wasn’t able to look into the issue in previous days. I think I’ve caught up on them. I will post again when I have more information regarding this issue.

Thanks,
Zhijie Zhang
Software Developer
PDFTron Systems Inc.

Hi Zhijie,

Thanks for the update.

David

Hi David,

I just want to mention that I haven’t forgot about this issue, and would like to give you an update on the status.
I’m currently trying to deploy a very basic Cordova app on my iPhone that integrates with WebViewer. However, it turns out to be much difficult than I thought. I’m pretty new to Cordova so there might be obvious things I’ve missed. I’m going to post what I have in case you would like to help.

I’m able to deploy the app on my iPhone but when I open the app I see the following error message:

“Cross origin requests are only supported for HTTP.”
“Fetch API cannot load file:///private/var/containers/Bundle/Application/4B38A83A-A51B-478C-8AA0-953D22FE5C92/WebViewerCordovaSample.app/www/js/lib/ui/i18n/translation-en.json due to access control checks.”

I think the errors kind of make sense to me as the app is on my iPhone and doing HTTP request to local files isn’t generally allowed due to security concerns.

Unfortunately googling doesn’t help resolve this issue. The closest post I can found is https://stackoverflow.com/questions/36451720/cordova-ios-cross-origin-requests-are-only-supported-for-http. But after installing those plugins mentioned in the top voted answer “cordova build ios” will throw a compile error. Another answer mentions “wkwebview-engine-localhost” but the repo link is a 404.

Since the issue seems to be requesting local files, I decided to upload the WebViewer build files to our S3, and change the path option in the WebViewer constructor to point to https://pdftron.s3.amazonaws.com/custom/ID-zJWLuhTffd3c/cordova-debug. What I found after doing this is that when I open the app on my iPhone it will open Safari automatically and then direct to a pdftron URL. This is weird and I’m not sure what happened.

I think what I’m going to do next is to take a look at your app and see what configurations you have, and see if I can use them. If that doesn’t work out I will start from a even more basic app(which doesn’t integrate with WebViewer) and see if I can get it work first.

Thanks,
Zhijie Zhang
Software Developer
PDFTron Systems Inc.