7

Help me I am in desperate need for help. Now to the real issue.

I have been trying to get my pdf to open up in new tab in Safari but till now I've only faced disappointment. I am using jsPDF for generating my PDFs and earlier I used it's

doc.save(pdfName+".pdf")

method to do the same, as in the latest safari version "9.1.1(10601.6.17)" it broke. I can still generate the pdf using jsPDF's inbuilt option:

pdf.output('dataurl');

but, it tends to open the PDF in the same tab, and this behaviour is highly undesirable. I tried various solutions available on the net to fix the issue but none works. Some of the solutions that I tried are :

  1. Using window.open(), doesn't work.
  2. Using location.href, doesn't work.
  3. Using doc.output('save', 'filename.pdf'), doc.output('datauri'), doc.output('dataurlnewwindow'), nothing works.
  4. Also tried fake clicking by creating an anchor tag and setting it's target as '_blank' and then using eventDispatcher to stimulate a mouse click but it also didn't work. Something like this :

    var a = window.document.createElement("a");
    a.target = '_blank';
    a.href = 'http://www.google.com';
    
    var e = window.document.createEvent("MouseEvents");
    e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    a.dispatchEvent(e);
    

Any suggestion on what I should do ? I want my pdf to open up in a new tab and not in the same one as that of my application.

P.S : Each of the solutions that I tried for Safari above work flawlessly in Chrome and Mozilla Firefox, I just can't figure out what's the deal with Safari. Any help would be appreciated.

hkm93
  • 1,240
  • 9
  • 14

3 Answers3

1

Tried many solution mentioned in stackoverflow but nothing worked for me, Later checked the FileSave.js implementation and created a working solution for this issue.

  1. Note that I have successfully tested this solution in iOS Safari.
  2. In function downloadPdfMobile the if part is for Web safari else part is for mobile safari.
  3. Normal Android chrome browser this will not work, you need to follow the traditional way.

First you need to get the base64 string from the jsPDF

const doc = new jsPDF.jsPDF({ unit: 'pt', putOnlyUsedFonts: true});
const pdfElement = document.getElementById('id');
var pdfName = 'Test.pdf';
  doc.html(pdfElement, {
    callback: (pdf) => {
      var base = pdf.output('datauristring').split(',')[1];
      downloadPdfMobile(pdfName, base);
    },
    margin: 20,
 });

This is how the downloadPdfMobile function looks like, First you need to convert the base64 t Blob.

downloadPdfMobile: function (FileName, content) {
                    var _global =
                        typeof window === "object" && window.window === window
                            ? window
                            : typeof self === "object" && self.self === self
                            ? self
                            : typeof global === "object" && global.global === global
                            ? global
                            : this;

                var isMacOSWebView =
                    _global.navigator && /Macintosh/.test(navigator.userAgent) && /AppleWebKit/.test(navigator.userAgent) && !/Safari/.test(navigator.userAgent);

                var blob = this.base64toBlob(content);
            
                var popup = open("", "_blank");
                if (popup) {
                    popup.document.title = popup.document.body.innerText = "downloading...";
                }

                var force = blob.type === "application/octet-stream";
                var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari;
                var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);

                if ((isChromeIOS || (force && isSafari) || isMacOSWebView) && typeof FileReader !== "undefined") {
                    var reader = new FileReader();
                    reader.onloadend = function () {
                        var url = reader.result;
                        url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, "data:attachment/file;");
                        if (popup) popup.location.href = url;
                        else location = url;
                        popup = null;
                    };
                    reader.readAsDataURL(blob);
                } else {
                    var URL = _global.URL || _global.webkitURL;
                    var url = URL.createObjectURL(blob);
                    if (popup) popup.location = url;
                    else location.href = url;
                    popup = null; 
                    setTimeout(function () {
                        URL.revokeObjectURL(url);
                    }, 4e4);
                }
            }


base64toBlob: function (base64str) {
                    var binary = atob(base64str.replace(/\s/g, ""));
                    var len = binary.length;
                    var buffer = new ArrayBuffer(len);
                    var view = new Uint8Array(buffer);
                    for (var i = 0; i < len; i++) {
                        view[i] = binary.charCodeAt(i);
                    }
                    return new Blob([view], {
                        type: "application/pdf",
                    });
                },
RRR
  • 3,509
  • 4
  • 29
  • 38
0

If you can get your PDF as base64, this is how you can do with it (works on both Safari and Chrome)

let base64PDF = "JVBERi0xLjQKMSAwIG9iago8PAovVGl0bGUgKP....."// your base64 pdf data

let pdfWindow = window.open("", "_blank");

pdfWindow.document.write(
  "<title>Healthcare</title><iframe width='100%' style='margin: -8px;border: none;' height='100%' src='data:application/pdf;base64, " +
  encodeURI(base64PDF) +
  "'></iframe>"
);
Ahmet Firat Keler
  • 2,603
  • 2
  • 11
  • 22
-1

You could try the blob output. Then generate a Data URI to this, and open it in a new window:

var blob = pdf.output("blob");
window.open(URL.createObjectURL(blob));
demarchisd
  • 734
  • 3
  • 16
  • still, opens the pdf in the same Tab ; _ ; – hkm93 Jun 20 '16 at 13:09
  • that's weird.. if you try to open any other URL, does it still open in the same tab? Anyway, maybe using the second argument could be the solution: `window.open(URL.createObjectURL(blob), '_blank');` – demarchisd Jun 20 '16 at 13:18
  • 1
    didn't work, not being rude but went through tthe doccumentation of Apple and found our that the "The standard window.open() JavaScript method cannot be used to open a new tab and window from a global HTML file or an extension bar" https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html – hkm93 Jun 20 '16 at 13:40
  • yeah, sorry, now I got what the real problem is.. using your 4th attempt (faking a click event), were there any error messages in the console? [here](http://stackoverflow.com/a/2381862/2209617) is a very useful function for firing events – demarchisd Jun 20 '16 at 14:03
  • I'm sorry for the late reply, got sidetracked on a different project. Well, no there are no error messages in console, except for an 'undefined' that is printed, without any event. The same action results in 'undefined' printed in console + google opening in new tab while using Chrome. I'm sorry to say that neither Dispatcher not the FireEvent works. – hkm93 Jun 21 '16 at 11:05