Issue with jsPDF not displaying Highcharts image in Edge browser

As a newcomer to jsPDF, I am attempting to download a highchart with some HTML content. Everything is running smoothly in all browsers except for "Microsoft Edge".
Here is the functional Plunker. I have searched online for similar issues, but no solutions specifically address problems with the Edge browser. In my quest for a solution, I even tried using PNG images instead of JPEG as suggested here, but unfortunately that did not work either.

Please Note: When I directly pass the image URL to the .addImage() function, it works perfectly across all browsers.

Could someone please advise me on what I might be overlooking or doing incorrectly?

Update: The code functions fine up until version 20 of Edge; the issue seems to arise in versions above 20.

Answer №1

It seems that the issue at hand is linked to a problem with Edge-Canvas.

In my case, I decided to use the SVG->Blob->Image->Canvas method instead of SVG->Canvas.

Initially, when testing on my local Edge browser, I encountered the same problem as mentioned in the post. However, after implementing my version it worked smoothly on Edge as well.

Here's a breakdown of what I did:

 $scope.chartWithContentDownload = function() {
        var doc = new jsPDF('portrait', 'pt', 'a4', true);
        var elementHandler = {
            '#ignorePDF' : function(element, renderer) {
                return true;
            }
        };

        var source = document.getElementById("top-content");
        doc.fromHTML(source, 15, 15, {
            'width' : 560,
            'elementHandlers' : elementHandler
        });


        var msie = document.documentMode;

  if (!isNaN(msie) && msie < 12) {
  // code for IE < 12

      var tempSVG = $('#testchart').highcharts().container.innerHTML;
                var canvas11 = document.createElement('canvas');

                canvg(canvas11, tempSVG);
                var dataUrl = canvas11.toDataURL('image/JPEG');

                doc.addImage(dataUrl, 'JPEG', 20, 300, 560, 350);

                var source2 = document.getElementById("bottom-content");
                doc.fromHTML(source2, 15, 650, {
                    'width' : 560,
                    'elementHandlers' : elementHandler
                });

                setTimeout(function() {
                    doc.save('TestChart.pdf');
                }, 2000);

  } else {

    var svg = document.querySelector('svg');
        var width = $('#testchart').find('svg').width();
        var height = $('#testchart').find('svg').height();
        var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    var DOMURL = window.URL || window.webkitURL || window;
    var data = (new XMLSerializer()).serializeToString(svg);

    var img = new Image();
    var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
    var url = DOMURL.createObjectURL(svgBlob);

    img.onload = function () {
      ctx.canvas.width = width;
      ctx.canvas.height = height;
      ctx.drawImage(img, 0, 0, width, height);
      DOMURL.revokeObjectURL(url);

      var dataUrl = canvas.toDataURL('image/jpeg');
      doc.addImage(dataUrl, 'JPEG', 20, 300, 560, 350);

            var source2 = document.getElementById("bottom-content");
            doc.fromHTML(source2, 15, 650, {
               'width' : 560,
                'elementHandlers' : elementHandler
            });

            setTimeout(function() {
                doc.save('TestChart.pdf');
            }, 2000);
    };

    img.src = url;

}

};

Access the Plunker Link here

Note:

I conducted tests only on Chrome and Edge browsers.

The version of my Edge is: Microsoft Edge 38.14393.0.0

My Chrome version is: Version 56.0.2924.87


Edit

Previously, there was a bug on IE 11 concerning canvas.toDataUrl() security error, which has now been resolved with the updated code. The behavior changes depending on the browser, specifically addressing actions for IE 11. The original code provided by the OP functions properly on IE 11, so no further adjustments were made outside of checking the client's IE browser version.

An Angular-specific property was used as follows:

var msie = document.documentMode;
. This property helps identify the browser type - returning NaN for non-IE browsers and the version number for Internet Explorer.

Source: https://github.com/angular/angular.js/blob/master/src/Angular.js#L204-L209


Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Distinguishing AngularJS Objects

I'm currently grappling with understanding JavaScript objects and am facing a challenge in distinguishing between two objects. Specifically, I have an input form for adding records to a database and a controller that handles the addition using $resou ...

Setting the title attribute for option elements in a select element that is bound to a model using AngularJs

I'm currently working on an HTML select element that is connected to an ng-model. Here's what the setup looks like: <select data-ng-model="accountType" data-ng-options="at.name for at in accountTypes"></select> This is how my accou ...

Clicking on a search result does not trigger the popup to open in the App.vue file

Whenever I click on a search item, my goal is to open the Popup. Why does this.$emit('openPopup', bookId); not work in the selectBook(bookId) method? In Results.vue component, the search results are displayed using Google Books API: <template ...

Replacing a string in a textarea using Jquery

Trying to dynamically replace a string value in a textarea while typing into a textbox using jQuery. Utilizing the keypress event for this functionality. Any ideas on what could be causing issues with this example? <input type="text" id="textbox" /> ...

Transforming multi-layered form data into a JSON array structure for seamless integration with application/json

I'm currently developing a Laravel application and facing an issue with the $controller->wantsJson() method in the back-end. This method returns TRUE only if the content type of the request is set to application/json. jQuery.ajax({ type: ...

JavaScript, detecting repeated characters

I need to create a script that checks an input box (password) for the occurrence of the same character appearing twice. This script should work alongside existing regex validation. I believe I will need to use a loop to check if any character appears twice ...

Comparison of element state prior to and post editing (with contentEditable)

Exploring how elements within a div can be monitored for changes made by the user (thanks to contentEditable), I created a sample page with the following setup: before_html = $("#example_div").children(); $("#differences_button").on("click", ...

Iframe Loading at Lightning Speed

I have set up a script to load my iframe, but I noticed that the script loads the iframe content too quickly. Is there a way for me to configure it to preload all CSS images and content in the background before showing the full iframe content? Here is my ...

Is there a way to divide a string and insert something into the new array that is created?

I am facing an issue with adding a new fruit to a string that is converted into an array. Here's the scenario: var fruits = "banana,apple"; In an attempt to add a new fruit to this list, I tried converting it to an array and then using the push meth ...

A guide on triggering a function when a button is clicked in reactjs

Can anyone please help me with this issue I'm having: how do I execute a function when a button is clicked? I currently have the following code but it's not working export var Modulo = React.createClass({ prom1: function () { retur ...

`Vue Router - Dynamically update route anchor on scroll`

My goal is to achieve the same routing behavior on my website as demonstrated here: https://router.vuejs.org/guide/#html. If you observe, the link changes to https://router.vuejs.org/guide/#javascript when you scroll down, and reverts when scrolling back u ...

Issues with data not being successfully transferred between controllers in my service

Presenting my unique service: var CustomService = function () { var filters, charts, subscription; return { getFilters: function () { return this.filters; }, setFilters: function (value) { this.filt ...

Can you explain the contrast between aws-amplify-react and @aws-amplify/ui-react?

I have come across multiple sources recommending the use of aws-amplify-react, but in the documentation for getting started with React, I found a different package @aws-amplify/ui-react that utilizes the module withAuthentication (which is also present in ...

Setting default date and time for Bootstrap datetimepicker only in the expanded calendar view

Here is the setup: $(function () { $('#datetimepicker').datetimepicker({ defaultDate: moment(), sideBySide: true }); }); This configuration allows setting a default date & time when no value is provided for the f ...

AngularJS: Transforming form field inputs into JSON format

I am curious about how I could create a function (either a directive or controller) that can convert all of my form inputs into JSON, including their current values. The JSON format I have in mind is something like this: { fields: [ {fi ...

Interactive feature on Google Maps information window allowing navigation to page's functions

Working on an Angular2 / Ionic 2 mobile App, I am utilizing the google maps JS API to display markers on a map. Upon clicking a marker, an information window pops up containing text and a button that triggers a function when clicked. If this function simpl ...

Why won't the jQuery function trigger when I click, but only responds when I move the cursor?

I am currently working on a website that includes a basic CSS style switcher. The function responsible for handling the theme button clicks is shown below: <script> $(function() { $(".light").click(function(){ $("link").attr("href", ...

Stock Chart that resembles the functionality of Google's popular line chart feature

Can anyone recommend a Javascript or SVG chart library that has a style similar to a Google Chart? I have been searching without much luck and would appreciate some guidance on how to achieve a similar look. I've looked into the Google Visualization ...

Tips on running methods consecutively within ngOnInit in Angular

I'm currently working on an ngoninit function that contains four methods. Two of these methods are responsible for retrieving data from the API, while the other two are intended to load this data when the page loads. ngOnInit(){ getname(); getsubjects ...

Using Vue.js as a view engine for ExpressJS

I'm on the hunt for a solution similar to React for ExpressJS, but tailored for Vue.js instead. Currently, I'm facing challenges when it comes to passing data from my database (mongoose) to my view. Right now, I'm utilizing the handlebars v ...