Printing on iPad in Ionic App

214 views
Skip to first unread message

David Compton

unread,
Mar 12, 2018, 1:01:00 PM3/12/18
to PDFTron WebViewer
Should the printing work in the mobile viewer on an iPad in an Ionic app?  Currently what happens is that the Print dialog comes up, then when you click Print  it goes through "Preparing page: nn/nn" .  But nothing else happens.

Kind regards,

David

Matt Parizeau

unread,
Mar 13, 2018, 4:08:59 PM3/13/18
to PDFTron WebViewer
Hi David,

I think you need to use the Cordova print plugin to do this https://github.com/katzer/cordova-plugin-printer. We don't have much experience with it but we had heard from a customer previously that was able to get it to work in their app.

You would need to modify MobileReaderControl.js where the startPrintJob function is called. You can change the call to this:

me.startPrintJob($('#printPageNumberInput').val(), orientation, true, function(printData) {
    cordova
.plugins.printer.print(printData, 'Document.html', function () {
        alert
('printing finished or canceled')
   
});
});

Matt Parizeau
Software Developer
PDFTron Systems Inc.

David Compton

unread,
Jun 29, 2018, 12:52:48 PM6/29/18
to PDFTron WebViewer
Hi Matt,

Thanks for your response.  When I initially tried to implement this it was failing silently on iOS.  I have only just had a chance to get back to it and debug it properly.  I find that it is calling into the modified code in MobileReaderControl.js, however it is failing with "cordova variable is undefined".  I cannot find how to make the cordova variable available from MobileReaderControl.  You mentioned that another of your customers was able to get this working.  Do you have any code that your can share or any other thoughts on how to get this working?

Kind regards,

David

Matt Parizeau

unread,
Jun 29, 2018, 7:38:30 PM6/29/18
to PDFTron WebViewer
Hi David,

I think window.cordova is probably defined on your parent page but the code specified is in an iframe so you should be able to do window.parent.cordova.printer... instead to get cordova from the parent window.

Matt Parizeau
Software Developer
PDFTron Systems Inc.

David Compton

unread,
Jul 3, 2018, 1:12:08 PM7/3/18
to PDFTron WebViewer on behalf of Ryan - PDFNet Developer
Hi Matt,

"window.parent" was indeed what was needed to access "cordova" - thanks for pointing me in the right direction.  Still does not print - but at least I am past "first base" now.

Kind regards,

David




--
You received this message because you are subscribed to the Google Groups "PDFTron WebViewer" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pdfnet-webview...@googlegroups.com.
To post to this group, send email to pdfnet-w...@googlegroups.com.
Visit this group at https://groups.google.com/group/pdfnet-webviewer.
For more options, visit https://groups.google.com/d/optout.

David Compton

unread,
Jul 3, 2018, 1:12:10 PM7/3/18
to PDFTron WebViewer on behalf of Ryan - PDFNet Developer
Actually the error that I am now getting from the cordova printer plugin is "Print function requires and HTML string. not an object".  Can we get a HTML string from the printData object?

Regards,

David

David Compton

unread,
Jul 3, 2018, 1:12:12 PM7/3/18
to PDFTron WebViewer on behalf of Ryan - PDFNet Developer
I worked it out, it was rather obvious printData.html().  So for anyone else trying to get this working the complete code necessary is as follows:

me.startPrintJob($('#printPageNumberInput').val(), orientation, true, function(printData) {

    window.parent.cordova
.plugins.printer.print(printData.html(), 'Document.html', function () {

        alert
('printing finished or canceled')
    
});
});

In fact I test for window.parent.cordova and only call this code when on a platform that is using Cordova.

David Compton

unread,
Oct 31, 2018, 11:33:19 AM10/31/18
to pdfnet-w...@googlegroups.com
How do I go about modifying me.startPrintJob with the new UI?

Justin Jung

unread,
Nov 2, 2018, 2:03:26 PM11/2/18
to pdfnet-w...@googlegroups.com
Hi David,

As the new UI is built in React, it's not as easy to override existing functions other than having APIs.
Right now, to modify printing, you would have to edit src/helpers/print.js directly and build the ui project.

Justin Jung

David Compton

unread,
Dec 4, 2018, 2:30:15 PM12/4/18
to pdfnet-w...@googlegroups.com
Hi Justin,

I did manage to debug in iOS using Safari.  What I found is that it calls into actions.openElement('loadingModal') - line 16 of print.js - which makes sense seeing as it does display the print modal.  But it never seems to hit the printPdf function even after the Print button on the modal is tapped.

Note that printing does still work in our web app working off the same code base.

Kind regards,

David

On Tue, 4 Dec 2018 at 18:20, David Compton <david.w...@gmail.com> wrote:
Hi Justin,

So I've forked the source modified const printPdf in print.js to the following (my changes are enclosed by comments):

const printPdf = () => {
  const xfdfString = core.exportAnnotations();
  const printDocument = true;
  return new Promise(resolve => {
    core.getDocument().getFileData({ xfdfString, printDocument }).then(data => {
      const arr = new Uint8Array(data);
      const blob = new Blob([arr], { type: 'application/pdf' });
        /* Start HS Modifications */
        if (!window.parent.cordova) {
          document.getElementById('print-handler').src = URL.createObjectURL(blob);
        } else {
          window.parent.cordova.plugins.printer.print(URL.createObjectURL(blob), 'document.pdf', function () {
            alert('printing finished or cancelled')
          });
       }
       /* End HS Modifications */
      resolve();
    });
  });
};

I've built the WebViewer UI project and then built my Ionic app using the modified build.  However printing still does not work on iOS.  I'm not quite sure how to go about debugging this with only the minified code.  Maybe you can see what I've done wrong - or point me in the right direction to build a non-minified version to debug.

Kind regards,

David

--

David Compton

unread,
Dec 4, 2018, 2:30:16 PM12/4/18
to pdfnet-w...@googlegroups.com
Hi Justin,

So I've forked the source modified const printPdf in print.js to the following (my changes are enclosed by comments):

const printPdf = () => {
  const xfdfString = core.exportAnnotations();
  const printDocument = true;
  return new Promise(resolve => {
    core.getDocument().getFileData({ xfdfString, printDocument }).then(data => {
      const arr = new Uint8Array(data);
      const blob = new Blob([arr], { type: 'application/pdf' });
        /* Start HS Modifications */
        if (!window.parent.cordova) {
          document.getElementById('print-handler').src = URL.createObjectURL(blob);
        } else {
          window.parent.cordova.plugins.printer.print(URL.createObjectURL(blob), 'document.pdf', function () {
            alert('printing finished or cancelled')
          });
       }
       /* End HS Modifications */
      resolve();
    });
  });
};

I've built the WebViewer UI project and then built my Ionic app using the modified build.  However printing still does not work on iOS.  I'm not quite sure how to go about debugging this with only the minified code.  Maybe you can see what I've done wrong - or point me in the right direction to build a non-minified version to debug.

Kind regards,

David

On Sat, 3 Nov 2018 at 05:03, PDFTron WebViewer on behalf of Justin Jung <pdfnet-w...@googlegroups.com> wrote:
--

Justin Jung

unread,
Dec 6, 2018, 3:42:31 PM12/6/18
to PDFTron WebViewer
Hi David,

Yes I don't think it would hit the second if condition and trigger printPdf. You would have to make a change in the if conditions as follows:

export default (dispatch, isEmbedPrintSupported) =>  {
  ...

  if (bbURLPromise) {
    ...
  } else if (isEmbedPrintSupported || window.parent.cordova) {
    dispatch(actions.openElement('loadingModal'));
    printPdf().then(() => {
      dispatch(actions.closeElement('loadingModal'));
    });
  } else {
    ...
  }
};

If the printPdf function is triggered, you will see a loading modal instead of the print modal.

David Compton

unread,
Dec 7, 2018, 12:47:03 PM12/7/18
to PDFTron WebViewer on behalf of Ryan - PDFNet Developer
Hi Justin,

Thanks for that - the code is now getting into printPdf.  However I get the call to:

core.getDocument().getFileData({ xfdfString, printDocument })

returns undefined.  The full error is Unhandled Promise Rejection: TypeError: undefined is not an object (evaluating 'i.default.getDocument(),getFileData({xfdfString:e;printiDocument:!0}).then').

Any idea why getFileData is returned undefined?  Am I going about this the wrong way?

My full modified print.js is as follows:

import { t } from 'i18next';

import actions from 'actions';
import core from 'core';

export default (dispatch, isEmbedPrintSupported) =>  {
  const bbURLPromise = core.getPrintablePDF();

  if (bbURLPromise) {
    const printPage = window.open('', '_blank');
    printPage.document.write(t('message.preparingToPrint'));
    bbURLPromise.then(result => {
      printPage.location.href = result.url;
    });
  /* Start HS Modifications */
  } else if (isEmbedPrintSupported || window.parent.cordova) {
  /* End HS Modifications */
    dispatch(actions.openElement('loadingModal'));
    printPdf().then(() => {
      dispatch(actions.closeElement('loadingModal'));
    });
  } else {
    dispatch(actions.openElement('printModal'));
  }
};

const printPdf = () => {
  const xfdfString = core.exportAnnotations();
  const printDocument = true;
  return new Promise(resolve => {
    core.getDocument().getFileData({ xfdfString, printDocument }).then(data => {
      const arr = new Uint8Array(data);
      const blob = new Blob([arr], { type: 'application/pdf' });
      /* Start HS Modifications */
      if (window.parent.cordova) {
        window.parent.cordova.plugins.printer.print(URL.createObjectURL(blob), 'document.pdf', function () {
          //alert('printing finished or cancelled')
        });
      } else {
        document.getElementById('print-handler').src = URL.createObjectURL(blob);
      }
      /* End HS Modifications */
      resolve();
      });
  });
};

Thanks,

David

--

Justin Jung

unread,
Dec 10, 2018, 6:50:11 PM12/10/18
to PDFTron WebViewer
Hi David,

getFileData is for PDF and office documents only, so you wouldn't be able to use it for XOD (https://www.pdftron.com/api/web/CoreControls.Document.html#getFileData__anchor).
If you are trying to print a PDF and still see the error, could you send us the document so that we can reproduce on our end?

David Compton

unread,
Dec 11, 2018, 1:20:03 PM12/11/18
to PDFTron WebViewer on behalf of Ryan - PDFNet Developer
OK - so I'm going about this the wrong way then.  We only use XOD format documents in the web viewer.  If you look back in this forum thread you will see that Matt pointed me in the right direction to get printing working on Cordova for the legacy UI.  What I'm trying to do is to find out where and what I need to implement to get things working in the new UI.  Could either you or Matt point me in the right direction please?

Kind regards,

David

--

Justin Jung

unread,
Dec 13, 2018, 2:30:17 PM12/13/18
to PDFTron WebViewer
To apply cordova plugin printing for xod, you will have to edit printImages function in PrintModal.js. Below is the change that I made to PrintModal component:

// added to check for cordova printer
isCordovaPrinter = () => {
  return window.parent.cordova && window.parent.cordova.plugins.printer;
}

printImages = images => {
  let printHandler;
  if (this.isCordovaPrinter()) {
    printHandler = document.createElement('div');
    printHandler.style.display = 'block';
    printHandler.style.height = '100%';
  } else {
    printHandler = document.getElementById('print-handler');
    printHandler.innerHTML = '';
  }

  images.forEach((image, index) => {
    if (this.isCordovaPrinter()) {
      image.style.display = 'block';
      image.style.maxWidth = '100%';
      image.style.maxHeight = '100%';
      image.style.width = '100%';
      image.style.height = '100%';
      image.style.objectFit = 'contain';
      image.style.pageBreakAfter = 'always';
    }
    printHandler.appendChild(image);
  });

  if (this.isCordovaPrinter()) {
    window.parent.cordova.plugins.printer.print(printHandler, 'Document.html');
  } else {
    window.print();
  }
  this.closePrintModal();
}

When I tested with the above code, I was able to get the print working, but there seemed to be some kind of margin in the first page.
Is that something you've noticed before as well?

David Compton

unread,
Dec 14, 2018, 1:24:45 PM12/14/18
to PDFTron WebViewer on behalf of Ryan - PDFNet Developer
Also I've noticed that with large documents - once was 140 pages the other 273 pages - it either crashes the application or just never gets past the print modal screen - even if I choose to only print a small range of pages.

On Fri, 14 Dec 2018 at 14:14, David Compton <david.w...@gmail.com> wrote:
Hi Justin,

Yes that change worked - the document now prints - thank you.  However a two page document turned into a 5 page document with 3 blank pages - page 2, 3 & 5.  The two pages that did print had funny margins.  So while it is printing - it is not working correctly.  Even a simple one page document turned into three pages - the last two of which were blank, the first page again had a wide margin.  None of these problems existed when printing to Cordova from the old UI.  Any ideas?

Kind regards,

David

--

David Compton

unread,
Dec 14, 2018, 1:24:45 PM12/14/18
to PDFTron WebViewer on behalf of Ryan - PDFNet Developer
Hi Justin,

Yes that change worked - the document now prints - thank you.  However a two page document turned into a 5 page document with 3 blank pages - page 2, 3 & 5.  The two pages that did print had funny margins.  So while it is printing - it is not working correctly.  Even a simple one page document turned into three pages - the last two of which were blank, the first page again had a wide margin.  None of these problems existed when printing to Cordova from the old UI.  Any ideas?

Kind regards,

David

--

Justin Jung

unread,
Dec 18, 2018, 7:35:46 PM12/18/18
to PDFTron WebViewer
Hi David,

I tried to play around with the argument to the cordova printer, and I think I got it working properly on mine.
Could you try updating the printImages function to the following:

printImages = images => {
  let printHandler;
  if (this.isCordovaPrinter()) {
    printHandler = document.createElement('div');
    printHandler.style.display = 'block';
    printHandler.style.height = '100%';
  } else {
    printHandler = document.getElementById('print-handler');
    printHandler.innerHTML = '';
  }

  images.forEach((image, index) => {
    if (this.isCordovaPrinter()) {
      image.style.display = 'block';
      image.style.maxWidth = '100%';
      image.style.maxHeight = '100%';
      image.style.width = '100%';
      image.style.height = '100%';
      image.style.objectFit = 'contain';
      if (index > 0) {
        image.style.pageBreakAfter = 'always';
      }
    }
    printHandler.appendChild(image);
  });

  if (this.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 {
    window.print();
  }
  this.closePrintModal();
}

About the large document failing to print, I wasn't able to reproduce the issue.
The steps that I took are:
1. Load a xod file with 700+ pages
2. Tap print button
3. In pages, select either Current Page or Custom Pages option to print

Could you elaborate what I should do to reproduce it?

David Compton

unread,
Dec 26, 2018, 1:07:31 PM12/26/18
to PDFTron WebViewer on behalf of Justin Jung
Hi Justin,

Thanks for the updated code regarding printing with Cordova.  I think we are getting closer to a working solution.  I'm no longer getting any blank pages.  However I am still getting the following problems:

1.  The pages still have a larger margin around them in print preview than what the document actually has.  It is a smaller margin than it was originally - but nevertheless there is still some extra white space that should not be there.  I was having problems with my printer so I couldn't verify how they turned out when actually printed on a piece of paper - but I presume it will be the same as the print preview.
2.  If I use the All option for a large document it starts processing pages (Processing... 3/273) but just stops processing once it gets to the 3rd or 4th page.
3.  If I close out of any print job without actually proceeding to print then the printing no longer works, if you select a different printing option.  Steps to reproduce:
  *  Tap Print button
  *  Select Current option
  *  Tap Print button
  *  Tap Cancel button
  *  Tap Print button (current will still be selected)
  *  Select pages option and enter a page range e.g. 1-3
  *  Tap Print button - nothing happens
4. The same problem at point 3 above happens even if you don't Cancel out of the original print job.  So it seems that if you try to print using a different option the second time you try then it fails silently.

I think that I experienced more problems than those detailed above -but hopefully they are enough for you to be able to reproduce the problems I'm experiencing.

Kind regards,

David

--

Justin Jung

unread,
Dec 28, 2018, 3:52:07 PM12/28/18
to PDFTron WebViewer
Hi David,

1. The margin seems to be automatically added by Safari, and it seems like there is no way to remove it completely when printing HTML.
2. The custom printing in Cordova is converting each page into an image, so it may run into memory issues. One of the option might be to limit number of pages to be printed at once, but is that something that fits into your use case?
3 & 4. We have trouble reproducing the issue. Is this in iOS only? Do you see any error messages when you debug? If you wish, you could also create and share forked version of webviewer-ui and webviewer-cordova-sample to make sure that we are on the same page.
Reply all
Reply to author
Forward
0 new messages