You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
681 lines
27 KiB
JavaScript
681 lines
27 KiB
JavaScript
2 months ago
|
/**
|
||
|
* @license Highcharts JS v6.0.4 (2017-12-15)
|
||
|
* Client side exporting module
|
||
|
*
|
||
|
* (c) 2015 Torstein Honsi / Oystein Moseng
|
||
|
*
|
||
|
* License: www.highcharts.com/license
|
||
|
*/
|
||
|
'use strict';
|
||
|
(function(factory) {
|
||
|
if (typeof module === 'object' && module.exports) {
|
||
|
module.exports = factory;
|
||
|
} else {
|
||
|
factory(Highcharts);
|
||
|
}
|
||
|
}(function(Highcharts) {
|
||
|
(function(Highcharts) {
|
||
|
/**
|
||
|
* Client side exporting module
|
||
|
*
|
||
|
* (c) 2015 Torstein Honsi / Oystein Moseng
|
||
|
*
|
||
|
* License: www.highcharts.com/license
|
||
|
*/
|
||
|
|
||
|
/* global MSBlobBuilder */
|
||
|
|
||
|
var merge = Highcharts.merge,
|
||
|
win = Highcharts.win,
|
||
|
nav = win.navigator,
|
||
|
doc = win.document,
|
||
|
each = Highcharts.each,
|
||
|
domurl = win.URL || win.webkitURL || win,
|
||
|
isMSBrowser = /Edge\/|Trident\/|MSIE /.test(nav.userAgent),
|
||
|
isEdgeBrowser = /Edge\/\d+/.test(nav.userAgent),
|
||
|
// Milliseconds to defer image load event handlers to offset IE bug
|
||
|
loadEventDeferDelay = isMSBrowser ? 150 : 0;
|
||
|
|
||
|
// Dummy object so we can reuse our canvas-tools.js without errors
|
||
|
Highcharts.CanVGRenderer = {};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Downloads a script and executes a callback when done.
|
||
|
* @param {String} scriptLocation
|
||
|
* @param {Function} callback
|
||
|
*/
|
||
|
function getScript(scriptLocation, callback) {
|
||
|
var head = doc.getElementsByTagName('head')[0],
|
||
|
script = doc.createElement('script');
|
||
|
|
||
|
script.type = 'text/javascript';
|
||
|
script.src = scriptLocation;
|
||
|
script.onload = callback;
|
||
|
script.onerror = function() {
|
||
|
Highcharts.error('Error loading script ' + scriptLocation);
|
||
|
};
|
||
|
|
||
|
head.appendChild(script);
|
||
|
}
|
||
|
|
||
|
// Convert dataURL to Blob if supported, otherwise returns undefined
|
||
|
Highcharts.dataURLtoBlob = function(dataURL) {
|
||
|
if (
|
||
|
win.atob &&
|
||
|
win.ArrayBuffer &&
|
||
|
win.Uint8Array &&
|
||
|
win.Blob &&
|
||
|
domurl.createObjectURL
|
||
|
) {
|
||
|
// Try to convert data URL to Blob
|
||
|
var parts = dataURL.match(/data:([^;]*)(;base64)?,([0-9A-Za-z+/]+)/),
|
||
|
binStr = win.atob(parts[3]), // Assume base64 encoding
|
||
|
buf = new win.ArrayBuffer(binStr.length),
|
||
|
binary = new win.Uint8Array(buf),
|
||
|
blob;
|
||
|
|
||
|
for (var i = 0; i < binary.length; ++i) {
|
||
|
binary[i] = binStr.charCodeAt(i);
|
||
|
}
|
||
|
|
||
|
blob = new win.Blob([binary], {
|
||
|
'type': parts[1]
|
||
|
});
|
||
|
return domurl.createObjectURL(blob);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Download contents by dataURL/blob
|
||
|
Highcharts.downloadURL = function(dataURL, filename) {
|
||
|
var a = doc.createElement('a'),
|
||
|
windowRef;
|
||
|
|
||
|
// IE specific blob implementation
|
||
|
// Don't use for normal dataURLs
|
||
|
if (
|
||
|
typeof dataURL !== 'string' &&
|
||
|
!(dataURL instanceof String) &&
|
||
|
nav.msSaveOrOpenBlob
|
||
|
) {
|
||
|
nav.msSaveOrOpenBlob(dataURL, filename);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Some browsers have limitations for data URL lengths. Try to convert to
|
||
|
// Blob or fall back. Edge always needs that blob.
|
||
|
if (isEdgeBrowser || dataURL.length > 2000000) {
|
||
|
dataURL = Highcharts.dataURLtoBlob(dataURL);
|
||
|
if (!dataURL) {
|
||
|
throw 'Data URL length limit reached';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Try HTML5 download attr if supported
|
||
|
if (a.download !== undefined) {
|
||
|
a.href = dataURL;
|
||
|
a.download = filename; // HTML5 download attribute
|
||
|
doc.body.appendChild(a);
|
||
|
a.click();
|
||
|
doc.body.removeChild(a);
|
||
|
} else {
|
||
|
// No download attr, just opening data URI
|
||
|
try {
|
||
|
windowRef = win.open(dataURL, 'chart');
|
||
|
if (windowRef === undefined || windowRef === null) {
|
||
|
throw 'Failed to open window';
|
||
|
}
|
||
|
} catch (e) {
|
||
|
// window.open failed, trying location.href
|
||
|
win.location.href = dataURL;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Get blob URL from SVG code. Falls back to normal data URI.
|
||
|
Highcharts.svgToDataUrl = function(svg) {
|
||
|
// Webkit and not chrome
|
||
|
var webKit = (
|
||
|
nav.userAgent.indexOf('WebKit') > -1 &&
|
||
|
nav.userAgent.indexOf('Chrome') < 0
|
||
|
);
|
||
|
try {
|
||
|
// Safari requires data URI since it doesn't allow navigation to blob
|
||
|
// URLs. Firefox has an issue with Blobs and internal references,
|
||
|
// leading to gradients not working using Blobs (#4550)
|
||
|
if (!webKit && nav.userAgent.toLowerCase().indexOf('firefox') < 0) {
|
||
|
return domurl.createObjectURL(new win.Blob([svg], {
|
||
|
type: 'image/svg+xml;charset-utf-16'
|
||
|
}));
|
||
|
}
|
||
|
} catch (e) {
|
||
|
// Ignore
|
||
|
}
|
||
|
return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg);
|
||
|
};
|
||
|
|
||
|
// Get data:URL from image URL
|
||
|
// Pass in callbacks to handle results. finallyCallback is always called at the
|
||
|
// end of the process. Supplying this callback is optional. All callbacks
|
||
|
// receive four arguments: imageURL, imageType, callbackArgs and scale.
|
||
|
// callbackArgs is used only by callbacks and can contain whatever.
|
||
|
Highcharts.imageToDataUrl = function(
|
||
|
imageURL,
|
||
|
imageType,
|
||
|
callbackArgs,
|
||
|
scale,
|
||
|
successCallback,
|
||
|
taintedCallback,
|
||
|
noCanvasSupportCallback,
|
||
|
failedLoadCallback,
|
||
|
finallyCallback
|
||
|
) {
|
||
|
var img = new win.Image(),
|
||
|
taintedHandler,
|
||
|
loadHandler = function() {
|
||
|
setTimeout(function() {
|
||
|
var canvas = doc.createElement('canvas'),
|
||
|
ctx = canvas.getContext && canvas.getContext('2d'),
|
||
|
dataURL;
|
||
|
try {
|
||
|
if (!ctx) {
|
||
|
noCanvasSupportCallback(
|
||
|
imageURL,
|
||
|
imageType,
|
||
|
callbackArgs,
|
||
|
scale
|
||
|
);
|
||
|
} else {
|
||
|
canvas.height = img.height * scale;
|
||
|
canvas.width = img.width * scale;
|
||
|
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||
|
|
||
|
// Now we try to get the contents of the canvas.
|
||
|
try {
|
||
|
dataURL = canvas.toDataURL(imageType);
|
||
|
successCallback(
|
||
|
dataURL,
|
||
|
imageType,
|
||
|
callbackArgs,
|
||
|
scale
|
||
|
);
|
||
|
} catch (e) {
|
||
|
taintedHandler(
|
||
|
imageURL,
|
||
|
imageType,
|
||
|
callbackArgs,
|
||
|
scale
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
} finally {
|
||
|
if (finallyCallback) {
|
||
|
finallyCallback(
|
||
|
imageURL,
|
||
|
imageType,
|
||
|
callbackArgs,
|
||
|
scale
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
// IE bug where image is not always ready despite calling load
|
||
|
// event.
|
||
|
}, loadEventDeferDelay);
|
||
|
},
|
||
|
// Image load failed (e.g. invalid URL)
|
||
|
errorHandler = function() {
|
||
|
failedLoadCallback(imageURL, imageType, callbackArgs, scale);
|
||
|
if (finallyCallback) {
|
||
|
finallyCallback(imageURL, imageType, callbackArgs, scale);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// This is called on load if the image drawing to canvas failed with a
|
||
|
// security error. We retry the drawing with crossOrigin set to Anonymous.
|
||
|
taintedHandler = function() {
|
||
|
img = new win.Image();
|
||
|
taintedHandler = taintedCallback;
|
||
|
// Must be set prior to loading image source
|
||
|
img.crossOrigin = 'Anonymous';
|
||
|
img.onload = loadHandler;
|
||
|
img.onerror = errorHandler;
|
||
|
img.src = imageURL;
|
||
|
};
|
||
|
|
||
|
img.onload = loadHandler;
|
||
|
img.onerror = errorHandler;
|
||
|
img.src = imageURL;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Get data URL to an image of an SVG and call download on it
|
||
|
*
|
||
|
* options object:
|
||
|
* - filename: Name of resulting downloaded file without extension
|
||
|
* - type: File type of resulting download
|
||
|
* - scale: Scaling factor of downloaded image compared to source
|
||
|
* - libURL: URL pointing to location of dependency scripts to download on
|
||
|
* demand
|
||
|
*/
|
||
|
Highcharts.downloadSVGLocal = function(
|
||
|
svg,
|
||
|
options,
|
||
|
failCallback,
|
||
|
successCallback
|
||
|
) {
|
||
|
var svgurl,
|
||
|
blob,
|
||
|
objectURLRevoke = true,
|
||
|
finallyHandler,
|
||
|
libURL = options.libURL || Highcharts.getOptions().exporting.libURL,
|
||
|
dummySVGContainer = doc.createElement('div'),
|
||
|
imageType = options.type || 'image/png',
|
||
|
filename = (
|
||
|
(options.filename || 'chart') +
|
||
|
'.' +
|
||
|
(imageType === 'image/svg+xml' ? 'svg' : imageType.split('/')[1])
|
||
|
),
|
||
|
scale = options.scale || 1;
|
||
|
|
||
|
// Allow libURL to end with or without fordward slash
|
||
|
libURL = libURL.slice(-1) !== '/' ? libURL + '/' : libURL;
|
||
|
|
||
|
function svgToPdf(svgElement, margin) {
|
||
|
var width = svgElement.width.baseVal.value + 2 * margin,
|
||
|
height = svgElement.height.baseVal.value + 2 * margin,
|
||
|
pdf = new win.jsPDF( // eslint-disable-line new-cap
|
||
|
'l',
|
||
|
'pt', [width, height]
|
||
|
);
|
||
|
|
||
|
// Workaround for #7090, hidden elements were drawn anyway. It comes
|
||
|
// down to https://github.com/yWorks/svg2pdf.js/issues/28. Check this
|
||
|
// later.
|
||
|
each(
|
||
|
svgElement.querySelectorAll('*[visibility="hidden"]'),
|
||
|
function(node) {
|
||
|
node.parentNode.removeChild(node);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
win.svg2pdf(svgElement, pdf, {
|
||
|
removeInvalid: true
|
||
|
});
|
||
|
return pdf.output('datauristring');
|
||
|
}
|
||
|
|
||
|
function downloadPDF() {
|
||
|
dummySVGContainer.innerHTML = svg;
|
||
|
var textElements = dummySVGContainer.getElementsByTagName('text'),
|
||
|
titleElements,
|
||
|
svgData,
|
||
|
svgElementStyle = dummySVGContainer
|
||
|
.getElementsByTagName('svg')[0].style;
|
||
|
|
||
|
// Workaround for the text styling. Making sure it does pick up the root
|
||
|
// element
|
||
|
each(textElements, function(el) {
|
||
|
// Workaround for the text styling. making sure it does pick up the
|
||
|
// root element
|
||
|
each(['font-family', 'font-size'], function(property) {
|
||
|
if (!el.style[property] && svgElementStyle[property]) {
|
||
|
el.style[property] = svgElementStyle[property];
|
||
|
}
|
||
|
});
|
||
|
el.style['font-family'] = (
|
||
|
el.style['font-family'] &&
|
||
|
el.style['font-family'].split(' ').splice(-1)
|
||
|
);
|
||
|
|
||
|
// Workaround for plotband with width, removing title from text
|
||
|
// nodes
|
||
|
titleElements = el.getElementsByTagName('title');
|
||
|
each(titleElements, function(titleElement) {
|
||
|
el.removeChild(titleElement);
|
||
|
});
|
||
|
});
|
||
|
svgData = svgToPdf(dummySVGContainer.firstChild, 0);
|
||
|
try {
|
||
|
Highcharts.downloadURL(svgData, filename);
|
||
|
if (successCallback) {
|
||
|
successCallback();
|
||
|
}
|
||
|
} catch (e) {
|
||
|
failCallback();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Initiate download depending on file type
|
||
|
if (imageType === 'image/svg+xml') {
|
||
|
// SVG download. In this case, we want to use Microsoft specific Blob if
|
||
|
// available
|
||
|
try {
|
||
|
if (nav.msSaveOrOpenBlob) {
|
||
|
blob = new MSBlobBuilder();
|
||
|
blob.append(svg);
|
||
|
svgurl = blob.getBlob('image/svg+xml');
|
||
|
} else {
|
||
|
svgurl = Highcharts.svgToDataUrl(svg);
|
||
|
}
|
||
|
Highcharts.downloadURL(svgurl, filename);
|
||
|
if (successCallback) {
|
||
|
successCallback();
|
||
|
}
|
||
|
} catch (e) {
|
||
|
failCallback();
|
||
|
}
|
||
|
} else if (imageType === 'application/pdf') {
|
||
|
if (win.jsPDF && win.svg2pdf) {
|
||
|
downloadPDF();
|
||
|
} else {
|
||
|
// Must load pdf libraries first. // 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.
|
||
|
objectURLRevoke = true;
|
||
|
getScript(libURL + 'jspdf.js', function() {
|
||
|
getScript(libURL + 'svg2pdf.js', function() {
|
||
|
downloadPDF();
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
} else {
|
||
|
// PNG/JPEG download - create bitmap from SVG
|
||
|
|
||
|
svgurl = Highcharts.svgToDataUrl(svg);
|
||
|
finallyHandler = function() {
|
||
|
try {
|
||
|
domurl.revokeObjectURL(svgurl);
|
||
|
} catch (e) {
|
||
|
// Ignore
|
||
|
}
|
||
|
};
|
||
|
// First, try to get PNG by rendering on canvas
|
||
|
Highcharts.imageToDataUrl(
|
||
|
svgurl,
|
||
|
imageType, { /* args */ },
|
||
|
scale,
|
||
|
function(imageURL) {
|
||
|
// Success
|
||
|
try {
|
||
|
Highcharts.downloadURL(imageURL, filename);
|
||
|
if (successCallback) {
|
||
|
successCallback();
|
||
|
}
|
||
|
} catch (e) {
|
||
|
failCallback();
|
||
|
}
|
||
|
},
|
||
|
function() {
|
||
|
// Failed due to tainted canvas
|
||
|
// Create new and untainted canvas
|
||
|
var canvas = doc.createElement('canvas'),
|
||
|
ctx = canvas.getContext('2d'),
|
||
|
imageWidth = svg.match(
|
||
|
/^<svg[^>]*width\s*=\s*\"?(\d+)\"?[^>]*>/
|
||
|
)[1] * scale,
|
||
|
imageHeight = svg.match(
|
||
|
/^<svg[^>]*height\s*=\s*\"?(\d+)\"?[^>]*>/
|
||
|
)[1] * scale,
|
||
|
downloadWithCanVG = function() {
|
||
|
ctx.drawSvg(svg, 0, 0, imageWidth, imageHeight);
|
||
|
try {
|
||
|
Highcharts.downloadURL(
|
||
|
nav.msSaveOrOpenBlob ?
|
||
|
canvas.msToBlob() :
|
||
|
canvas.toDataURL(imageType),
|
||
|
filename
|
||
|
);
|
||
|
if (successCallback) {
|
||
|
successCallback();
|
||
|
}
|
||
|
} catch (e) {
|
||
|
failCallback();
|
||
|
} finally {
|
||
|
finallyHandler();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
canvas.width = imageWidth;
|
||
|
canvas.height = imageHeight;
|
||
|
if (win.canvg) {
|
||
|
// Use preloaded canvg
|
||
|
downloadWithCanVG();
|
||
|
} else {
|
||
|
// Must load canVG first. // 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.
|
||
|
objectURLRevoke = true;
|
||
|
// Get RGBColor.js first, then canvg
|
||
|
getScript(libURL + 'rgbcolor.js', function() {
|
||
|
getScript(libURL + 'canvg.js', function() {
|
||
|
downloadWithCanVG();
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
// No canvas support
|
||
|
failCallback,
|
||
|
// Failed to load image
|
||
|
failCallback,
|
||
|
// Finally
|
||
|
function() {
|
||
|
if (objectURLRevoke) {
|
||
|
finallyHandler();
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Get SVG of chart prepared for client side export. This converts embedded
|
||
|
// images in the SVG to data URIs. The options and chartOptions arguments are
|
||
|
// passed to the getSVGForExport function.
|
||
|
Highcharts.Chart.prototype.getSVGForLocalExport = function(
|
||
|
options,
|
||
|
chartOptions,
|
||
|
failCallback,
|
||
|
successCallback
|
||
|
) {
|
||
|
var chart = this,
|
||
|
images,
|
||
|
imagesEmbedded = 0,
|
||
|
chartCopyContainer,
|
||
|
chartCopyOptions,
|
||
|
el,
|
||
|
i,
|
||
|
l,
|
||
|
// After grabbing the SVG of the chart's copy container we need to do
|
||
|
// sanitation on the SVG
|
||
|
sanitize = function(svg) {
|
||
|
return chart.sanitizeSVG(svg, chartCopyOptions);
|
||
|
},
|
||
|
// Success handler, we converted image to base64!
|
||
|
embeddedSuccess = function(imageURL, imageType, callbackArgs) {
|
||
|
++imagesEmbedded;
|
||
|
|
||
|
// Change image href in chart copy
|
||
|
callbackArgs.imageElement.setAttributeNS(
|
||
|
'http://www.w3.org/1999/xlink',
|
||
|
'href',
|
||
|
imageURL
|
||
|
);
|
||
|
|
||
|
// When done with last image we have our SVG
|
||
|
if (imagesEmbedded === images.length) {
|
||
|
successCallback(sanitize(chartCopyContainer.innerHTML));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Hook into getSVG to get a copy of the chart copy's container
|
||
|
Highcharts.wrap(
|
||
|
Highcharts.Chart.prototype,
|
||
|
'getChartHTML',
|
||
|
function(proceed) {
|
||
|
var ret = proceed.apply(
|
||
|
this,
|
||
|
Array.prototype.slice.call(arguments, 1)
|
||
|
);
|
||
|
chartCopyOptions = this.options;
|
||
|
chartCopyContainer = this.container.cloneNode(true);
|
||
|
return ret;
|
||
|
}
|
||
|
);
|
||
|
|
||
|
// Trigger hook to get chart copy
|
||
|
chart.getSVGForExport(options, chartOptions);
|
||
|
images = chartCopyContainer.getElementsByTagName('image');
|
||
|
|
||
|
try {
|
||
|
// If there are no images to embed, the SVG is okay now.
|
||
|
if (!images.length) {
|
||
|
// Use SVG of chart copy
|
||
|
successCallback(sanitize(chartCopyContainer.innerHTML));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Go through the images we want to embed
|
||
|
for (i = 0, l = images.length; i < l; ++i) {
|
||
|
el = images[i];
|
||
|
Highcharts.imageToDataUrl(el.getAttributeNS(
|
||
|
'http://www.w3.org/1999/xlink',
|
||
|
'href'
|
||
|
), 'image/png', {
|
||
|
imageElement: el
|
||
|
}, options.scale,
|
||
|
embeddedSuccess,
|
||
|
// Tainted canvas
|
||
|
failCallback,
|
||
|
// No canvas support
|
||
|
failCallback,
|
||
|
// Failed to load source
|
||
|
failCallback
|
||
|
);
|
||
|
}
|
||
|
} catch (e) {
|
||
|
failCallback();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Exporting and offline-exporting modules required. Export a chart to an image
|
||
|
* locally in the user's browser.
|
||
|
*
|
||
|
* @param {Object} exportingOptions
|
||
|
* Exporting options, the same as in {@link
|
||
|
* Highcharts.Chart#exportChart}.
|
||
|
* @param {Options} chartOptions
|
||
|
* Additional chart options for the exported chart. For example a
|
||
|
* different background color can be added here, or `dataLabels`
|
||
|
* for export only.
|
||
|
*/
|
||
|
Highcharts.Chart.prototype.exportChartLocal = function(
|
||
|
exportingOptions,
|
||
|
chartOptions
|
||
|
) {
|
||
|
var chart = this,
|
||
|
options = Highcharts.merge(chart.options.exporting, exportingOptions),
|
||
|
fallbackToExportServer = function() {
|
||
|
if (options.fallbackToExportServer === false) {
|
||
|
if (options.error) {
|
||
|
options.error(options);
|
||
|
} else {
|
||
|
throw 'Fallback to export server disabled';
|
||
|
}
|
||
|
} else {
|
||
|
chart.exportChart(options);
|
||
|
}
|
||
|
},
|
||
|
svgSuccess = function(svg) {
|
||
|
// If SVG contains foreignObjects all exports except SVG will fail,
|
||
|
// as both CanVG and svg2pdf choke on this. Gracefully fall back.
|
||
|
if (
|
||
|
svg.indexOf('<foreignObject') > -1 &&
|
||
|
options.type !== 'image/svg+xml'
|
||
|
) {
|
||
|
fallbackToExportServer();
|
||
|
} else {
|
||
|
Highcharts.downloadSVGLocal(
|
||
|
svg,
|
||
|
options,
|
||
|
fallbackToExportServer
|
||
|
);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// If we are on IE and in styled mode, add a whitelist to the renderer for
|
||
|
// inline styles that we want to pass through. There are so many styles by
|
||
|
// default in IE that we don't want to blacklist them all.
|
||
|
|
||
|
|
||
|
// Always fall back on:
|
||
|
// - MS browsers: Embedded images JPEG/PNG, or any PDF
|
||
|
// - Embedded images and PDF
|
||
|
if (
|
||
|
(
|
||
|
isMSBrowser &&
|
||
|
(
|
||
|
options.type === 'application/pdf' ||
|
||
|
chart.container.getElementsByTagName('image').length &&
|
||
|
options.type !== 'image/svg+xml'
|
||
|
)
|
||
|
) || (
|
||
|
options.type === 'application/pdf' &&
|
||
|
chart.container.getElementsByTagName('image').length
|
||
|
)
|
||
|
) {
|
||
|
fallbackToExportServer();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
chart.getSVGForLocalExport(
|
||
|
options,
|
||
|
chartOptions,
|
||
|
fallbackToExportServer,
|
||
|
svgSuccess
|
||
|
);
|
||
|
};
|
||
|
|
||
|
// Extend the default options to use the local exporter logic
|
||
|
merge(true, Highcharts.getOptions().exporting, {
|
||
|
libURL: 'https://code.highcharts.com/6.0.4/lib/',
|
||
|
|
||
|
// When offline-exporting is loaded, redefine the menu item definitions
|
||
|
// related to download.
|
||
|
menuItemDefinitions: {
|
||
|
downloadPNG: {
|
||
|
textKey: 'downloadPNG',
|
||
|
onclick: function() {
|
||
|
this.exportChartLocal();
|
||
|
}
|
||
|
},
|
||
|
downloadJPEG: {
|
||
|
textKey: 'downloadJPEG',
|
||
|
onclick: function() {
|
||
|
this.exportChartLocal({
|
||
|
type: 'image/jpeg'
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
downloadSVG: {
|
||
|
textKey: 'downloadSVG',
|
||
|
onclick: function() {
|
||
|
this.exportChartLocal({
|
||
|
type: 'image/svg+xml'
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
downloadPDF: {
|
||
|
textKey: 'downloadPDF',
|
||
|
onclick: function() {
|
||
|
this.exportChartLocal({
|
||
|
type: 'application/pdf'
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
});
|
||
|
|
||
|
}(Highcharts));
|
||
|
}));
|