highcharts_rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +106 -0
  9. data/Rakefile +6 -0
  10. data/highcharts_rails.gemspec +27 -0
  11. data/lib/highcharts_rails/version.rb +3 -0
  12. data/lib/highcharts_rails.rb +8 -0
  13. data/vendor/assets/javascripts/highcharts-3d.src.js +2139 -0
  14. data/vendor/assets/javascripts/highcharts-more.src.js +2982 -0
  15. data/vendor/assets/javascripts/highcharts.src.js +22947 -0
  16. data/vendor/assets/javascripts/js/highcharts-3d.src.js +2085 -0
  17. data/vendor/assets/javascripts/js/highcharts-more.src.js +2820 -0
  18. data/vendor/assets/javascripts/js/highcharts.src.js +20917 -0
  19. data/vendor/assets/javascripts/js/modules/accessibility.src.js +1072 -0
  20. data/vendor/assets/javascripts/js/modules/annotations.src.js +408 -0
  21. data/vendor/assets/javascripts/js/modules/boost.src.js +652 -0
  22. data/vendor/assets/javascripts/js/modules/broken-axis.src.js +338 -0
  23. data/vendor/assets/javascripts/js/modules/data.src.js +981 -0
  24. data/vendor/assets/javascripts/js/modules/drilldown.src.js +756 -0
  25. data/vendor/assets/javascripts/js/modules/exporting.src.js +953 -0
  26. data/vendor/assets/javascripts/js/modules/funnel.src.js +290 -0
  27. data/vendor/assets/javascripts/js/modules/gantt.src.js +791 -0
  28. data/vendor/assets/javascripts/js/modules/grid-axis.src.js +545 -0
  29. data/vendor/assets/javascripts/js/modules/heatmap.src.js +798 -0
  30. data/vendor/assets/javascripts/js/modules/no-data-to-display.src.js +150 -0
  31. data/vendor/assets/javascripts/js/modules/offline-exporting.src.js +492 -0
  32. data/vendor/assets/javascripts/js/modules/overlapping-datalabels.src.js +164 -0
  33. data/vendor/assets/javascripts/js/modules/series-label.src.js +606 -0
  34. data/vendor/assets/javascripts/js/modules/solid-gauge.src.js +305 -0
  35. data/vendor/assets/javascripts/js/modules/treemap.src.js +881 -0
  36. data/vendor/assets/javascripts/js/modules/xrange-series.src.js +254 -0
  37. data/vendor/assets/javascripts/js/themes/dark-blue.js +317 -0
  38. data/vendor/assets/javascripts/js/themes/dark-green.js +314 -0
  39. data/vendor/assets/javascripts/js/themes/dark-unica.js +243 -0
  40. data/vendor/assets/javascripts/js/themes/gray.js +326 -0
  41. data/vendor/assets/javascripts/js/themes/grid-light.js +99 -0
  42. data/vendor/assets/javascripts/js/themes/grid.js +131 -0
  43. data/vendor/assets/javascripts/js/themes/sand-signika.js +129 -0
  44. data/vendor/assets/javascripts/js/themes/skies.js +112 -0
  45. data/vendor/assets/javascripts/lib/canvg.src.js +3073 -0
  46. data/vendor/assets/javascripts/lib/jspdf.src.js +3031 -0
  47. data/vendor/assets/javascripts/lib/rgbcolor.src.js +299 -0
  48. data/vendor/assets/javascripts/lib/svg2pdf.src.js +1451 -0
  49. data/vendor/assets/javascripts/modules/accessibility.src.js +1072 -0
  50. data/vendor/assets/javascripts/modules/annotations.src.js +408 -0
  51. data/vendor/assets/javascripts/modules/boost.src.js +652 -0
  52. data/vendor/assets/javascripts/modules/broken-axis.src.js +338 -0
  53. data/vendor/assets/javascripts/modules/data.src.js +981 -0
  54. data/vendor/assets/javascripts/modules/drilldown.src.js +797 -0
  55. data/vendor/assets/javascripts/modules/exporting.src.js +882 -0
  56. data/vendor/assets/javascripts/modules/funnel.src.js +304 -0
  57. data/vendor/assets/javascripts/modules/gantt.src.js +815 -0
  58. data/vendor/assets/javascripts/modules/grid-axis.src.js +547 -0
  59. data/vendor/assets/javascripts/modules/heatmap.src.js +810 -0
  60. data/vendor/assets/javascripts/modules/no-data-to-display.src.js +161 -0
  61. data/vendor/assets/javascripts/modules/offline-exporting.src.js +492 -0
  62. data/vendor/assets/javascripts/modules/overlapping-datalabels.src.js +164 -0
  63. data/vendor/assets/javascripts/modules/series-label.src.js +606 -0
  64. data/vendor/assets/javascripts/modules/solid-gauge.src.js +316 -0
  65. data/vendor/assets/javascripts/modules/treemap.src.js +935 -0
  66. data/vendor/assets/javascripts/modules/xrange-series.src.js +276 -0
  67. data/vendor/assets/javascripts/themes/dark-blue.js +317 -0
  68. data/vendor/assets/javascripts/themes/dark-green.js +314 -0
  69. data/vendor/assets/javascripts/themes/dark-unica.js +243 -0
  70. data/vendor/assets/javascripts/themes/gray.js +326 -0
  71. data/vendor/assets/javascripts/themes/grid-light.js +99 -0
  72. data/vendor/assets/javascripts/themes/grid.js +131 -0
  73. data/vendor/assets/javascripts/themes/sand-signika.js +129 -0
  74. data/vendor/assets/javascripts/themes/skies.js +112 -0
  75. data/vendor/assets/stylesheets/highcharts.scss +610 -0
  76. metadata +161 -0
@@ -0,0 +1,150 @@
1
+ /**
2
+ * @license Highcharts JS v5.0.6 (2016-12-07)
3
+ * Plugin for displaying a message when there is no data visible in chart.
4
+ *
5
+ * (c) 2010-2016 Highsoft AS
6
+ * Author: Oystein Moseng
7
+ *
8
+ * License: www.highcharts.com/license
9
+ */
10
+ (function(factory) {
11
+ if (typeof module === 'object' && module.exports) {
12
+ module.exports = factory;
13
+ } else {
14
+ factory(Highcharts);
15
+ }
16
+ }(function(Highcharts) {
17
+ (function(H) {
18
+ /**
19
+ * Plugin for displaying a message when there is no data visible in chart.
20
+ *
21
+ * (c) 2010-2016 Highsoft AS
22
+ * Author: Oystein Moseng
23
+ *
24
+ * License: www.highcharts.com/license
25
+ */
26
+ 'use strict';
27
+
28
+ var seriesTypes = H.seriesTypes,
29
+ chartPrototype = H.Chart.prototype,
30
+ defaultOptions = H.getOptions(),
31
+ extend = H.extend,
32
+ each = H.each;
33
+
34
+ // Add language option
35
+ extend(defaultOptions.lang, {
36
+ noData: 'No data to display'
37
+ });
38
+
39
+ // Add default display options for message
40
+ defaultOptions.noData = {
41
+ position: {
42
+ x: 0,
43
+ y: 0,
44
+ align: 'center',
45
+ verticalAlign: 'middle'
46
+ }
47
+ // useHTML: false
48
+ };
49
+
50
+
51
+
52
+ /**
53
+ * Define hasData functions for series. These return true if there are data points on this series within the plot area
54
+ */
55
+ function hasDataPie() {
56
+ return !!this.points.length; /* != 0 */
57
+ }
58
+
59
+ each(['pie', 'gauge', 'waterfall', 'bubble', 'treemap'], function(type) {
60
+ if (seriesTypes[type]) {
61
+ seriesTypes[type].prototype.hasData = hasDataPie;
62
+ }
63
+ });
64
+
65
+ H.Series.prototype.hasData = function() {
66
+ return this.visible && this.dataMax !== undefined && this.dataMin !== undefined; // #3703
67
+ };
68
+
69
+ /**
70
+ * Display a no-data message.
71
+ *
72
+ * @param {String} str An optional message to show in place of the default one
73
+ */
74
+ chartPrototype.showNoData = function(str) {
75
+ var chart = this,
76
+ options = chart.options,
77
+ text = str || options.lang.noData,
78
+ noDataOptions = options.noData;
79
+
80
+ if (!chart.noDataLabel) {
81
+ chart.noDataLabel = chart.renderer
82
+ .label(
83
+ text,
84
+ 0,
85
+ 0,
86
+ null,
87
+ null,
88
+ null,
89
+ noDataOptions.useHTML,
90
+ null,
91
+ 'no-data'
92
+ );
93
+
94
+
95
+
96
+ chart.noDataLabel.add();
97
+
98
+ chart.noDataLabel.align(extend(chart.noDataLabel.getBBox(), noDataOptions.position), false, 'plotBox');
99
+ }
100
+ };
101
+
102
+ /**
103
+ * Hide no-data message
104
+ */
105
+ chartPrototype.hideNoData = function() {
106
+ var chart = this;
107
+ if (chart.noDataLabel) {
108
+ chart.noDataLabel = chart.noDataLabel.destroy();
109
+ }
110
+ };
111
+
112
+ /**
113
+ * Returns true if there are data points within the plot area now
114
+ */
115
+ chartPrototype.hasData = function() {
116
+ var chart = this,
117
+ series = chart.series,
118
+ i = series.length;
119
+
120
+ while (i--) {
121
+ if (series[i].hasData() && !series[i].options.isInternal) {
122
+ return true;
123
+ }
124
+ }
125
+
126
+ return false;
127
+ };
128
+
129
+ /**
130
+ * Show no-data message if there is no data in sight. Otherwise, hide it.
131
+ */
132
+ function handleNoData() {
133
+ var chart = this;
134
+ if (chart.hasData()) {
135
+ chart.hideNoData();
136
+ } else {
137
+ chart.showNoData();
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Add event listener to handle automatic display of no-data message
143
+ */
144
+ chartPrototype.callbacks.push(function(chart) {
145
+ H.addEvent(chart, 'load', handleNoData);
146
+ H.addEvent(chart, 'redraw', handleNoData);
147
+ });
148
+
149
+ }(Highcharts));
150
+ }));
@@ -0,0 +1,492 @@
1
+ /**
2
+ * @license Highcharts JS v5.0.6 (2016-12-07)
3
+ * Client side exporting module
4
+ *
5
+ * (c) 2015 Torstein Honsi / Oystein Moseng
6
+ *
7
+ * License: www.highcharts.com/license
8
+ */
9
+ (function(factory) {
10
+ if (typeof module === 'object' && module.exports) {
11
+ module.exports = factory;
12
+ } else {
13
+ factory(Highcharts);
14
+ }
15
+ }(function(Highcharts) {
16
+ (function(Highcharts) {
17
+ /**
18
+ * Client side exporting module
19
+ *
20
+ * (c) 2015 Torstein Honsi / Oystein Moseng
21
+ *
22
+ * License: www.highcharts.com/license
23
+ */
24
+
25
+ 'use strict';
26
+ /*global MSBlobBuilder */
27
+
28
+ var merge = Highcharts.merge,
29
+ win = Highcharts.win,
30
+ nav = win.navigator,
31
+ doc = win.document,
32
+ each = Highcharts.each,
33
+ domurl = win.URL || win.webkitURL || win,
34
+ isMSBrowser = /Edge\/|Trident\/|MSIE /.test(nav.userAgent),
35
+ loadEventDeferDelay = isMSBrowser ? 150 : 0; // Milliseconds to defer image load event handlers to offset IE bug
36
+
37
+ // Dummy object so we can reuse our canvas-tools.js without errors
38
+ Highcharts.CanVGRenderer = {};
39
+
40
+
41
+ /**
42
+ * Downloads a script and executes a callback when done.
43
+ * @param {String} scriptLocation
44
+ * @param {Function} callback
45
+ */
46
+ function getScript(scriptLocation, callback) {
47
+ var head = doc.getElementsByTagName('head')[0],
48
+ script = doc.createElement('script');
49
+
50
+ script.type = 'text/javascript';
51
+ script.src = scriptLocation;
52
+ script.onload = callback;
53
+ script.onerror = function() {
54
+ console.error('Error loading script', scriptLocation); // eslint-disable-line no-console
55
+ };
56
+
57
+ head.appendChild(script);
58
+ }
59
+
60
+ // Download contents by dataURL/blob
61
+ Highcharts.downloadURL = function(dataURL, filename) {
62
+ var a = doc.createElement('a'),
63
+ windowRef;
64
+
65
+ // IE specific blob implementation
66
+ if (nav.msSaveOrOpenBlob) {
67
+ nav.msSaveOrOpenBlob(dataURL, filename);
68
+ return;
69
+ }
70
+
71
+ // Try HTML5 download attr if supported
72
+ if (a.download !== undefined) {
73
+ a.href = dataURL;
74
+ a.download = filename; // HTML5 download attribute
75
+ a.target = '_blank';
76
+ doc.body.appendChild(a);
77
+ a.click();
78
+ doc.body.removeChild(a);
79
+ } else {
80
+ // No download attr, just opening data URI
81
+ try {
82
+ windowRef = win.open(dataURL, 'chart');
83
+ if (windowRef === undefined || windowRef === null) {
84
+ throw 'Failed to open window';
85
+ }
86
+ } catch (e) {
87
+ // window.open failed, trying location.href
88
+ win.location.href = dataURL;
89
+ }
90
+ }
91
+ };
92
+
93
+ // Get blob URL from SVG code. Falls back to normal data URI.
94
+ Highcharts.svgToDataUrl = function(svg) {
95
+ var webKit = nav.userAgent.indexOf('WebKit') > -1 && nav.userAgent.indexOf('Chrome') < 0; // Webkit and not chrome
96
+ try {
97
+ // Safari requires data URI since it doesn't allow navigation to blob URLs
98
+ // Firefox has an issue with Blobs and internal references, leading to gradients not working using Blobs (#4550)
99
+ if (!webKit && nav.userAgent.toLowerCase().indexOf('firefox') < 0) {
100
+ return domurl.createObjectURL(new win.Blob([svg], {
101
+ type: 'image/svg+xml;charset-utf-16'
102
+ }));
103
+ }
104
+ } catch (e) {
105
+ // Ignore
106
+ }
107
+ return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg);
108
+ };
109
+
110
+ // Get data:URL from image URL
111
+ // Pass in callbacks to handle results. finallyCallback is always called at the end of the process. Supplying this callback is optional.
112
+ // All callbacks receive four arguments: imageURL, imageType, callbackArgs and scale. callbackArgs is used only by callbacks and can contain whatever.
113
+ Highcharts.imageToDataUrl = function(imageURL, imageType, callbackArgs, scale, successCallback, taintedCallback, noCanvasSupportCallback, failedLoadCallback, finallyCallback) {
114
+ var img = new win.Image(),
115
+ taintedHandler,
116
+ loadHandler = function() {
117
+ setTimeout(function() {
118
+ var canvas = doc.createElement('canvas'),
119
+ ctx = canvas.getContext && canvas.getContext('2d'),
120
+ dataURL;
121
+ try {
122
+ if (!ctx) {
123
+ noCanvasSupportCallback(imageURL, imageType, callbackArgs, scale);
124
+ } else {
125
+ canvas.height = img.height * scale;
126
+ canvas.width = img.width * scale;
127
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
128
+
129
+ // Now we try to get the contents of the canvas.
130
+ try {
131
+ dataURL = canvas.toDataURL(imageType);
132
+ successCallback(dataURL, imageType, callbackArgs, scale);
133
+ } catch (e) {
134
+ taintedHandler(imageURL, imageType, callbackArgs, scale);
135
+ }
136
+ }
137
+ } finally {
138
+ if (finallyCallback) {
139
+ finallyCallback(imageURL, imageType, callbackArgs, scale);
140
+ }
141
+ }
142
+ }, loadEventDeferDelay); // IE bug where image is not always ready despite calling load event.
143
+ },
144
+ // Image load failed (e.g. invalid URL)
145
+ errorHandler = function() {
146
+ failedLoadCallback(imageURL, imageType, callbackArgs, scale);
147
+ if (finallyCallback) {
148
+ finallyCallback(imageURL, imageType, callbackArgs, scale);
149
+ }
150
+ };
151
+
152
+ // This is called on load if the image drawing to canvas failed with a security error.
153
+ // We retry the drawing with crossOrigin set to Anonymous.
154
+ taintedHandler = function() {
155
+ img = new win.Image();
156
+ taintedHandler = taintedCallback;
157
+ img.crossOrigin = 'Anonymous'; // Must be set prior to loading image source
158
+ img.onload = loadHandler;
159
+ img.onerror = errorHandler;
160
+ img.src = imageURL;
161
+ };
162
+
163
+ img.onload = loadHandler;
164
+ img.onerror = errorHandler;
165
+ img.src = imageURL;
166
+ };
167
+
168
+ /**
169
+ * Get data URL to an image of an SVG and call download on it
170
+ *
171
+ * options object:
172
+ * filename: Name of resulting downloaded file without extension
173
+ * type: File type of resulting download
174
+ * scale: Scaling factor of downloaded image compared to source
175
+ * libURL: URL pointing to location of dependency scripts to download on demand
176
+ */
177
+ Highcharts.downloadSVGLocal = function(svg, options, failCallback, successCallback) {
178
+ var svgurl,
179
+ blob,
180
+ objectURLRevoke = true,
181
+ finallyHandler,
182
+ libURL = options.libURL || Highcharts.getOptions().exporting.libURL,
183
+ dummySVGContainer = doc.createElement('div'),
184
+ imageType = options.type || 'image/png',
185
+ filename = (options.filename || 'chart') + '.' + (imageType === 'image/svg+xml' ? 'svg' : imageType.split('/')[1]),
186
+ scale = options.scale || 1;
187
+
188
+ libURL = libURL.slice(-1) !== '/' ? libURL + '/' : libURL; // Allow libURL to end with or without fordward slash
189
+
190
+ function svgToPdf(svgElement, margin) {
191
+ var width = svgElement.width.baseVal.value + 2 * margin,
192
+ height = svgElement.height.baseVal.value + 2 * margin,
193
+ pdf = new win.jsPDF('l', 'pt', [width, height]); // eslint-disable-line new-cap
194
+ win.svgElementToPdf(svgElement, pdf, {
195
+ removeInvalid: true
196
+ });
197
+ return pdf.output('datauristring');
198
+ }
199
+
200
+ function downloadPDF() {
201
+ dummySVGContainer.innerHTML = svg;
202
+ var textElements = dummySVGContainer.getElementsByTagName('text'),
203
+ titleElements,
204
+ svgElementStyle = dummySVGContainer.getElementsByTagName('svg')[0].style;
205
+ // Workaround for the text styling. Making sure it does pick up the root element
206
+ each(textElements, function(el) {
207
+ // Workaround for the text styling. making sure it does pick up the root element
208
+ each(['font-family', 'font-size'], function(property) {
209
+ if (!el.style[property] && svgElementStyle[property]) {
210
+ el.style[property] = svgElementStyle[property];
211
+ }
212
+ });
213
+ el.style['font-family'] = el.style['font-family'] && el.style['font-family'].split(' ').splice(-1);
214
+ // Workaround for plotband with width, removing title from text nodes
215
+ titleElements = el.getElementsByTagName('title');
216
+ each(titleElements, function(titleElement) {
217
+ el.removeChild(titleElement);
218
+ });
219
+ });
220
+ var svgData = svgToPdf(dummySVGContainer.firstChild, 0);
221
+ Highcharts.downloadURL(svgData, filename);
222
+ if (successCallback) {
223
+ successCallback();
224
+ }
225
+ }
226
+
227
+ // Initiate download depending on file type
228
+ if (imageType === 'image/svg+xml') {
229
+ // SVG download. In this case, we want to use Microsoft specific Blob if available
230
+ try {
231
+ if (nav.msSaveOrOpenBlob) {
232
+ blob = new MSBlobBuilder();
233
+ blob.append(svg);
234
+ svgurl = blob.getBlob('image/svg+xml');
235
+ } else {
236
+ svgurl = Highcharts.svgToDataUrl(svg);
237
+ }
238
+ Highcharts.downloadURL(svgurl, filename);
239
+ if (successCallback) {
240
+ successCallback();
241
+ }
242
+ } catch (e) {
243
+ failCallback();
244
+ }
245
+ } else if (imageType === 'application/pdf') {
246
+ if (win.jsPDF && win.svgElementToPdf) {
247
+ downloadPDF();
248
+ } else {
249
+ // Must load pdf libraries first
250
+ objectURLRevoke = true; // Don't destroy the object URL yet since we are doing things asynchronously. A cleaner solution would be nice, but this will do for now.
251
+ getScript(libURL + 'jspdf.js', function() {
252
+ getScript(libURL + 'rgbcolor.js', function() {
253
+ getScript(libURL + 'svg2pdf.js', function() {
254
+ downloadPDF();
255
+ });
256
+ });
257
+ });
258
+ }
259
+ } else {
260
+ // PNG/JPEG download - create bitmap from SVG
261
+
262
+ svgurl = Highcharts.svgToDataUrl(svg);
263
+ finallyHandler = function() {
264
+ try {
265
+ domurl.revokeObjectURL(svgurl);
266
+ } catch (e) {
267
+ // Ignore
268
+ }
269
+ };
270
+ // First, try to get PNG by rendering on canvas
271
+ Highcharts.imageToDataUrl(svgurl, imageType, { /* args */ }, scale, function(imageURL) {
272
+ // Success
273
+ try {
274
+ Highcharts.downloadURL(imageURL, filename);
275
+ if (successCallback) {
276
+ successCallback();
277
+ }
278
+ } catch (e) {
279
+ failCallback();
280
+ }
281
+ }, function() {
282
+ // Failed due to tainted canvas
283
+ // Create new and untainted canvas
284
+ var canvas = doc.createElement('canvas'),
285
+ ctx = canvas.getContext('2d'),
286
+ imageWidth = svg.match(/^<svg[^>]*width\s*=\s*\"?(\d+)\"?[^>]*>/)[1] * scale,
287
+ imageHeight = svg.match(/^<svg[^>]*height\s*=\s*\"?(\d+)\"?[^>]*>/)[1] * scale,
288
+ downloadWithCanVG = function() {
289
+ ctx.drawSvg(svg, 0, 0, imageWidth, imageHeight);
290
+ try {
291
+ Highcharts.downloadURL(nav.msSaveOrOpenBlob ? canvas.msToBlob() : canvas.toDataURL(imageType), filename);
292
+ if (successCallback) {
293
+ successCallback();
294
+ }
295
+ } catch (e) {
296
+ failCallback();
297
+ } finally {
298
+ finallyHandler();
299
+ }
300
+ };
301
+
302
+ canvas.width = imageWidth;
303
+ canvas.height = imageHeight;
304
+ if (win.canvg) {
305
+ // Use preloaded canvg
306
+ downloadWithCanVG();
307
+ } else {
308
+ // Must load canVG first
309
+ objectURLRevoke = true; // Don't destroy the object URL yet since we are doing things asynchronously. A cleaner solution would be nice, but this will do for now.
310
+ getScript(libURL + 'rgbcolor.js', function() { // Get RGBColor.js first
311
+ getScript(libURL + 'canvg.js', function() {
312
+ downloadWithCanVG();
313
+ });
314
+ });
315
+ }
316
+ },
317
+ // No canvas support
318
+ failCallback,
319
+ // Failed to load image
320
+ failCallback,
321
+ // Finally
322
+ function() {
323
+ if (objectURLRevoke) {
324
+ finallyHandler();
325
+ }
326
+ });
327
+ }
328
+ };
329
+
330
+ // Get SVG of chart prepared for client side export. This converts embedded images in the SVG to data URIs.
331
+ // The options and chartOptions arguments are passed to the getSVGForExport function.
332
+ Highcharts.Chart.prototype.getSVGForLocalExport = function(options, chartOptions, failCallback, successCallback) {
333
+ var chart = this,
334
+ images,
335
+ imagesEmbedded = 0,
336
+ chartCopyContainer,
337
+ chartCopyOptions,
338
+ el,
339
+ i,
340
+ l,
341
+ // After grabbing the SVG of the chart's copy container we need to do sanitation on the SVG
342
+ sanitize = function(svg) {
343
+ return chart.sanitizeSVG(svg, chartCopyOptions);
344
+ },
345
+ // Success handler, we converted image to base64!
346
+ embeddedSuccess = function(imageURL, imageType, callbackArgs) {
347
+ ++imagesEmbedded;
348
+
349
+ // Change image href in chart copy
350
+ callbackArgs.imageElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', imageURL);
351
+
352
+ // When done with last image we have our SVG
353
+ if (imagesEmbedded === images.length) {
354
+ successCallback(sanitize(chartCopyContainer.innerHTML));
355
+ }
356
+ };
357
+
358
+ // Hook into getSVG to get a copy of the chart copy's container
359
+ Highcharts.wrap(
360
+ Highcharts.Chart.prototype,
361
+ 'getChartHTML',
362
+ function(proceed) {
363
+ var ret = proceed.apply(
364
+ this,
365
+ Array.prototype.slice.call(arguments, 1)
366
+ );
367
+ chartCopyOptions = this.options;
368
+ chartCopyContainer = this.container.cloneNode(true);
369
+ return ret;
370
+ }
371
+ );
372
+
373
+ // Trigger hook to get chart copy
374
+ chart.getSVGForExport(options, chartOptions);
375
+ images = chartCopyContainer.getElementsByTagName('image');
376
+
377
+ try {
378
+ // If there are no images to embed, the SVG is okay now.
379
+ if (!images.length) {
380
+ successCallback(sanitize(chartCopyContainer.innerHTML)); // Use SVG of chart copy
381
+ return;
382
+ }
383
+
384
+ // Go through the images we want to embed
385
+ for (i = 0, l = images.length; i < l; ++i) {
386
+ el = images[i];
387
+ Highcharts.imageToDataUrl(el.getAttributeNS('http://www.w3.org/1999/xlink', 'href'), 'image/png', {
388
+ imageElement: el
389
+ }, options.scale,
390
+ embeddedSuccess,
391
+ // Tainted canvas
392
+ failCallback,
393
+ // No canvas support
394
+ failCallback,
395
+ // Failed to load source
396
+ failCallback
397
+ );
398
+ }
399
+ } catch (e) {
400
+ failCallback();
401
+ }
402
+ };
403
+
404
+ /**
405
+ * Add a new method to the Chart object to perform a local download
406
+ */
407
+ Highcharts.Chart.prototype.exportChartLocal = function(exportingOptions, chartOptions) {
408
+ var chart = this,
409
+ options = Highcharts.merge(chart.options.exporting, exportingOptions),
410
+ fallbackToExportServer = function() {
411
+ if (options.fallbackToExportServer === false) {
412
+ if (options.error) {
413
+ options.error();
414
+ } else {
415
+ throw 'Fallback to export server disabled';
416
+ }
417
+ } else {
418
+ chart.exportChart(options);
419
+ }
420
+ },
421
+ svgSuccess = function(svg) {
422
+ // If SVG contains foreignObjects all exports except SVG will fail,
423
+ // as both CanVG and svg2pdf choke on this. Gracefully fall back.
424
+ if (
425
+ svg.indexOf('<foreignObject') > -1 &&
426
+ options.type !== 'image/svg+xml'
427
+ ) {
428
+ fallbackToExportServer();
429
+ } else {
430
+ Highcharts.downloadSVGLocal(svg, options, fallbackToExportServer);
431
+ }
432
+ };
433
+
434
+ // If we have embedded images and are exporting to JPEG/PNG, Microsoft
435
+ // browsers won't handle it, so fall back.
436
+ if (
437
+ (isMSBrowser && options.type !== 'image/svg+xml' ||
438
+ options.type === 'application/pdf') &&
439
+ chart.container.getElementsByTagName('image').length
440
+ ) {
441
+ fallbackToExportServer();
442
+ return;
443
+ }
444
+
445
+ chart.getSVGForLocalExport(options, chartOptions, fallbackToExportServer, svgSuccess);
446
+ };
447
+
448
+ // Extend the default options to use the local exporter logic
449
+ merge(true, Highcharts.getOptions().exporting, {
450
+ libURL: 'https://code.highcharts.com/5.0.6/lib/',
451
+ buttons: {
452
+ contextButton: {
453
+ menuItems: [{
454
+ textKey: 'printChart',
455
+ onclick: function() {
456
+ this.print();
457
+ }
458
+ }, {
459
+ separator: true
460
+ }, {
461
+ textKey: 'downloadPNG',
462
+ onclick: function() {
463
+ this.exportChartLocal();
464
+ }
465
+ }, {
466
+ textKey: 'downloadJPEG',
467
+ onclick: function() {
468
+ this.exportChartLocal({
469
+ type: 'image/jpeg'
470
+ });
471
+ }
472
+ }, {
473
+ textKey: 'downloadSVG',
474
+ onclick: function() {
475
+ this.exportChartLocal({
476
+ type: 'image/svg+xml'
477
+ });
478
+ }
479
+ }, {
480
+ textKey: 'downloadPDF',
481
+ onclick: function() {
482
+ this.exportChartLocal({
483
+ type: 'application/pdf'
484
+ });
485
+ }
486
+ }]
487
+ }
488
+ }
489
+ });
490
+
491
+ }(Highcharts));
492
+ }));