Commit 9d1e206582d8a9d1ac2227f40630d534e87988a2

Authored by Antoine Goutenoir
1 parent 1d74f62f
Exists in master

Fix an issue with PNG downloads.

flaskr/static/js/vendor/simg.js
1 1 /*jshint nonstandard:true */
2   -(function(root){
3   - var previousSimg = root.Simg;
4   - var Simg = root.Simg = function(svg){
5   - this.svg = svg;
6   - };
7   -
8   - Simg.noConflict = function(){
9   - root.Simg = previousSimg;
10   - return this;
11   - };
12   -
13   - Simg.getBase64Image = function(img) {
14   - // From: http://stackoverflow.com/questions/934012/get-image-data-in-javascript
15   - var canvas = document.createElement("canvas");
16   - canvas.width = img.width;
17   - canvas.height = img.height;
18   -
19   - var ctx = canvas.getContext("2d");
20   - ctx.drawImage(img, 0, 0);
21   - var dataURL = canvas.toDataURL("image/png");
22   -
23   - return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
24   - };
25   -
26   - Simg.prototype = {
27   - // Return SVG text.
28   - toString: function(svg){
29   - if (!svg){
30   - throw new Error('.toString: No SVG found.');
31   - }
32   -
33   - [
34   - ['version', 1.1],
35   - ['xmlns', "http://www.w3.org/2000/svg"],
36   - ].forEach(function(item){
37   - svg.setAttribute(item[0], item[1]);
38   - });
39   - return svg.parentNode.innerHTML;
40   - },
41   -
42   - // Return canvas with this SVG drawn inside.
43   - toCanvas: function(cb){
44   - this.toSvgImage(function(img){
45   - var canvas = document.createElement('canvas');
46   - var context = canvas.getContext("2d");
47   -
  2 +(function (root) {
  3 + var previousSimg = root.Simg;
  4 + var Simg = root.Simg = function (svg) {
  5 + this.svg = svg;
  6 + };
  7 +
  8 + Simg.noConflict = function () {
  9 + root.Simg = previousSimg;
  10 + return this;
  11 + };
  12 +
  13 + Simg.getBase64Image = function (img) {
  14 + // From: http://stackoverflow.com/questions/934012/get-image-data-in-javascript
  15 + var canvas = document.createElement("canvas");
48 16 canvas.width = img.width;
49 17 canvas.height = img.height;
50 18  
51   - context.drawImage(img, 0, 0);
52   - cb(canvas);
53   - });
54   - },
55   -
56   - toSvgImage: function(cb){
57   - var str = this.toString(this.svg);
58   - var img = document.createElement('img');
59   -
60   - if (cb){
61   - img.onload = function(){
62   - cb(img);
63   - };
64   - }
65   -
66   - // Make the new img's source an SVG image.
67   - img.setAttribute('src', 'data:image/svg+xml;base64,'+ btoa(unescape(encodeURIComponent(str))));
68   - },
69   -
70   - // Returns callback to new img from SVG.
71   - // Call with no arguments to return svg image element.
72   - // Call with callback to return png image element.
73   - toImg: function(cb){
74   - this.toCanvas(function(canvas){
75   - var canvasData = canvas.toDataURL("image/png");
76   - var img = document.createElement('img');
77   -
78   - img.onload = function(){
79   - cb(img);
80   - };
81   -
82   - // Make pngImg's source the canvas data.
83   - img.setAttribute('src', canvasData);
84   - });
85   - },
86   -
87   - // Replace SVG with PNG img.
88   - replace: function(cb){
89   - var self = this;
90   - this.toImg(function(img){
91   - var parentNode = self.svg.parentNode;
92   - parentNode.replaceChild(img, self.svg);
93   - if (cb){
94   - cb();
95   - }
96   - });
97   - },
98   -
99   - // Converts canvas to binary blob.
100   - toBinaryBlob: function(cb){
101   - this.toCanvas(function(canvas){
102   - var dataUrl = canvas.toDataURL().replace(/^data:image\/(png|jpg);base64,/, "");
103   - var byteString = atob(escape(dataUrl));
104   - // write the bytes of the string to an ArrayBuffer
105   - var ab = new ArrayBuffer(byteString.length);
106   - var ia = new Uint8Array(ab);
107   - for (var i = 0; i < byteString.length; i++) {
108   - ia[i] = byteString.charCodeAt(i);
  19 + var ctx = canvas.getContext("2d");
  20 + ctx.drawImage(img, 0, 0);
  21 + var dataURL = canvas.toDataURL("image/png");
  22 +
  23 + return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
  24 + };
  25 +
  26 + Simg.prototype = {
  27 + // Return SVG text.
  28 + toString: function (svg) {
  29 + if (!svg) {
  30 + throw new Error('.toString: No SVG found.');
  31 + }
  32 +
  33 + [
  34 + ['version', 1.1],
  35 + ['xmlns', "http://www.w3.org/2000/svg"],
  36 + ].forEach(function (item) {
  37 + svg.setAttribute(item[0], item[1]);
  38 + });
  39 + return svg.parentNode.innerHTML;
  40 + },
  41 +
  42 + // Return canvas with this SVG drawn inside.
  43 + toCanvas: function (cb) {
  44 + this.toSvgImage(function (img) {
  45 + var canvas = document.createElement('canvas');
  46 + var context = canvas.getContext("2d");
  47 +
  48 + canvas.width = img.width;
  49 + canvas.height = img.height;
  50 +
  51 + context.drawImage(img, 0, 0);
  52 + cb(canvas);
  53 + });
  54 + },
  55 +
  56 + toSvgImage: function (cb) {
  57 + var str = this.toString(this.svg);
  58 + var img = document.createElement('img');
  59 +
  60 + if (cb) {
  61 + img.onload = function () {
  62 + cb(img);
  63 + };
  64 + }
  65 +
  66 + // Make the new img's source an SVG image.
  67 + img.setAttribute('src', 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(str))));
  68 +
  69 + //document.getElementById("png_buffer").appendChild(img);
  70 + },
  71 +
  72 + // Returns callback to new img from SVG.
  73 + // Call with no arguments to return svg image element.
  74 + // Call with callback to return png image element.
  75 + toImg: function (cb) {
  76 + this.toCanvas(function (canvas) {
  77 + var canvasData = canvas.toDataURL("image/png");
  78 + var img = document.createElement('img');
  79 + //document.getElementById("png_buffer").appendChild(img);
  80 + img.onload = function () {
  81 + cb(img);
  82 + };
  83 +
  84 + // Make pngImg's source the canvas data.
  85 + img.setAttribute('src', canvasData);
  86 + });
  87 + },
  88 +
  89 + // Replace SVG with PNG img.
  90 + replace: function (cb) {
  91 + var self = this;
  92 + this.toImg(function (img) {
  93 + var parentNode = self.svg.parentNode;
  94 + parentNode.replaceChild(img, self.svg);
  95 + if (cb) {
  96 + cb();
  97 + }
  98 + });
  99 + },
  100 +
  101 + // Converts canvas to binary blob.
  102 + toBinaryBlob: function (cb) {
  103 + this.toCanvas(function (canvas) {
  104 + var dataUrl = canvas.toDataURL().replace(/^data:image\/(png|jpg);base64,/, "");
  105 + var byteString = atob(escape(dataUrl));
  106 + // write the bytes of the string to an ArrayBuffer
  107 + var ab = new ArrayBuffer(byteString.length);
  108 + var ia = new Uint8Array(ab);
  109 + for (var i = 0; i < byteString.length; i++) {
  110 + ia[i] = byteString.charCodeAt(i);
  111 + }
  112 + var dataView = new DataView(ab);
  113 + var blob = new Blob([dataView], {type: "image/png"});
  114 + cb(blob);
  115 + });
  116 + },
  117 +
  118 + // Trigger download of image.
  119 + download: function (filename) {
  120 + if (!filename) {
  121 + filename = 'chart';
  122 + }
  123 + this.toImg(function (img) {
  124 + var a = document.createElement("a");
  125 + a.download = filename + ".png";
  126 + a.href = img.getAttribute('src');
  127 + //document.getElementById("png_buffer").appendChild(a);
  128 + a.click();
  129 + });
109 130 }
110   - var dataView = new DataView(ab);
111   - var blob = new Blob([dataView], {type: "image/png"});
112   - cb(blob);
113   - });
114   - },
115   -
116   - // Trigger download of image.
117   - download: function(filename){
118   - if (!filename){
119   - filename = 'chart';
120   - }
121   - this.toImg(function(img){
122   - var a = document.createElement("a");
123   - a.download = filename + ".png";
124   - a.href = img.getAttribute('src');
125   - a.click();
126   - });
127   - }
128   - };
  131 + };
129 132 })(this);
... ...
flaskr/static/public/js/common.js
... ... @@ -140,6 +140,8 @@
140 140 var a = document.createElement("a");
141 141 a.download = filename + ".png";
142 142 a.href = img.getAttribute('src');
  143 + document.getElementById("png_buffer").appendChild(a);
  144 + console.debug("SIMG RAN");
143 145 a.click();
144 146 });
145 147 }
... ...
flaskr/templates/estimation.html
... ... @@ -100,8 +100,9 @@
100 100 {# <h4>Total CO<sub>2</sub> footprint (in kilograms-equivalent) of each city</h4>#}
101 101 {# <div id="cities_footprints_d3viz" class="plot-container"></div>#}
102 102 <hr>
  103 + <div id="cities_footprints_spinner" class="lds-ripple text-center"><div></div><div></div><div></div></div>
  104 + {# This MUST stay empty (because Simg uses svg.getparentnode.innerhtml) #}
103 105 <div id="cities_footprints_d3viz_lollipop" class="plot-container">
104   - <div id="cities_footprints_spinner" class="lds-ripple text-center"><div></div><div></div><div></div></div>
105 106 </div>
106 107 {# <br>#}
107 108 {# <p>A Legend here</p>#}
... ... @@ -203,6 +204,9 @@
203 204 {{ content.estimation.footer | markdown | safe }}
204 205 </div>
205 206  
  207 +{# Buffer to drop the PNG image into to hack firefox into downloading the PNG #}
  208 +<div id="png_buffer"></div>
  209 +
206 210 {% endif %}{# not estimation.has_failed() #}
207 211 {% endblock %}
208 212  
... ... @@ -560,7 +564,7 @@ jQuery(document).ready(function($){
560 564 $(vizid+" svg .value-text").css("opacity", 1);
561 565 // May not work everywhere, but…
562 566 var simg = new Simg($(vizid + " svg")[0]);
563   - simg.download();
  567 + simg.download("travel_carbon_footprint_{{ estimation.public_id }}");
564 568 // Hide the values
565 569 $(vizid+" svg .value-text").css("opacity", 0);
566 570 return false;
... ...