corrade-nucleus-nucleons – Blame information for rev 20

Subversion Repositories:
Rev:
Rev Author Line No. Line
20 office 1 /**
2 * @license Highcharts JS v5.0.12 (2017-05-24)
3 * Exporting module
4 *
5 * (c) 2010-2017 Torstein Honsi
6 *
7 * License: www.highcharts.com/license
8 */
9 'use strict';
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 * Exporting module
20 *
21 * (c) 2010-2017 Torstein Honsi
22 *
23 * License: www.highcharts.com/license
24 */
25  
26 /* eslint indent:0 */
27  
28 // create shortcuts
29 var defaultOptions = H.defaultOptions,
30 doc = H.doc,
31 Chart = H.Chart,
32 addEvent = H.addEvent,
33 removeEvent = H.removeEvent,
34 fireEvent = H.fireEvent,
35 createElement = H.createElement,
36 discardElement = H.discardElement,
37 css = H.css,
38 merge = H.merge,
39 pick = H.pick,
40 each = H.each,
41 objectEach = H.objectEach,
42 extend = H.extend,
43 isTouchDevice = H.isTouchDevice,
44 win = H.win,
45 userAgent = win.navigator.userAgent,
46 SVGRenderer = H.SVGRenderer,
47 symbols = H.Renderer.prototype.symbols,
48 isMSBrowser = /Edge\/|Trident\/|MSIE /.test(userAgent),
49 isFirefoxBrowser = /firefox/i.test(userAgent);
50  
51 // Add language
52 extend(defaultOptions.lang, {
53 printChart: 'Print chart',
54 downloadPNG: 'Download PNG image',
55 downloadJPEG: 'Download JPEG image',
56 downloadPDF: 'Download PDF document',
57 downloadSVG: 'Download SVG vector image',
58 contextButtonTitle: 'Chart context menu'
59 });
60  
61 // Buttons and menus are collected in a separate config option set called 'navigation'.
62 // This can be extended later to add control buttons like zoom and pan right click menus.
63 defaultOptions.navigation = {
64 buttonOptions: {
65 theme: {},
66 symbolSize: 14,
67 symbolX: 12.5,
68 symbolY: 10.5,
69 align: 'right',
70 buttonSpacing: 3,
71 height: 22,
72 // text: null,
73 verticalAlign: 'top',
74 width: 24
75 }
76 };
77  
78  
79 // Presentational attributes
80 merge(true, defaultOptions.navigation, {
81 menuStyle: {
82 border: '1px solid #999999',
83 background: '#ffffff',
84 padding: '5px 0'
85 },
86 menuItemStyle: {
87 padding: '0.5em 1em',
88 background: 'none',
89 color: '#333333',
90 fontSize: isTouchDevice ? '14px' : '11px',
91 transition: 'background 250ms, color 250ms'
92 },
93 menuItemHoverStyle: {
94 background: '#335cad',
95 color: '#ffffff'
96 },
97 buttonOptions: {
98 symbolFill: '#666666',
99 symbolStroke: '#666666',
100 symbolStrokeWidth: 3,
101 theme: {
102 fill: '#ffffff', // capture hover
103 stroke: 'none',
104 padding: 5
105 }
106 }
107 });
108  
109  
110  
111 // Add the export related options
112 defaultOptions.exporting = {
113 //enabled: true,
114 //filename: 'chart',
115 type: 'image/png',
116 url: 'https://export.highcharts.com/',
117 //width: undefined,
118 printMaxWidth: 780,
119 scale: 2,
120 buttons: {
121 contextButton: {
122 className: 'highcharts-contextbutton',
123 menuClassName: 'highcharts-contextmenu',
124 //x: -10,
125 symbol: 'menu',
126 _titleKey: 'contextButtonTitle',
127 menuItems: [{
128 textKey: 'printChart',
129 onclick: function() {
130 this.print();
131 }
132 }, {
133 separator: true
134 }, {
135 textKey: 'downloadPNG',
136 onclick: function() {
137 this.exportChart();
138 }
139 }, {
140 textKey: 'downloadJPEG',
141 onclick: function() {
142 this.exportChart({
143 type: 'image/jpeg'
144 });
145 }
146 }, {
147 textKey: 'downloadPDF',
148 onclick: function() {
149 this.exportChart({
150 type: 'application/pdf'
151 });
152 }
153 }, {
154 textKey: 'downloadSVG',
155 onclick: function() {
156 this.exportChart({
157 type: 'image/svg+xml'
158 });
159 }
160 }]
161 }
162 }
163 };
164  
165 // Add the H.post utility
166 H.post = function(url, data, formAttributes) {
167 // create the form
168 var form = createElement('form', merge({
169 method: 'post',
170 action: url,
171 enctype: 'multipart/form-data'
172 }, formAttributes), {
173 display: 'none'
174 }, doc.body);
175  
176 // add the data
177 objectEach(data, function(val, name) {
178 createElement('input', {
179 type: 'hidden',
180 name: name,
181 value: val
182 }, null, form);
183 });
184  
185 // submit
186 form.submit();
187  
188 // clean up
189 discardElement(form);
190 };
191  
192 extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ {
193  
194 /**
195 * A collection of fixes on the produced SVG to account for expando properties,
196 * browser bugs, VML problems and other. Returns a cleaned SVG.
197 */
198 sanitizeSVG: function(svg, options) {
199 // Move HTML into a foreignObject
200 if (options && options.exporting && options.exporting.allowHTML) {
201 var html = svg.match(/<\/svg>(.*?$)/);
202 <\/svg> if (html && html[1]) {
203 <\/svg> html = '<foreignObject x="0" y="0" ' +
204 <\/svg> 'width="' + options.chart.width + '" ' +
205 <\/svg> 'height="' + options.chart.height + '">' +
206 <\/svg> '<body xmlns="http://www.w3.org/1999/xhtml">' +
207 <\/svg> html[1] +
208 <\/svg> '</body>' +
209 <\/svg> '</foreignObject>';
210 <\/svg> svg = svg.replace('</svg>', html + '</svg>');
211 <\/svg> }
212 <\/svg> }
213  
214 <\/svg> svg = svg
215 <\/svg> .replace(/zIndex="[^"]+"/g, '')
216 <\/svg> .replace(/isShadow="[^"]+"/g, '')
217 <\/svg> .replace(/symbolName="[^"]+"/g, '')
218 <\/svg> .replace(/jQuery[0-9]+="[^"]+"/g, '')
219 <\/svg> .replace(/url\(("|")(\S+)("|")\)/g, 'url($2)')
220 <\/svg> .replace(/url\([^#]+#/g, 'url(#')
221 <\/svg> .replace(/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ')
222 <\/svg> .replace(/ (NS[0-9]+\:)?href=/g, ' xlink:href=') // #3567
223 <\/svg> .replace(/\n/, ' ')
224 <\/svg> // Any HTML added to the container after the SVG (#894)
225 <\/svg> .replace(/<\/svg>.*?$/, '</svg>')
226 <\/svg><\/svg> // Batik doesn't support rgba fills and strokes (#3095)
227 <\/svg><\/svg> .replace(/(fill|stroke)="rgba\(([ 0-9]+,[ 0-9]+,[ 0-9]+),([ 0-9\.]+)\)"/g, '$1="rgb($2)" $1-opacity="$3"')
228 <\/svg><\/svg> /* This fails in IE < 8
229 <\/svg><\/svg> .replace(/([0-9]+)\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight
230 <\/svg><\/svg> return s2 +'.'+ s3[0];
231 <\/svg><\/svg> })*/
232  
233 <\/svg><\/svg> // Replace HTML entities, issue #347
234 <\/svg><\/svg> .replace(/ /g, '\u00A0') // no-break space
235 <\/svg><\/svg> .replace(/­/g, '\u00AD'); // soft hyphen
236  
237  
238 <\/svg><\/svg> // IE specific
239 <\/svg><\/svg> svg = svg
240 <\/svg><\/svg> .replace(/g, '<image ')
241 <\/svg><\/svg> .replace(/<(\/?)TITLE>/g, '<$1title>')
242 <\/svg><\/svg><(\/?)TITLE> .replace(/height=([^" ]+)/g, 'height="$1"')
243 <\/svg><\/svg><(\/?)TITLE> .replace(/width=([^" ]+)/g, 'width="$1"')
244 <\/svg><\/svg><(\/?)TITLE> .replace(/hc-svg-href="([^"]+)">/g, 'xlink:href="$1"/>')
245 <\/svg><\/svg><(\/?)TITLE> .replace(/ id=([^" >]+)/g, ' id="$1"') // #4003
246 <\/svg><\/svg><(\/?)TITLE> .replace(/class=([^" >]+)/g, 'class="$1"')
247 <\/svg><\/svg><(\/?)TITLE> .replace(/ transform /g, ' ')
248 <\/svg><\/svg><(\/?)TITLE> .replace(/:(path|rect)/g, '$1')
249 <\/svg><\/svg><(\/?)TITLE> .replace(/style="([^"]+)"/g, function(s) {
250 <\/svg><\/svg><(\/?)TITLE> return s.toLowerCase();
251 <\/svg><\/svg><(\/?)TITLE> });
252  
253  
254 <\/svg><\/svg><(\/?)TITLE> return svg;
255 <\/svg><\/svg><(\/?)TITLE> },
256  
257 <\/svg><\/svg><(\/?)TITLE> /**
258 <\/svg><\/svg><(\/?)TITLE> * Return innerHTML of chart. Used as hook for plugins.
259 <\/svg><\/svg><(\/?)TITLE> */
260 <\/svg><\/svg><(\/?)TITLE> getChartHTML: function() {
261  
262 <\/svg><\/svg><(\/?)TITLE> return this.container.innerHTML;
263 <\/svg><\/svg><(\/?)TITLE> },
264  
265 <\/svg><\/svg><(\/?)TITLE> /**
266 <\/svg><\/svg><(\/?)TITLE> * Return an SVG representation of the chart.
267 <\/svg><\/svg><(\/?)TITLE> *
268 <\/svg><\/svg><(\/?)TITLE> * @param chartOptions {Options}
269 <\/svg><\/svg><(\/?)TITLE> * Additional chart options for the generated SVG representation.
270 <\/svg><\/svg><(\/?)TITLE> * For collections like `xAxis`, `yAxis` or `series`, the additional
271 <\/svg><\/svg><(\/?)TITLE> * options is either merged in to the orininal item of the same
272 <\/svg><\/svg><(\/?)TITLE> * `id`, or to the first item if a common id is not found.
273 <\/svg><\/svg><(\/?)TITLE> * @return {String}
274 <\/svg><\/svg><(\/?)TITLE> * The SVG representation of the rendered chart.
275 <\/svg><\/svg><(\/?)TITLE> * @sample highcharts/members/chart-getsvg/
276 <\/svg><\/svg><(\/?)TITLE> * View the SVG from a button
277 <\/svg><\/svg><(\/?)TITLE> */
278 <\/svg><\/svg><(\/?)TITLE> getSVG: function(chartOptions) {
279 <\/svg><\/svg><(\/?)TITLE> var chart = this,
280 <\/svg><\/svg><(\/?)TITLE> chartCopy,
281 <\/svg><\/svg><(\/?)TITLE> sandbox,
282 <\/svg><\/svg><(\/?)TITLE> svg,
283 <\/svg><\/svg><(\/?)TITLE> seriesOptions,
284 <\/svg><\/svg><(\/?)TITLE> sourceWidth,
285 <\/svg><\/svg><(\/?)TITLE> sourceHeight,
286 <\/svg><\/svg><(\/?)TITLE> cssWidth,
287 <\/svg><\/svg><(\/?)TITLE> cssHeight,
288 <\/svg><\/svg><(\/?)TITLE> options = merge(chart.options, chartOptions); // copy the options and add extra options
289  
290  
291 <\/svg><\/svg><(\/?)TITLE> // IE compatibility hack for generating SVG content that it doesn't really understand
292 <\/svg><\/svg><(\/?)TITLE> if (!doc.createElementNS) {
293 <\/svg><\/svg><(\/?)TITLE> doc.createElementNS = function(ns, tagName) {
294 <\/svg><\/svg><(\/?)TITLE> return doc.createElement(tagName);
295 <\/svg><\/svg><(\/?)TITLE> };
296 <\/svg><\/svg><(\/?)TITLE> }
297  
298 <\/svg><\/svg><(\/?)TITLE> // create a sandbox where a new chart will be generated
299 <\/svg><\/svg><(\/?)TITLE> sandbox = createElement('div', null, {
300 <\/svg><\/svg><(\/?)TITLE> position: 'absolute',
301 <\/svg><\/svg><(\/?)TITLE> top: '-9999em',
302 <\/svg><\/svg><(\/?)TITLE> width: chart.chartWidth + 'px',
303 <\/svg><\/svg><(\/?)TITLE> height: chart.chartHeight + 'px'
304 <\/svg><\/svg><(\/?)TITLE> }, doc.body);
305  
306 <\/svg><\/svg><(\/?)TITLE> // get the source size
307 <\/svg><\/svg><(\/?)TITLE> cssWidth = chart.renderTo.style.width;
308 <\/svg><\/svg><(\/?)TITLE> cssHeight = chart.renderTo.style.height;
309 <\/svg><\/svg><(\/?)TITLE> sourceWidth = options.exporting.sourceWidth ||
310 <\/svg><\/svg><(\/?)TITLE> options.chart.width ||
311 <\/svg><\/svg><(\/?)TITLE> (/px$/.test(cssWidth) && parseInt(cssWidth, 10)) ||
312 <\/svg><\/svg><(\/?)TITLE> 600;
313 <\/svg><\/svg><(\/?)TITLE> sourceHeight = options.exporting.sourceHeight ||
314 <\/svg><\/svg><(\/?)TITLE> options.chart.height ||
315 <\/svg><\/svg><(\/?)TITLE> (/px$/.test(cssHeight) && parseInt(cssHeight, 10)) ||
316 <\/svg><\/svg><(\/?)TITLE> 400;
317  
318 <\/svg><\/svg><(\/?)TITLE> // override some options
319 <\/svg><\/svg><(\/?)TITLE> extend(options.chart, {
320 <\/svg><\/svg><(\/?)TITLE> animation: false,
321 <\/svg><\/svg><(\/?)TITLE> renderTo: sandbox,
322 <\/svg><\/svg><(\/?)TITLE> forExport: true,
323 <\/svg><\/svg><(\/?)TITLE> renderer: 'SVGRenderer',
324 <\/svg><\/svg><(\/?)TITLE> width: sourceWidth,
325 <\/svg><\/svg><(\/?)TITLE> height: sourceHeight
326 <\/svg><\/svg><(\/?)TITLE> });
327 <\/svg><\/svg><(\/?)TITLE> options.exporting.enabled = false; // hide buttons in print
328 <\/svg><\/svg><(\/?)TITLE> delete options.data; // #3004
329  
330 <\/svg><\/svg><(\/?)TITLE> // prepare for replicating the chart
331 <\/svg><\/svg><(\/?)TITLE> options.series = [];
332 <\/svg><\/svg><(\/?)TITLE> each(chart.series, function(serie) {
333 <\/svg><\/svg><(\/?)TITLE> seriesOptions = merge(serie.userOptions, { // #4912
334 <\/svg><\/svg><(\/?)TITLE> animation: false, // turn off animation
335 <\/svg><\/svg><(\/?)TITLE> enableMouseTracking: false,
336 <\/svg><\/svg><(\/?)TITLE> showCheckbox: false,
337 <\/svg><\/svg><(\/?)TITLE> visible: serie.visible
338 <\/svg><\/svg><(\/?)TITLE> });
339  
340 <\/svg><\/svg><(\/?)TITLE> if (!seriesOptions.isInternal) { // used for the navigator series that has its own option set
341 <\/svg><\/svg><(\/?)TITLE> options.series.push(seriesOptions);
342 <\/svg><\/svg><(\/?)TITLE> }
343 <\/svg><\/svg><(\/?)TITLE> });
344  
345 <\/svg><\/svg><(\/?)TITLE> // Assign an internal key to ensure a one-to-one mapping (#5924)
346 <\/svg><\/svg><(\/?)TITLE> each(chart.axes, function(axis) {
347 <\/svg><\/svg><(\/?)TITLE> if (!axis.userOptions.internalKey) { // #6444
348 <\/svg><\/svg><(\/?)TITLE> axis.userOptions.internalKey = H.uniqueKey();
349 <\/svg><\/svg><(\/?)TITLE> }
350 <\/svg><\/svg><(\/?)TITLE> });
351  
352 <\/svg><\/svg><(\/?)TITLE> // generate the chart copy
353 <\/svg><\/svg><(\/?)TITLE> chartCopy = new H.Chart(options, chart.callback);
354  
355 <\/svg><\/svg><(\/?)TITLE> // Axis options and series options (#2022, #3900, #5982)
356 <\/svg><\/svg><(\/?)TITLE> if (chartOptions) {
357 <\/svg><\/svg><(\/?)TITLE> each(['xAxis', 'yAxis', 'series'], function(coll) {
358 <\/svg><\/svg><(\/?)TITLE> var collOptions = {};
359 <\/svg><\/svg><(\/?)TITLE> if (chartOptions[coll]) {
360 <\/svg><\/svg><(\/?)TITLE> collOptions[coll] = chartOptions[coll];
361 <\/svg><\/svg><(\/?)TITLE> chartCopy.update(collOptions);
362 <\/svg><\/svg><(\/?)TITLE> }
363 <\/svg><\/svg><(\/?)TITLE> });
364 <\/svg><\/svg><(\/?)TITLE> }
365  
366 <\/svg><\/svg><(\/?)TITLE> // Reflect axis extremes in the export (#5924)
367 <\/svg><\/svg><(\/?)TITLE> each(chart.axes, function(axis) {
368 <\/svg><\/svg><(\/?)TITLE> var axisCopy = H.find(chartCopy.axes, function(copy) {
369 <\/svg><\/svg><(\/?)TITLE> return copy.options.internalKey ===
370 <\/svg><\/svg><(\/?)TITLE> axis.userOptions.internalKey;
371 <\/svg><\/svg><(\/?)TITLE> }),
372 <\/svg><\/svg><(\/?)TITLE> extremes = axis.getExtremes(),
373 <\/svg><\/svg><(\/?)TITLE> userMin = extremes.userMin,
374 <\/svg><\/svg><(\/?)TITLE> userMax = extremes.userMax;
375  
376 <\/svg><\/svg><(\/?)TITLE> if (axisCopy && (userMin !== undefined || userMax !== undefined)) {
377 <\/svg><\/svg><(\/?)TITLE> axisCopy.setExtremes(userMin, userMax, true, false);
378 <\/svg><\/svg><(\/?)TITLE> }
379 <\/svg><\/svg><(\/?)TITLE> });
380  
381 <\/svg><\/svg><(\/?)TITLE> // Get the SVG from the container's innerHTML
382 <\/svg><\/svg><(\/?)TITLE> svg = chartCopy.getChartHTML();
383  
384 <\/svg><\/svg><(\/?)TITLE> svg = chart.sanitizeSVG(svg, options);
385  
386 <\/svg><\/svg><(\/?)TITLE> // free up memory
387 <\/svg><\/svg><(\/?)TITLE> options = null;
388 <\/svg><\/svg><(\/?)TITLE> chartCopy.destroy();
389 <\/svg><\/svg><(\/?)TITLE> discardElement(sandbox);
390  
391 <\/svg><\/svg><(\/?)TITLE> return svg;
392 <\/svg><\/svg><(\/?)TITLE> },
393  
394 <\/svg><\/svg><(\/?)TITLE> getSVGForExport: function(options, chartOptions) {
395 <\/svg><\/svg><(\/?)TITLE> var chartExportingOptions = this.options.exporting;
396  
397 <\/svg><\/svg><(\/?)TITLE> return this.getSVG(merge({
398 <\/svg><\/svg><(\/?)TITLE> chart: {
399 <\/svg><\/svg><(\/?)TITLE> borderRadius: 0
400 <\/svg><\/svg><(\/?)TITLE> }
401 <\/svg><\/svg><(\/?)TITLE> },
402 <\/svg><\/svg><(\/?)TITLE> chartExportingOptions.chartOptions,
403 <\/svg><\/svg><(\/?)TITLE> chartOptions, {
404 <\/svg><\/svg><(\/?)TITLE> exporting: {
405 <\/svg><\/svg><(\/?)TITLE> sourceWidth: (options && options.sourceWidth) || chartExportingOptions.sourceWidth,
406 <\/svg><\/svg><(\/?)TITLE> sourceHeight: (options && options.sourceHeight) || chartExportingOptions.sourceHeight
407 <\/svg><\/svg><(\/?)TITLE> }
408 <\/svg><\/svg><(\/?)TITLE> }
409 <\/svg><\/svg><(\/?)TITLE> ));
410 <\/svg><\/svg><(\/?)TITLE> },
411  
412 <\/svg><\/svg><(\/?)TITLE> /**
413 <\/svg><\/svg><(\/?)TITLE> * Exporting module required. Submit an SVG version of the chart to a server
414 <\/svg><\/svg><(\/?)TITLE> * along with some parameters for conversion.
415 <\/svg><\/svg><(\/?)TITLE> * @param {Object} exportingOptions
416 <\/svg><\/svg><(\/?)TITLE> * Exporting options in addition to those defined in {@link
417 <\/svg><\/svg><(\/?)TITLE> * https://api.highcharts.com/highcharts/exporting|exporting}.
418 <\/svg><\/svg><(\/?)TITLE> * @param {String} exportingOptions.filename
419 <\/svg><\/svg><(\/?)TITLE> * The file name for the export without extension.
420 <\/svg><\/svg><(\/?)TITLE> * @param {String} exportingOptions.url
421 <\/svg><\/svg><(\/?)TITLE> * The URL for the server module to do the conversion.
422 <\/svg><\/svg><(\/?)TITLE> * @param {Number} exportingOptions.width
423 <\/svg><\/svg><(\/?)TITLE> * The width of the PNG or JPG image generated on the server.
424 <\/svg><\/svg><(\/?)TITLE> * @param {String} exportingOptions.type
425 <\/svg><\/svg><(\/?)TITLE> * The MIME type of the converted image.
426 <\/svg><\/svg><(\/?)TITLE> * @param {Number} exportingOptions.sourceWidth
427 <\/svg><\/svg><(\/?)TITLE> * The pixel width of the source (in-page) chart.
428 <\/svg><\/svg><(\/?)TITLE> * @param {Number} exportingOptions.sourceHeight
429 <\/svg><\/svg><(\/?)TITLE> * The pixel height of the source (in-page) chart.
430 <\/svg><\/svg><(\/?)TITLE> * @param {Options} chartOptions
431 <\/svg><\/svg><(\/?)TITLE> * Additional chart options for the exported chart. For example a
432 <\/svg><\/svg><(\/?)TITLE> * different background color can be added here, or `dataLabels`
433 <\/svg><\/svg><(\/?)TITLE> * for export only.
434 <\/svg><\/svg><(\/?)TITLE> *
435 <\/svg><\/svg><(\/?)TITLE> * @sample highcharts/members/chart-exportchart/
436 <\/svg><\/svg><(\/?)TITLE> * Export with no options
437 <\/svg><\/svg><(\/?)TITLE> * @sample highcharts/members/chart-exportchart-filename/
438 <\/svg><\/svg><(\/?)TITLE> * PDF type and custom filename
439 <\/svg><\/svg><(\/?)TITLE> * @sample highcharts/members/chart-exportchart-custom-background/
440 <\/svg><\/svg><(\/?)TITLE> * Different chart background in export
441 <\/svg><\/svg><(\/?)TITLE> * @sample stock/members/chart-exportchart/
442 <\/svg><\/svg><(\/?)TITLE> * Export with Highstock
443 <\/svg><\/svg><(\/?)TITLE> */
444 <\/svg><\/svg><(\/?)TITLE> exportChart: function(exportingOptions, chartOptions) {
445  
446 <\/svg><\/svg><(\/?)TITLE> var svg = this.getSVGForExport(exportingOptions, chartOptions);
447  
448 <\/svg><\/svg><(\/?)TITLE> // merge the options
449 <\/svg><\/svg><(\/?)TITLE> exportingOptions = merge(this.options.exporting, exportingOptions);
450  
451 <\/svg><\/svg><(\/?)TITLE> // do the post
452 <\/svg><\/svg><(\/?)TITLE> H.post(exportingOptions.url, {
453 <\/svg><\/svg><(\/?)TITLE> filename: exportingOptions.filename || 'chart',
454 <\/svg><\/svg><(\/?)TITLE> type: exportingOptions.type,
455 <\/svg><\/svg><(\/?)TITLE> width: exportingOptions.width || 0, // IE8 fails to post undefined correctly, so use 0
456 <\/svg><\/svg><(\/?)TITLE> scale: exportingOptions.scale,
457 <\/svg><\/svg><(\/?)TITLE> svg: svg
458 <\/svg><\/svg><(\/?)TITLE> }, exportingOptions.formAttributes);
459  
460 <\/svg><\/svg><(\/?)TITLE> },
461  
462 <\/svg><\/svg><(\/?)TITLE> /**
463 <\/svg><\/svg><(\/?)TITLE> * Exporting module required. Clears away other elements in the page and
464 <\/svg><\/svg><(\/?)TITLE> * prints the chart as it is displayed. By default, when the exporting
465 <\/svg><\/svg><(\/?)TITLE> * module is enabled, a context button with a drop down menu in the upper
466 <\/svg><\/svg><(\/?)TITLE> * right corner accesses this function.
467 <\/svg><\/svg><(\/?)TITLE> *
468 <\/svg><\/svg><(\/?)TITLE> * @sample highcharts/members/chart-print/
469 <\/svg><\/svg><(\/?)TITLE> * Print from a HTML button
470 <\/svg><\/svg><(\/?)TITLE> */
471 <\/svg><\/svg><(\/?)TITLE> print: function() {
472  
473 <\/svg><\/svg><(\/?)TITLE> var chart = this,
474 <\/svg><\/svg><(\/?)TITLE> container = chart.container,
475 <\/svg><\/svg><(\/?)TITLE> origDisplay = [],
476 <\/svg><\/svg><(\/?)TITLE> origParent = container.parentNode,
477 <\/svg><\/svg><(\/?)TITLE> body = doc.body,
478 <\/svg><\/svg><(\/?)TITLE> childNodes = body.childNodes,
479 <\/svg><\/svg><(\/?)TITLE> printMaxWidth = chart.options.exporting.printMaxWidth,
480 <\/svg><\/svg><(\/?)TITLE> resetParams,
481 <\/svg><\/svg><(\/?)TITLE> handleMaxWidth;
482  
483 <\/svg><\/svg><(\/?)TITLE> if (chart.isPrinting) { // block the button while in printing mode
484 <\/svg><\/svg><(\/?)TITLE> return;
485 <\/svg><\/svg><(\/?)TITLE> }
486  
487 <\/svg><\/svg><(\/?)TITLE> chart.isPrinting = true;
488 <\/svg><\/svg><(\/?)TITLE> chart.pointer.reset(null, 0);
489  
490 <\/svg><\/svg><(\/?)TITLE> fireEvent(chart, 'beforePrint');
491  
492 <\/svg><\/svg><(\/?)TITLE> // Handle printMaxWidth
493 <\/svg><\/svg><(\/?)TITLE> handleMaxWidth = printMaxWidth && chart.chartWidth > printMaxWidth;
494 <\/svg><\/svg><(\/?)TITLE> if (handleMaxWidth) {
495 <\/svg><\/svg><(\/?)TITLE> resetParams = [chart.options.chart.width, undefined, false];
496 <\/svg><\/svg><(\/?)TITLE> chart.setSize(printMaxWidth, undefined, false);
497 <\/svg><\/svg><(\/?)TITLE> }
498  
499 <\/svg><\/svg><(\/?)TITLE> // hide all body content
500 <\/svg><\/svg><(\/?)TITLE> each(childNodes, function(node, i) {
501 <\/svg><\/svg><(\/?)TITLE> if (node.nodeType === 1) {
502 <\/svg><\/svg><(\/?)TITLE> origDisplay[i] = node.style.display;
503 <\/svg><\/svg><(\/?)TITLE> node.style.display = 'none';
504 <\/svg><\/svg><(\/?)TITLE> }
505 <\/svg><\/svg><(\/?)TITLE> });
506  
507 <\/svg><\/svg><(\/?)TITLE> // pull out the chart
508 <\/svg><\/svg><(\/?)TITLE> body.appendChild(container);
509  
510 <\/svg><\/svg><(\/?)TITLE> // print
511 <\/svg><\/svg><(\/?)TITLE> win.focus(); // #1510
512 <\/svg><\/svg><(\/?)TITLE> win.print();
513  
514 <\/svg><\/svg><(\/?)TITLE> // allow the browser to prepare before reverting
515 <\/svg><\/svg><(\/?)TITLE> setTimeout(function() {
516  
517 <\/svg><\/svg><(\/?)TITLE> // put the chart back in
518 <\/svg><\/svg><(\/?)TITLE> origParent.appendChild(container);
519  
520 <\/svg><\/svg><(\/?)TITLE> // restore all body content
521 <\/svg><\/svg><(\/?)TITLE> each(childNodes, function(node, i) {
522 <\/svg><\/svg><(\/?)TITLE> if (node.nodeType === 1) {
523 <\/svg><\/svg><(\/?)TITLE> node.style.display = origDisplay[i];
524 <\/svg><\/svg><(\/?)TITLE> }
525 <\/svg><\/svg><(\/?)TITLE> });
526  
527 <\/svg><\/svg><(\/?)TITLE> chart.isPrinting = false;
528  
529 <\/svg><\/svg><(\/?)TITLE> // Reset printMaxWidth
530 <\/svg><\/svg><(\/?)TITLE> if (handleMaxWidth) {
531 <\/svg><\/svg><(\/?)TITLE> chart.setSize.apply(chart, resetParams);
532 <\/svg><\/svg><(\/?)TITLE> }
533  
534 <\/svg><\/svg><(\/?)TITLE> fireEvent(chart, 'afterPrint');
535  
536 <\/svg><\/svg><(\/?)TITLE> }, 1000);
537  
538 <\/svg><\/svg><(\/?)TITLE> },
539  
540 <\/svg><\/svg><(\/?)TITLE> /**
541 <\/svg><\/svg><(\/?)TITLE> * Display a popup menu for choosing the export type
542 <\/svg><\/svg><(\/?)TITLE> *
543 <\/svg><\/svg><(\/?)TITLE> * @param {String} className An identifier for the menu
544 <\/svg><\/svg><(\/?)TITLE> * @param {Array} items A collection with text and onclicks for the items
545 <\/svg><\/svg><(\/?)TITLE> * @param {Number} x The x position of the opener button
546 <\/svg><\/svg><(\/?)TITLE> * @param {Number} y The y position of the opener button
547 <\/svg><\/svg><(\/?)TITLE> * @param {Number} width The width of the opener button
548 <\/svg><\/svg><(\/?)TITLE> * @param {Number} height The height of the opener button
549 <\/svg><\/svg><(\/?)TITLE> */
550 <\/svg><\/svg><(\/?)TITLE> contextMenu: function(className, items, x, y, width, height, button) {
551 <\/svg><\/svg><(\/?)TITLE> var chart = this,
552 <\/svg><\/svg><(\/?)TITLE> navOptions = chart.options.navigation,
553 <\/svg><\/svg><(\/?)TITLE> chartWidth = chart.chartWidth,
554 <\/svg><\/svg><(\/?)TITLE> chartHeight = chart.chartHeight,
555 <\/svg><\/svg><(\/?)TITLE> cacheName = 'cache-' + className,
556 <\/svg><\/svg><(\/?)TITLE> menu = chart[cacheName],
557 <\/svg><\/svg><(\/?)TITLE> menuPadding = Math.max(width, height), // for mouse leave detection
558 <\/svg><\/svg><(\/?)TITLE> innerMenu,
559 <\/svg><\/svg><(\/?)TITLE> hide,
560 <\/svg><\/svg><(\/?)TITLE> menuStyle;
561  
562 <\/svg><\/svg><(\/?)TITLE> // create the menu only the first time
563 <\/svg><\/svg><(\/?)TITLE> if (!menu) {
564  
565 <\/svg><\/svg><(\/?)TITLE> // create a HTML element above the SVG
566 <\/svg><\/svg><(\/?)TITLE> chart[cacheName] = menu = createElement('div', {
567 <\/svg><\/svg><(\/?)TITLE> className: className
568 <\/svg><\/svg><(\/?)TITLE> }, {
569 <\/svg><\/svg><(\/?)TITLE> position: 'absolute',
570 <\/svg><\/svg><(\/?)TITLE> zIndex: 1000,
571 <\/svg><\/svg><(\/?)TITLE> padding: menuPadding + 'px'
572 <\/svg><\/svg><(\/?)TITLE> }, chart.container);
573  
574 <\/svg><\/svg><(\/?)TITLE> innerMenu = createElement('div', {
575 <\/svg><\/svg><(\/?)TITLE> className: 'highcharts-menu'
576 <\/svg><\/svg><(\/?)TITLE> }, null, menu);
577  
578  
579 <\/svg><\/svg><(\/?)TITLE> // Presentational CSS
580 <\/svg><\/svg><(\/?)TITLE> css(innerMenu, extend({
581 <\/svg><\/svg><(\/?)TITLE> MozBoxShadow: '3px 3px 10px #888',
582 <\/svg><\/svg><(\/?)TITLE> WebkitBoxShadow: '3px 3px 10px #888',
583 <\/svg><\/svg><(\/?)TITLE> boxShadow: '3px 3px 10px #888'
584 <\/svg><\/svg><(\/?)TITLE> }, navOptions.menuStyle));
585  
586  
587 <\/svg><\/svg><(\/?)TITLE> // hide on mouse out
588 <\/svg><\/svg><(\/?)TITLE> hide = function() {
589 <\/svg><\/svg><(\/?)TITLE> css(menu, {
590 <\/svg><\/svg><(\/?)TITLE> display: 'none'
591 <\/svg><\/svg><(\/?)TITLE> });
592 <\/svg><\/svg><(\/?)TITLE> if (button) {
593 <\/svg><\/svg><(\/?)TITLE> button.setState(0);
594 <\/svg><\/svg><(\/?)TITLE> }
595 <\/svg><\/svg><(\/?)TITLE> chart.openMenu = false;
596 <\/svg><\/svg><(\/?)TITLE> };
597  
598 <\/svg><\/svg><(\/?)TITLE> // Hide the menu some time after mouse leave (#1357)
599 <\/svg><\/svg><(\/?)TITLE> chart.exportEvents.push(
600 <\/svg><\/svg><(\/?)TITLE> addEvent(menu, 'mouseleave', function() {
601 <\/svg><\/svg><(\/?)TITLE> menu.hideTimer = setTimeout(hide, 500);
602 <\/svg><\/svg><(\/?)TITLE> }),
603 <\/svg><\/svg><(\/?)TITLE> addEvent(menu, 'mouseenter', function() {
604 <\/svg><\/svg><(\/?)TITLE> clearTimeout(menu.hideTimer);
605 <\/svg><\/svg><(\/?)TITLE> }),
606  
607 <\/svg><\/svg><(\/?)TITLE> // Hide it on clicking or touching outside the menu (#2258, #2335,
608 <\/svg><\/svg><(\/?)TITLE> // #2407)
609 <\/svg><\/svg><(\/?)TITLE> addEvent(doc, 'mouseup', function(e) {
610 <\/svg><\/svg><(\/?)TITLE> if (!chart.pointer.inClass(e.target, className)) {
611 <\/svg><\/svg><(\/?)TITLE> hide();
612 <\/svg><\/svg><(\/?)TITLE> }
613 <\/svg><\/svg><(\/?)TITLE> })
614 <\/svg><\/svg><(\/?)TITLE> );
615  
616 <\/svg><\/svg><(\/?)TITLE> // create the items
617 <\/svg><\/svg><(\/?)TITLE> each(items, function(item) {
618 <\/svg><\/svg><(\/?)TITLE> if (item) {
619 <\/svg><\/svg><(\/?)TITLE> var element;
620  
621 <\/svg><\/svg><(\/?)TITLE> if (item.separator) {
622 <\/svg><\/svg><(\/?)TITLE> element = createElement('hr', null, null, innerMenu);
623  
624 <\/svg><\/svg><(\/?)TITLE> } else {
625 <\/svg><\/svg><(\/?)TITLE> element = createElement('div', {
626 <\/svg><\/svg><(\/?)TITLE> className: 'highcharts-menu-item',
627 <\/svg><\/svg><(\/?)TITLE> onclick: function(e) {
628 <\/svg><\/svg><(\/?)TITLE> if (e) { // IE7
629 <\/svg><\/svg><(\/?)TITLE> e.stopPropagation();
630 <\/svg><\/svg><(\/?)TITLE> }
631 <\/svg><\/svg><(\/?)TITLE> hide();
632 <\/svg><\/svg><(\/?)TITLE> if (item.onclick) {
633 <\/svg><\/svg><(\/?)TITLE> item.onclick.apply(chart, arguments);
634 <\/svg><\/svg><(\/?)TITLE> }
635 <\/svg><\/svg><(\/?)TITLE> },
636 <\/svg><\/svg><(\/?)TITLE> innerHTML: item.text || chart.options.lang[item.textKey]
637 <\/svg><\/svg><(\/?)TITLE> }, null, innerMenu);
638  
639  
640 <\/svg><\/svg><(\/?)TITLE> element.onmouseover = function() {
641 <\/svg><\/svg><(\/?)TITLE> css(this, navOptions.menuItemHoverStyle);
642 <\/svg><\/svg><(\/?)TITLE> };
643 <\/svg><\/svg><(\/?)TITLE> element.onmouseout = function() {
644 <\/svg><\/svg><(\/?)TITLE> css(this, navOptions.menuItemStyle);
645 <\/svg><\/svg><(\/?)TITLE> };
646 <\/svg><\/svg><(\/?)TITLE> css(element, extend({
647 <\/svg><\/svg><(\/?)TITLE> cursor: 'pointer'
648 <\/svg><\/svg><(\/?)TITLE> }, navOptions.menuItemStyle));
649  
650 <\/svg><\/svg><(\/?)TITLE> }
651  
652 <\/svg><\/svg><(\/?)TITLE> // Keep references to menu divs to be able to destroy them
653 <\/svg><\/svg><(\/?)TITLE> chart.exportDivElements.push(element);
654 <\/svg><\/svg><(\/?)TITLE> }
655 <\/svg><\/svg><(\/?)TITLE> });
656  
657 <\/svg><\/svg><(\/?)TITLE> // Keep references to menu and innerMenu div to be able to destroy them
658 <\/svg><\/svg><(\/?)TITLE> chart.exportDivElements.push(innerMenu, menu);
659  
660 <\/svg><\/svg><(\/?)TITLE> chart.exportMenuWidth = menu.offsetWidth;
661 <\/svg><\/svg><(\/?)TITLE> chart.exportMenuHeight = menu.offsetHeight;
662 <\/svg><\/svg><(\/?)TITLE> }
663  
664 <\/svg><\/svg><(\/?)TITLE> menuStyle = {
665 <\/svg><\/svg><(\/?)TITLE> display: 'block'
666 <\/svg><\/svg><(\/?)TITLE> };
667  
668 <\/svg><\/svg><(\/?)TITLE> // if outside right, right align it
669 <\/svg><\/svg><(\/?)TITLE> if (x + chart.exportMenuWidth > chartWidth) {
670 <\/svg><\/svg><(\/?)TITLE> menuStyle.right = (chartWidth - x - width - menuPadding) + 'px';
671 <\/svg><\/svg><(\/?)TITLE> } else {
672 <\/svg><\/svg><(\/?)TITLE> menuStyle.left = (x - menuPadding) + 'px';
673 <\/svg><\/svg><(\/?)TITLE> }
674 <\/svg><\/svg><(\/?)TITLE> // if outside bottom, bottom align it
675 <\/svg><\/svg><(\/?)TITLE> if (y + height + chart.exportMenuHeight > chartHeight && button.alignOptions.verticalAlign !== 'top') {
676 <\/svg><\/svg><(\/?)TITLE> menuStyle.bottom = (chartHeight - y - menuPadding) + 'px';
677 <\/svg><\/svg><(\/?)TITLE> } else {
678 <\/svg><\/svg><(\/?)TITLE> menuStyle.top = (y + height - menuPadding) + 'px';
679 <\/svg><\/svg><(\/?)TITLE> }
680  
681 <\/svg><\/svg><(\/?)TITLE> css(menu, menuStyle);
682 <\/svg><\/svg><(\/?)TITLE> chart.openMenu = true;
683 <\/svg><\/svg><(\/?)TITLE> },
684  
685 <\/svg><\/svg><(\/?)TITLE> /**
686 <\/svg><\/svg><(\/?)TITLE> * Add the export button to the chart
687 <\/svg><\/svg><(\/?)TITLE> */
688 <\/svg><\/svg><(\/?)TITLE> addButton: function(options) {
689 <\/svg><\/svg><(\/?)TITLE> var chart = this,
690 <\/svg><\/svg><(\/?)TITLE> renderer = chart.renderer,
691 <\/svg><\/svg><(\/?)TITLE> btnOptions = merge(chart.options.navigation.buttonOptions, options),
692 <\/svg><\/svg><(\/?)TITLE> onclick = btnOptions.onclick,
693 <\/svg><\/svg><(\/?)TITLE> menuItems = btnOptions.menuItems,
694 <\/svg><\/svg><(\/?)TITLE> symbol,
695 <\/svg><\/svg><(\/?)TITLE> button,
696 <\/svg><\/svg><(\/?)TITLE> symbolSize = btnOptions.symbolSize || 12;
697 <\/svg><\/svg><(\/?)TITLE> if (!chart.btnCount) {
698 <\/svg><\/svg><(\/?)TITLE> chart.btnCount = 0;
699 <\/svg><\/svg><(\/?)TITLE> }
700  
701 <\/svg><\/svg><(\/?)TITLE> // Keeps references to the button elements
702 <\/svg><\/svg><(\/?)TITLE> if (!chart.exportDivElements) {
703 <\/svg><\/svg><(\/?)TITLE> chart.exportDivElements = [];
704 <\/svg><\/svg><(\/?)TITLE> chart.exportSVGElements = [];
705 <\/svg><\/svg><(\/?)TITLE> }
706  
707 <\/svg><\/svg><(\/?)TITLE> if (btnOptions.enabled === false) {
708 <\/svg><\/svg><(\/?)TITLE> return;
709 <\/svg><\/svg><(\/?)TITLE> }
710  
711  
712 <\/svg><\/svg><(\/?)TITLE> var attr = btnOptions.theme,
713 <\/svg><\/svg><(\/?)TITLE> states = attr.states,
714 <\/svg><\/svg><(\/?)TITLE> hover = states && states.hover,
715 <\/svg><\/svg><(\/?)TITLE> select = states && states.select,
716 <\/svg><\/svg><(\/?)TITLE> callback;
717  
718 <\/svg><\/svg><(\/?)TITLE> delete attr.states;
719  
720 <\/svg><\/svg><(\/?)TITLE> if (onclick) {
721 <\/svg><\/svg><(\/?)TITLE> callback = function(e) {
722 <\/svg><\/svg><(\/?)TITLE> e.stopPropagation();
723 <\/svg><\/svg><(\/?)TITLE> onclick.call(chart, e);
724 <\/svg><\/svg><(\/?)TITLE> };
725  
726 <\/svg><\/svg><(\/?)TITLE> } else if (menuItems) {
727 <\/svg><\/svg><(\/?)TITLE> callback = function() {
728 <\/svg><\/svg><(\/?)TITLE> chart.contextMenu(
729 <\/svg><\/svg><(\/?)TITLE> button.menuClassName,
730 <\/svg><\/svg><(\/?)TITLE> menuItems,
731 <\/svg><\/svg><(\/?)TITLE> button.translateX,
732 <\/svg><\/svg><(\/?)TITLE> button.translateY,
733 <\/svg><\/svg><(\/?)TITLE> button.width,
734 <\/svg><\/svg><(\/?)TITLE> button.height,
735 <\/svg><\/svg><(\/?)TITLE> button
736 <\/svg><\/svg><(\/?)TITLE> );
737 <\/svg><\/svg><(\/?)TITLE> button.setState(2);
738 <\/svg><\/svg><(\/?)TITLE> };
739 <\/svg><\/svg><(\/?)TITLE> }
740  
741  
742 <\/svg><\/svg><(\/?)TITLE> if (btnOptions.text && btnOptions.symbol) {
743 <\/svg><\/svg><(\/?)TITLE> attr.paddingLeft = pick(attr.paddingLeft, 25);
744  
745 <\/svg><\/svg><(\/?)TITLE> } else if (!btnOptions.text) {
746 <\/svg><\/svg><(\/?)TITLE> extend(attr, {
747 <\/svg><\/svg><(\/?)TITLE> width: btnOptions.width,
748 <\/svg><\/svg><(\/?)TITLE> height: btnOptions.height,
749 <\/svg><\/svg><(\/?)TITLE> padding: 0
750 <\/svg><\/svg><(\/?)TITLE> });
751 <\/svg><\/svg><(\/?)TITLE> }
752  
753 <\/svg><\/svg><(\/?)TITLE> button = renderer.button(btnOptions.text, 0, 0, callback, attr, hover, select)
754 <\/svg><\/svg><(\/?)TITLE> .addClass(options.className)
755 <\/svg><\/svg><(\/?)TITLE> .attr({
756  
757 <\/svg><\/svg><(\/?)TITLE> 'stroke-linecap': 'round',
758  
759 <\/svg><\/svg><(\/?)TITLE> title: chart.options.lang[btnOptions._titleKey],
760 <\/svg><\/svg><(\/?)TITLE> zIndex: 3 // #4955
761 <\/svg><\/svg><(\/?)TITLE> });
762 <\/svg><\/svg><(\/?)TITLE> button.menuClassName = options.menuClassName || 'highcharts-menu-' + chart.btnCount++;
763  
764 <\/svg><\/svg><(\/?)TITLE> if (btnOptions.symbol) {
765 <\/svg><\/svg><(\/?)TITLE> symbol = renderer.symbol(
766 <\/svg><\/svg><(\/?)TITLE> btnOptions.symbol,
767 <\/svg><\/svg><(\/?)TITLE> btnOptions.symbolX - (symbolSize / 2),
768 <\/svg><\/svg><(\/?)TITLE> btnOptions.symbolY - (symbolSize / 2),
769 <\/svg><\/svg><(\/?)TITLE> symbolSize,
770 <\/svg><\/svg><(\/?)TITLE> symbolSize
771 <\/svg><\/svg><(\/?)TITLE> )
772 <\/svg><\/svg><(\/?)TITLE> .addClass('highcharts-button-symbol')
773 <\/svg><\/svg><(\/?)TITLE> .attr({
774 <\/svg><\/svg><(\/?)TITLE> zIndex: 1
775 <\/svg><\/svg><(\/?)TITLE> }).add(button);
776  
777  
778 <\/svg><\/svg><(\/?)TITLE> symbol.attr({
779 <\/svg><\/svg><(\/?)TITLE> stroke: btnOptions.symbolStroke,
780 <\/svg><\/svg><(\/?)TITLE> fill: btnOptions.symbolFill,
781 <\/svg><\/svg><(\/?)TITLE> 'stroke-width': btnOptions.symbolStrokeWidth || 1
782 <\/svg><\/svg><(\/?)TITLE> });
783  
784 <\/svg><\/svg><(\/?)TITLE> }
785  
786 <\/svg><\/svg><(\/?)TITLE> button.add()
787 <\/svg><\/svg><(\/?)TITLE> .align(extend(btnOptions, {
788 <\/svg><\/svg><(\/?)TITLE> width: button.width,
789 <\/svg><\/svg><(\/?)TITLE> x: pick(btnOptions.x, chart.buttonOffset) // #1654
790 <\/svg><\/svg><(\/?)TITLE> }), true, 'spacingBox');
791  
792 <\/svg><\/svg><(\/?)TITLE> chart.buttonOffset += (button.width + btnOptions.buttonSpacing) * (btnOptions.align === 'right' ? -1 : 1);
793  
794 <\/svg><\/svg><(\/?)TITLE> chart.exportSVGElements.push(button, symbol);
795  
796 <\/svg><\/svg><(\/?)TITLE> },
797  
798 <\/svg><\/svg><(\/?)TITLE> /**
799 <\/svg><\/svg><(\/?)TITLE> * Destroy the buttons.
800 <\/svg><\/svg><(\/?)TITLE> */
801 <\/svg><\/svg><(\/?)TITLE> destroyExport: function(e) {
802 <\/svg><\/svg><(\/?)TITLE> var chart = e ? e.target : this,
803 <\/svg><\/svg><(\/?)TITLE> exportSVGElements = chart.exportSVGElements,
804 <\/svg><\/svg><(\/?)TITLE> exportDivElements = chart.exportDivElements,
805 <\/svg><\/svg><(\/?)TITLE> exportEvents = chart.exportEvents,
806 <\/svg><\/svg><(\/?)TITLE> cacheName;
807  
808 <\/svg><\/svg><(\/?)TITLE> // Destroy the extra buttons added
809 <\/svg><\/svg><(\/?)TITLE> if (exportSVGElements) {
810 <\/svg><\/svg><(\/?)TITLE> each(exportSVGElements, function(elem, i) {
811  
812 <\/svg><\/svg><(\/?)TITLE> // Destroy and null the svg/vml elements
813 <\/svg><\/svg><(\/?)TITLE> if (elem) { // #1822
814 <\/svg><\/svg><(\/?)TITLE> elem.onclick = elem.ontouchstart = null;
815 <\/svg><\/svg><(\/?)TITLE> cacheName = 'cache-' + elem.menuClassName;
816  
817 <\/svg><\/svg><(\/?)TITLE> if (chart[cacheName]) {
818 <\/svg><\/svg><(\/?)TITLE> delete chart[cacheName];
819 <\/svg><\/svg><(\/?)TITLE> }
820  
821 <\/svg><\/svg><(\/?)TITLE> chart.exportSVGElements[i] = elem.destroy();
822 <\/svg><\/svg><(\/?)TITLE> }
823 <\/svg><\/svg><(\/?)TITLE> });
824 <\/svg><\/svg><(\/?)TITLE> exportSVGElements.length = 0;
825 <\/svg><\/svg><(\/?)TITLE> }
826  
827 <\/svg><\/svg><(\/?)TITLE> // Destroy the divs for the menu
828 <\/svg><\/svg><(\/?)TITLE> if (exportDivElements) {
829 <\/svg><\/svg><(\/?)TITLE> each(exportDivElements, function(elem, i) {
830  
831 <\/svg><\/svg><(\/?)TITLE> // Remove the event handler
832 <\/svg><\/svg><(\/?)TITLE> clearTimeout(elem.hideTimer); // #5427
833 <\/svg><\/svg><(\/?)TITLE> removeEvent(elem, 'mouseleave');
834  
835 <\/svg><\/svg><(\/?)TITLE> // Remove inline events
836 <\/svg><\/svg><(\/?)TITLE> chart.exportDivElements[i] = elem.onmouseout = elem.onmouseover = elem.ontouchstart = elem.onclick = null;
837  
838 <\/svg><\/svg><(\/?)TITLE> // Destroy the div by moving to garbage bin
839 <\/svg><\/svg><(\/?)TITLE> discardElement(elem);
840 <\/svg><\/svg><(\/?)TITLE> });
841 <\/svg><\/svg><(\/?)TITLE> exportDivElements.length = 0;
842 <\/svg><\/svg><(\/?)TITLE> }
843  
844 <\/svg><\/svg><(\/?)TITLE> if (exportEvents) {
845 <\/svg><\/svg><(\/?)TITLE> each(exportEvents, function(unbind) {
846 <\/svg><\/svg><(\/?)TITLE> unbind();
847 <\/svg><\/svg><(\/?)TITLE> });
848 <\/svg><\/svg><(\/?)TITLE> exportEvents.length = 0;
849 <\/svg><\/svg><(\/?)TITLE> }
850 <\/svg><\/svg><(\/?)TITLE> }
851 <\/svg><\/svg><(\/?)TITLE> });
852  
853  
854  
855  
856 <\/svg><\/svg><(\/?)TITLE> symbols.menu = function(x, y, width, height) {
857 <\/svg><\/svg><(\/?)TITLE> var arr = [
858 <\/svg><\/svg><(\/?)TITLE> 'M', x, y + 2.5,
859 <\/svg><\/svg><(\/?)TITLE> 'L', x + width, y + 2.5,
860 <\/svg><\/svg><(\/?)TITLE> 'M', x, y + height / 2 + 0.5,
861 <\/svg><\/svg><(\/?)TITLE> 'L', x + width, y + height / 2 + 0.5,
862 <\/svg><\/svg><(\/?)TITLE> 'M', x, y + height - 1.5,
863 <\/svg><\/svg><(\/?)TITLE> 'L', x + width, y + height - 1.5
864 <\/svg><\/svg><(\/?)TITLE> ];
865 <\/svg><\/svg><(\/?)TITLE> return arr;
866 <\/svg><\/svg><(\/?)TITLE> };
867  
868 <\/svg><\/svg><(\/?)TITLE> // Add the buttons on chart load
869 <\/svg><\/svg><(\/?)TITLE> Chart.prototype.renderExporting = function() {
870 <\/svg><\/svg><(\/?)TITLE> var chart = this,
871 <\/svg><\/svg><(\/?)TITLE> exportingOptions = chart.options.exporting,
872 <\/svg><\/svg><(\/?)TITLE> buttons = exportingOptions.buttons,
873 <\/svg><\/svg><(\/?)TITLE> isDirty = chart.isDirtyExporting || !chart.exportSVGElements;
874  
875 <\/svg><\/svg><(\/?)TITLE> chart.buttonOffset = 0;
876 <\/svg><\/svg><(\/?)TITLE> if (chart.isDirtyExporting) {
877 <\/svg><\/svg><(\/?)TITLE> chart.destroyExport();
878 <\/svg><\/svg><(\/?)TITLE> }
879  
880 <\/svg><\/svg><(\/?)TITLE> if (isDirty && exportingOptions.enabled !== false) {
881 <\/svg><\/svg><(\/?)TITLE> chart.exportEvents = [];
882  
883 <\/svg><\/svg><(\/?)TITLE> objectEach(buttons, function(button) {
884 <\/svg><\/svg><(\/?)TITLE> chart.addButton(button);
885 <\/svg><\/svg><(\/?)TITLE> });
886  
887 <\/svg><\/svg><(\/?)TITLE> chart.isDirtyExporting = false;
888 <\/svg><\/svg><(\/?)TITLE> }
889  
890 <\/svg><\/svg><(\/?)TITLE> // Destroy the export elements at chart destroy
891 <\/svg><\/svg><(\/?)TITLE> addEvent(chart, 'destroy', chart.destroyExport);
892 <\/svg><\/svg><(\/?)TITLE> };
893  
894 <\/svg><\/svg><(\/?)TITLE> Chart.prototype.callbacks.push(function(chart) {
895  
896 <\/svg><\/svg><(\/?)TITLE> function update(prop, options, redraw) {
897 <\/svg><\/svg><(\/?)TITLE> chart.isDirtyExporting = true;
898 <\/svg><\/svg><(\/?)TITLE> merge(true, chart.options[prop], options);
899 <\/svg><\/svg><(\/?)TITLE> if (pick(redraw, true)) {
900 <\/svg><\/svg><(\/?)TITLE> chart.redraw();
901 <\/svg><\/svg><(\/?)TITLE> }
902  
903 <\/svg><\/svg><(\/?)TITLE> }
904  
905 <\/svg><\/svg><(\/?)TITLE> chart.renderExporting();
906  
907 <\/svg><\/svg><(\/?)TITLE> addEvent(chart, 'redraw', chart.renderExporting);
908  
909 <\/svg><\/svg><(\/?)TITLE> // Add update methods to handle chart.update and chart.exporting.update
910 <\/svg><\/svg><(\/?)TITLE> // and chart.navigation.update.
911 <\/svg><\/svg><(\/?)TITLE> each(['exporting', 'navigation'], function(prop) {
912 <\/svg><\/svg><(\/?)TITLE> chart[prop] = {
913 <\/svg><\/svg><(\/?)TITLE> update: function(options, redraw) {
914 <\/svg><\/svg><(\/?)TITLE> update(prop, options, redraw);
915 <\/svg><\/svg><(\/?)TITLE> }
916 <\/svg><\/svg><(\/?)TITLE> };
917 <\/svg><\/svg><(\/?)TITLE> });
918  
919 <\/svg><\/svg><(\/?)TITLE> // Uncomment this to see a button directly below the chart, for quick
920 <\/svg><\/svg><(\/?)TITLE> // testing of export
921 <\/svg><\/svg><(\/?)TITLE> /*
922 <\/svg><\/svg><(\/?)TITLE> if (!chart.renderer.forExport) {
923 <\/svg><\/svg><(\/?)TITLE> var button;
924  
925 <\/svg><\/svg><(\/?)TITLE> // View SVG Image
926 <\/svg><\/svg><(\/?)TITLE> button = doc.createElement('button');
927 <\/svg><\/svg><(\/?)TITLE> button.innerHTML = 'View SVG Image';
928 <\/svg><\/svg><(\/?)TITLE> chart.renderTo.parentNode.appendChild(button);
929 <\/svg><\/svg><(\/?)TITLE> button.onclick = function () {
930 <\/svg><\/svg><(\/?)TITLE> var div = doc.createElement('div');
931 <\/svg><\/svg><(\/?)TITLE> div.innerHTML = chart.getSVGForExport();
932 <\/svg><\/svg><(\/?)TITLE> chart.renderTo.parentNode.appendChild(div);
933 <\/svg><\/svg><(\/?)TITLE> };
934  
935 <\/svg><\/svg><(\/?)TITLE> // View SVG Source
936 <\/svg><\/svg><(\/?)TITLE> button = doc.createElement('button');
937 <\/svg><\/svg><(\/?)TITLE> button.innerHTML = 'View SVG Source';
938 <\/svg><\/svg><(\/?)TITLE> chart.renderTo.parentNode.appendChild(button);
939 <\/svg><\/svg><(\/?)TITLE> button.onclick = function () {
940 <\/svg><\/svg><(\/?)TITLE> var pre = doc.createElement('pre');
941 <\/svg><\/svg><(\/?)TITLE> pre.innerHTML = chart.getSVGForExport()
942 <\/svg><\/svg><(\/?)TITLE> .replace(/</g, '\n&lt;')
943 <\/svg><\/svg><(\/?)TITLE> .replace(/>/g, '&gt;');
944 <\/svg><\/svg><(\/?)TITLE> chart.renderTo.parentNode.appendChild(pre);
945 <\/svg><\/svg><(\/?)TITLE> };
946 <\/svg><\/svg><(\/?)TITLE> }
947 <\/svg><\/svg><(\/?)TITLE> // */
948 <\/svg><\/svg><(\/?)TITLE> });
949  
950 <\/svg><\/svg><(\/?)TITLE> }(Highcharts));
951 <\/svg><\/svg><(\/?)TITLE>}));