corrade-nucleus-nucleons – Blame information for rev 31

Subversion Repositories:
Rev:
Rev Author Line No. Line
31 office 1 /**
2 * @license Highcharts JS v5.0.14 (2017-07-28)
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 /**
53 * @apioption lang
54 */
55 extend(defaultOptions.lang, {
56 printChart: 'Print chart',
57 downloadPNG: 'Download PNG image',
58 downloadJPEG: 'Download JPEG image',
59 downloadPDF: 'Download PDF document',
60 downloadSVG: 'Download SVG vector image',
61 contextButtonTitle: 'Chart context menu'
62 });
63  
64 // Buttons and menus are collected in a separate config option set called 'navigation'.
65 // This can be extended later to add control buttons like zoom and pan right click menus.
66  
67 /**
68 * @apioption navigation
69 */
70 defaultOptions.navigation = {
71 buttonOptions: {
72 theme: {},
73 symbolSize: 14,
74 symbolX: 12.5,
75 symbolY: 10.5,
76 align: 'right',
77 buttonSpacing: 3,
78 height: 22,
79 // text: null,
80 verticalAlign: 'top',
81 width: 24
82 }
83 };
84  
85  
86  
87  
88 // Add the export related options
89  
90 /**
91 * Options for the exporting module. For an overview on the matter, see [the docs](http://www.highcharts.com/docs/export-module/export-module-overview).
92 * @type {Object}
93 * @optionparent exporting
94 */
95 defaultOptions.exporting = {
96 //enabled: true,
97 //filename: 'chart',
98  
99 /**
100 * Default MIME type for exporting if `chart.exportChart()` is called
101 * without specifying a `type` option. Possible values are `image/png`,
102 * `image/jpeg`, `application/pdf` and `image/svg+xml`.
103 *
104 * @validvalue ["image/png", "image/jpeg", "application/pdf", "image/svg+xml"]
105 * @type {String}
106 * @default image/png
107 * @since 2.0
108 * @product highcharts highstock highmaps
109 */
110 type: 'image/png',
111  
112 /**
113 * The URL for the server module converting the SVG string to an image
114 * format. By default this points to Highchart's free web service.
115 *
116 * @type {String}
117 * @default https://export.highcharts.com
118 * @since 2.0
119 * @product highcharts highstock highmaps
120 */
121 url: 'https://export.highcharts.com/',
122 //width: undefined,
123  
124 /**
125 * When printing the chart from the menu item in the burger menu, if
126 * the on-screen chart exceeds this width, it is resized. After printing
127 * or cancelled, it is restored. The default width makes the chart
128 * fit into typical paper format. Note that this does not affect the
129 * chart when printing the web page as a whole.
130 *
131 * @type {Number}
132 * @default 780
133 * @since 4.2.5
134 * @product highcharts highstock highmaps
135 */
136 printMaxWidth: 780,
137  
138 /**
139 * Defines the scale or zoom factor for the exported image compared
140 * to the on-screen display. While for instance a 600px wide chart
141 * may look good on a website, it will look bad in print. The default
142 * scale of 2 makes this chart export to a 1200px PNG or JPG.
143 *
144 * @type {Number}
145 * @see [chart.width](#chart.width), [exporting.sourceWidth](#exporting.
146 * sourceWidth)
147 * @sample {highcharts} highcharts/exporting/scale/ Scale demonstrated
148 * @sample {highstock} highcharts/exporting/scale/ Scale demonstrated
149 * @sample {highmaps} maps/exporting/scale/ Scale demonstrated
150 * @default 2
151 * @since 3.0
152 * @product highcharts highstock highmaps
153 */
154 scale: 2,
155  
156 /**
157 * Options for the export related buttons, print and export. In addition
158 * to the default buttons listed here, custom buttons can be added.
159 * See [navigation.buttonOptions](#navigation.buttonOptions) for general
160 * options.
161 *
162 * @product highcharts highstock highmaps
163 */
164 buttons: {
165  
166 /**
167 * Options for the export button.
168 *
169 * In [styled mode](http://www.highcharts.com/docs/chart-design-and-
170 * style/style-by-css), export button styles can be applied with the
171 * `.highcharts-contextbutton` class.
172 *
173 * @extends navigation.buttonOptions
174 * @product highcharts highstock highmaps
175 */
176 contextButton: {
177  
178 /**
179 */
180 className: 'highcharts-contextbutton',
181  
182 /**
183 */
184 menuClassName: 'highcharts-contextmenu',
185 //x: -10,
186  
187 /**
188 * The symbol for the button. Points to a definition function in
189 * the `Highcharts.Renderer.symbols` collection. The default `exportIcon`
190 * function is part of the exporting module.
191 *
192 * @validvalue ["circle", "square", "diamond", "triangle", "triangle-down", "menu"]
193 * @type {String}
194 * @sample {highcharts} highcharts/exporting/buttons-contextbutton-symbol/ Use a circle for symbol
195 * @sample {highstock} highcharts/exporting/buttons-contextbutton-symbol/ Use a circle for symbol
196 * @sample {highmaps} highcharts/exporting/buttons-contextbutton-symbol/ Use a circle for symbol
197 * @default menu
198 * @since 2.0
199 * @product highcharts highstock highmaps
200 */
201 symbol: 'menu',
202  
203 /**
204 */
205 _titleKey: 'contextButtonTitle',
206  
207 /**
208 * A collection of config options for the menu items. Each options
209 * object consists of a `text` option which is a string to show in
210 * the menu item, as well as an `onclick` parameter which is a callback
211 * function to run on click.
212 *
213 * By default, there is the "Print" menu item plus one menu item
214 * for each of the available export types. Menu items can be customized
215 * by defining a new array of items and assigning `null` to unwanted
216 * positions (see override example below).
217 *
218 * @type {Array<Object>}
219 * @sample {highcharts} highcharts/exporting/buttons-contextbutton-onclick/ Skip the menu and export the chart directly
220 * @sample {highcharts} highcharts/exporting/buttons-contextbutton-menuitems/ Override the menu items
221 * @sample {highstock} highcharts/exporting/buttons-contextbutton-onclick/ Skip the menu and export the chart directly
222 * @sample {highstock} highcharts/exporting/buttons-contextbutton-menuitems/ Override the menu items
223 * @sample {highmaps} highcharts/exporting/buttons-contextbutton-onclick/ Skip the menu and export the chart directly
224 * @sample {highmaps} highcharts/exporting/buttons-contextbutton-menuitems/ Override the menu items
225 * @since 2.0
226 * @product highcharts highstock highmaps
227 */
228 menuItems: [
229 'printChart',
230 'separator',
231 'downloadPNG',
232 'downloadJPEG',
233 'downloadPDF',
234 'downloadSVG'
235 ]
236 }
237 },
238 // docs. Created API item with since:next. Add information and link to sample
239 // from menuItems too.
240  
241 /**
242 * An object consisting of definitions for the menu items in the context
243 * menu. Each key value pair has a `key` that is referenced in the
244 * [menuItems](#exporting.buttons.contextButton.menuItems) setting,
245 * and a `value`, which is an object with the following properties:
246 *
247 * <dl>
248 *
249 * <dt>onclick</dt>
250 *
251 * <dd>The click handler for the menu item</dd>
252 *
253 * <dt>text</dt>
254 *
255 * <dd>The text for the menu item</dd>
256 *
257 * <dt>textKey</dt>
258 *
259 * <dd>If internationalization is required, the key to a language string</dd>
260 *
261 * </dl>
262 *
263 * @type {Object}
264 * @sample {highcharts} highcharts/exporting/menuitemdefinitions/ Menu item definitions
265 * @sample {highstock} highcharts/exporting/menuitemdefinitions/ Menu item definitions
266 * @sample {highmaps} highcharts/exporting/menuitemdefinitions/ Menu item definitions
267 * @since next
268 * @product highcharts highstock highmaps
269 */
270 menuItemDefinitions: {
271  
272 /**
273 */
274 printChart: {
275  
276 /**
277 */
278 textKey: 'printChart',
279  
280 /**
281 */
282 onclick: function() {
283 this.print();
284 }
285 },
286  
287 /**
288 */
289 separator: {
290  
291 /**
292 */
293 separator: true
294 },
295  
296 /**
297 */
298 downloadPNG: {
299  
300 /**
301 */
302 textKey: 'downloadPNG',
303  
304 /**
305 */
306 onclick: function() {
307 this.exportChart();
308 }
309 },
310  
311 /**
312 */
313 downloadJPEG: {
314  
315 /**
316 */
317 textKey: 'downloadJPEG',
318  
319 /**
320 */
321 onclick: function() {
322 this.exportChart({
323 type: 'image/jpeg'
324 });
325 }
326 },
327  
328 /**
329 */
330 downloadPDF: {
331  
332 /**
333 */
334 textKey: 'downloadPDF',
335  
336 /**
337 */
338 onclick: function() {
339 this.exportChart({
340 type: 'application/pdf'
341 });
342 }
343 },
344  
345 /**
346 */
347 downloadSVG: {
348  
349 /**
350 */
351 textKey: 'downloadSVG',
352  
353 /**
354 */
355 onclick: function() {
356 this.exportChart({
357 type: 'image/svg+xml'
358 });
359 }
360 }
361 }
362 };
363  
364 /**
365 * Fires after a chart is printed through the context menu item or the
366 * `Chart.print` method. Requires the exporting module.
367 *
368 * @type {Function}
369 * @context Chart
370 * @sample {highcharts} highcharts/chart/events-beforeprint-afterprint/
371 * Rescale the chart to print
372 * @sample {highstock} highcharts/chart/events-beforeprint-afterprint/
373 * Rescale the chart to print
374 * @sample {highmaps} highcharts/chart/events-beforeprint-afterprint/
375 * Rescale the chart to print
376 * @since 4.1.0
377 * @apioption chart.events.afterPrint
378 */
379  
380 /**
381 * Fires before a chart is printed through the context menu item or
382 * the `Chart.print` method. Requires the exporting module.
383 *
384 * @type {Function}
385 * @context Chart
386 * @sample {highcharts} highcharts/chart/events-beforeprint-afterprint/
387 * Rescale the chart to print
388 * @sample {highstock} highcharts/chart/events-beforeprint-afterprint/
389 * Rescale the chart to print
390 * @sample {highmaps} highcharts/chart/events-beforeprint-afterprint/
391 * Rescale the chart to print
392 * @since 4.1.0
393 * @apioption chart.events.beforePrint
394 */
395  
396  
397 // Add the H.post utility
398 H.post = function(url, data, formAttributes) {
399 // create the form
400 var form = createElement('form', merge({
401 method: 'post',
402 action: url,
403 enctype: 'multipart/form-data'
404 }, formAttributes), {
405 display: 'none'
406 }, doc.body);
407  
408 // add the data
409 objectEach(data, function(val, name) {
410 createElement('input', {
411 type: 'hidden',
412 name: name,
413 value: val
414 }, null, form);
415 });
416  
417 // submit
418 form.submit();
419  
420 // clean up
421 discardElement(form);
422 };
423  
424 extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ {
425  
426 /**
427 * Exporting module only. A collection of fixes on the produced SVG to
428 * account for expando properties, browser bugs, VML problems and other.
429 * Returns a cleaned SVG.
430 *
431 * @private
432 */
433 sanitizeSVG: function(svg, options) {
434 // Move HTML into a foreignObject
435 if (options && options.exporting && options.exporting.allowHTML) {
436 var html = svg.match(/<\/svg>(.*?$)/);
437 <\/svg> if (html && html[1]) {
438 <\/svg> html = '<foreignObject x="0" y="0" ' +
439 <\/svg> 'width="' + options.chart.width + '" ' +
440 <\/svg> 'height="' + options.chart.height + '">' +
441 <\/svg> '<body xmlns="http://www.w3.org/1999/xhtml">' +
442 <\/svg> html[1] +
443 <\/svg> '</body>' +
444 <\/svg> '</foreignObject>';
445 <\/svg> svg = svg.replace('</svg>', html + '</svg>');
446 <\/svg> }
447 <\/svg> }
448  
449 <\/svg> svg = svg
450 <\/svg> .replace(/zIndex="[^"]+"/g, '')
451 <\/svg> .replace(/isShadow="[^"]+"/g, '')
452 <\/svg> .replace(/symbolName="[^"]+"/g, '')
453 <\/svg> .replace(/jQuery[0-9]+="[^"]+"/g, '')
454 <\/svg> .replace(/url\(("|")(\S+)("|")\)/g, 'url($2)')
455 <\/svg> .replace(/url\([^#]+#/g, 'url(#')
456 <\/svg> .replace(/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ')
457 <\/svg> .replace(/ (NS[0-9]+\:)?href=/g, ' xlink:href=') // #3567
458 <\/svg> .replace(/\n/, ' ')
459 <\/svg> // Any HTML added to the container after the SVG (#894)
460 <\/svg> .replace(/<\/svg>.*?$/, '</svg>')
461 <\/svg><\/svg> // Batik doesn't support rgba fills and strokes (#3095)
462 <\/svg><\/svg> .replace(/(fill|stroke)="rgba\(([ 0-9]+,[ 0-9]+,[ 0-9]+),([ 0-9\.]+)\)"/g, '$1="rgb($2)" $1-opacity="$3"')
463 <\/svg><\/svg> /* This fails in IE < 8
464 <\/svg><\/svg> .replace(/([0-9]+)\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight
465 <\/svg><\/svg> return s2 +'.'+ s3[0];
466 <\/svg><\/svg> })*/
467  
468 <\/svg><\/svg> // Replace HTML entities, issue #347
469 <\/svg><\/svg> .replace(/ /g, '\u00A0') // no-break space
470 <\/svg><\/svg> .replace(/­/g, '\u00AD'); // soft hyphen
471  
472  
473  
474 <\/svg><\/svg> return svg;
475 <\/svg><\/svg> },
476  
477 <\/svg><\/svg> /**
478 <\/svg><\/svg> * Return the unfiltered innerHTML of the chart container. Used as hook for
479 <\/svg><\/svg> * plugins. In styled mode, it also takes care of inlining CSS style rules.
480 <\/svg><\/svg> *
481 <\/svg><\/svg> * @see Chart#getSVG
482 <\/svg><\/svg> *
483 <\/svg><\/svg> * @returns {String}
484 <\/svg><\/svg> * The unfiltered SVG of the chart.
485 <\/svg><\/svg> */
486 <\/svg><\/svg> getChartHTML: function() {
487  
488 <\/svg><\/svg> this.inlineStyles();
489  
490 <\/svg><\/svg> return this.container.innerHTML;
491 <\/svg><\/svg> },
492  
493 <\/svg><\/svg> /**
494 <\/svg><\/svg> * Return an SVG representation of the chart.
495 <\/svg><\/svg> *
496 <\/svg><\/svg> * @param chartOptions {Options}
497 <\/svg><\/svg> * Additional chart options for the generated SVG representation.
498 <\/svg><\/svg> * For collections like `xAxis`, `yAxis` or `series`, the additional
499 <\/svg><\/svg> * options is either merged in to the orininal item of the same
500 <\/svg><\/svg> * `id`, or to the first item if a common id is not found.
501 <\/svg><\/svg> * @return {String}
502 <\/svg><\/svg> * The SVG representation of the rendered chart.
503 <\/svg><\/svg> * @sample highcharts/members/chart-getsvg/
504 <\/svg><\/svg> * View the SVG from a button
505 <\/svg><\/svg> */
506 <\/svg><\/svg> getSVG: function(chartOptions) {
507 <\/svg><\/svg> var chart = this,
508 <\/svg><\/svg> chartCopy,
509 <\/svg><\/svg> sandbox,
510 <\/svg><\/svg> svg,
511 <\/svg><\/svg> seriesOptions,
512 <\/svg><\/svg> sourceWidth,
513 <\/svg><\/svg> sourceHeight,
514 <\/svg><\/svg> cssWidth,
515 <\/svg><\/svg> cssHeight,
516 <\/svg><\/svg> options = merge(chart.options, chartOptions); // copy the options and add extra options
517  
518  
519 <\/svg><\/svg> // IE compatibility hack for generating SVG content that it doesn't really understand
520 <\/svg><\/svg> if (!doc.createElementNS) {
521 <\/svg><\/svg> doc.createElementNS = function(ns, tagName) {
522 <\/svg><\/svg> return doc.createElement(tagName);
523 <\/svg><\/svg> };
524 <\/svg><\/svg> }
525  
526 <\/svg><\/svg> // create a sandbox where a new chart will be generated
527 <\/svg><\/svg> sandbox = createElement('div', null, {
528 <\/svg><\/svg> position: 'absolute',
529 <\/svg><\/svg> top: '-9999em',
530 <\/svg><\/svg> width: chart.chartWidth + 'px',
531 <\/svg><\/svg> height: chart.chartHeight + 'px'
532 <\/svg><\/svg> }, doc.body);
533  
534 <\/svg><\/svg> // get the source size
535 <\/svg><\/svg> cssWidth = chart.renderTo.style.width;
536 <\/svg><\/svg> cssHeight = chart.renderTo.style.height;
537 <\/svg><\/svg> sourceWidth = options.exporting.sourceWidth ||
538 <\/svg><\/svg> options.chart.width ||
539 <\/svg><\/svg> (/px$/.test(cssWidth) && parseInt(cssWidth, 10)) ||
540 <\/svg><\/svg> 600;
541 <\/svg><\/svg> sourceHeight = options.exporting.sourceHeight ||
542 <\/svg><\/svg> options.chart.height ||
543 <\/svg><\/svg> (/px$/.test(cssHeight) && parseInt(cssHeight, 10)) ||
544 <\/svg><\/svg> 400;
545  
546 <\/svg><\/svg> // override some options
547 <\/svg><\/svg> extend(options.chart, {
548 <\/svg><\/svg> animation: false,
549 <\/svg><\/svg> renderTo: sandbox,
550 <\/svg><\/svg> forExport: true,
551 <\/svg><\/svg> renderer: 'SVGRenderer',
552 <\/svg><\/svg> width: sourceWidth,
553 <\/svg><\/svg> height: sourceHeight
554 <\/svg><\/svg> });
555 <\/svg><\/svg> options.exporting.enabled = false; // hide buttons in print
556 <\/svg><\/svg> delete options.data; // #3004
557  
558 <\/svg><\/svg> // prepare for replicating the chart
559 <\/svg><\/svg> options.series = [];
560 <\/svg><\/svg> each(chart.series, function(serie) {
561 <\/svg><\/svg> seriesOptions = merge(serie.userOptions, { // #4912
562 <\/svg><\/svg> animation: false, // turn off animation
563 <\/svg><\/svg> enableMouseTracking: false,
564 <\/svg><\/svg> showCheckbox: false,
565 <\/svg><\/svg> visible: serie.visible
566 <\/svg><\/svg> });
567  
568 <\/svg><\/svg> if (!seriesOptions.isInternal) { // used for the navigator series that has its own option set
569 <\/svg><\/svg> options.series.push(seriesOptions);
570 <\/svg><\/svg> }
571 <\/svg><\/svg> });
572  
573 <\/svg><\/svg> // Assign an internal key to ensure a one-to-one mapping (#5924)
574 <\/svg><\/svg> each(chart.axes, function(axis) {
575 <\/svg><\/svg> if (!axis.userOptions.internalKey) { // #6444
576 <\/svg><\/svg> axis.userOptions.internalKey = H.uniqueKey();
577 <\/svg><\/svg> }
578 <\/svg><\/svg> });
579  
580 <\/svg><\/svg> // generate the chart copy
581 <\/svg><\/svg> chartCopy = new H.Chart(options, chart.callback);
582  
583 <\/svg><\/svg> // Axis options and series options (#2022, #3900, #5982)
584 <\/svg><\/svg> if (chartOptions) {
585 <\/svg><\/svg> each(['xAxis', 'yAxis', 'series'], function(coll) {
586 <\/svg><\/svg> var collOptions = {};
587 <\/svg><\/svg> if (chartOptions[coll]) {
588 <\/svg><\/svg> collOptions[coll] = chartOptions[coll];
589 <\/svg><\/svg> chartCopy.update(collOptions);
590 <\/svg><\/svg> }
591 <\/svg><\/svg> });
592 <\/svg><\/svg> }
593  
594 <\/svg><\/svg> // Reflect axis extremes in the export (#5924)
595 <\/svg><\/svg> each(chart.axes, function(axis) {
596 <\/svg><\/svg> var axisCopy = H.find(chartCopy.axes, function(copy) {
597 <\/svg><\/svg> return copy.options.internalKey ===
598 <\/svg><\/svg> axis.userOptions.internalKey;
599 <\/svg><\/svg> }),
600 <\/svg><\/svg> extremes = axis.getExtremes(),
601 <\/svg><\/svg> userMin = extremes.userMin,
602 <\/svg><\/svg> userMax = extremes.userMax;
603  
604 <\/svg><\/svg> if (axisCopy && (userMin !== undefined || userMax !== undefined)) {
605 <\/svg><\/svg> axisCopy.setExtremes(userMin, userMax, true, false);
606 <\/svg><\/svg> }
607 <\/svg><\/svg> });
608  
609 <\/svg><\/svg> // Get the SVG from the container's innerHTML
610 <\/svg><\/svg> svg = chartCopy.getChartHTML();
611  
612 <\/svg><\/svg> svg = chart.sanitizeSVG(svg, options);
613  
614 <\/svg><\/svg> // free up memory
615 <\/svg><\/svg> options = null;
616 <\/svg><\/svg> chartCopy.destroy();
617 <\/svg><\/svg> discardElement(sandbox);
618  
619 <\/svg><\/svg> return svg;
620 <\/svg><\/svg> },
621  
622 <\/svg><\/svg> getSVGForExport: function(options, chartOptions) {
623 <\/svg><\/svg> var chartExportingOptions = this.options.exporting;
624  
625 <\/svg><\/svg> return this.getSVG(merge({
626 <\/svg><\/svg> chart: {
627 <\/svg><\/svg> borderRadius: 0
628 <\/svg><\/svg> }
629 <\/svg><\/svg> },
630 <\/svg><\/svg> chartExportingOptions.chartOptions,
631 <\/svg><\/svg> chartOptions, {
632 <\/svg><\/svg> exporting: {
633 <\/svg><\/svg> sourceWidth: (options && options.sourceWidth) || chartExportingOptions.sourceWidth,
634 <\/svg><\/svg> sourceHeight: (options && options.sourceHeight) || chartExportingOptions.sourceHeight
635 <\/svg><\/svg> }
636 <\/svg><\/svg> }
637 <\/svg><\/svg> ));
638 <\/svg><\/svg> },
639  
640 <\/svg><\/svg> /**
641 <\/svg><\/svg> * Exporting module required. Submit an SVG version of the chart to a server
642 <\/svg><\/svg> * along with some parameters for conversion.
643 <\/svg><\/svg> * @param {Object} exportingOptions
644 <\/svg><\/svg> * Exporting options in addition to those defined in {@link
645 <\/svg><\/svg> * https://api.highcharts.com/highcharts/exporting|exporting}.
646 <\/svg><\/svg> * @param {String} exportingOptions.filename
647 <\/svg><\/svg> * The file name for the export without extension.
648 <\/svg><\/svg> * @param {String} exportingOptions.url
649 <\/svg><\/svg> * The URL for the server module to do the conversion.
650 <\/svg><\/svg> * @param {Number} exportingOptions.width
651 <\/svg><\/svg> * The width of the PNG or JPG image generated on the server.
652 <\/svg><\/svg> * @param {String} exportingOptions.type
653 <\/svg><\/svg> * The MIME type of the converted image.
654 <\/svg><\/svg> * @param {Number} exportingOptions.sourceWidth
655 <\/svg><\/svg> * The pixel width of the source (in-page) chart.
656 <\/svg><\/svg> * @param {Number} exportingOptions.sourceHeight
657 <\/svg><\/svg> * The pixel height of the source (in-page) chart.
658 <\/svg><\/svg> * @param {Options} chartOptions
659 <\/svg><\/svg> * Additional chart options for the exported chart. For example a
660 <\/svg><\/svg> * different background color can be added here, or `dataLabels`
661 <\/svg><\/svg> * for export only.
662 <\/svg><\/svg> *
663 <\/svg><\/svg> * @sample highcharts/members/chart-exportchart/
664 <\/svg><\/svg> * Export with no options
665 <\/svg><\/svg> * @sample highcharts/members/chart-exportchart-filename/
666 <\/svg><\/svg> * PDF type and custom filename
667 <\/svg><\/svg> * @sample highcharts/members/chart-exportchart-custom-background/
668 <\/svg><\/svg> * Different chart background in export
669 <\/svg><\/svg> * @sample stock/members/chart-exportchart/
670 <\/svg><\/svg> * Export with Highstock
671 <\/svg><\/svg> */
672 <\/svg><\/svg> exportChart: function(exportingOptions, chartOptions) {
673  
674 <\/svg><\/svg> var svg = this.getSVGForExport(exportingOptions, chartOptions);
675  
676 <\/svg><\/svg> // merge the options
677 <\/svg><\/svg> exportingOptions = merge(this.options.exporting, exportingOptions);
678  
679 <\/svg><\/svg> // do the post
680 <\/svg><\/svg> H.post(exportingOptions.url, {
681 <\/svg><\/svg> filename: exportingOptions.filename || 'chart',
682 <\/svg><\/svg> type: exportingOptions.type,
683 <\/svg><\/svg> width: exportingOptions.width || 0, // IE8 fails to post undefined correctly, so use 0
684 <\/svg><\/svg> scale: exportingOptions.scale,
685 <\/svg><\/svg> svg: svg
686 <\/svg><\/svg> }, exportingOptions.formAttributes);
687  
688 <\/svg><\/svg> },
689  
690 <\/svg><\/svg> /**
691 <\/svg><\/svg> * Exporting module required. Clears away other elements in the page and
692 <\/svg><\/svg> * prints the chart as it is displayed. By default, when the exporting
693 <\/svg><\/svg> * module is enabled, a context button with a drop down menu in the upper
694 <\/svg><\/svg> * right corner accesses this function.
695 <\/svg><\/svg> *
696 <\/svg><\/svg> * @sample highcharts/members/chart-print/
697 <\/svg><\/svg> * Print from a HTML button
698 <\/svg><\/svg> */
699 <\/svg><\/svg> print: function() {
700  
701 <\/svg><\/svg> var chart = this,
702 <\/svg><\/svg> container = chart.container,
703 <\/svg><\/svg> origDisplay = [],
704 <\/svg><\/svg> origParent = container.parentNode,
705 <\/svg><\/svg> body = doc.body,
706 <\/svg><\/svg> childNodes = body.childNodes,
707 <\/svg><\/svg> printMaxWidth = chart.options.exporting.printMaxWidth,
708 <\/svg><\/svg> resetParams,
709 <\/svg><\/svg> handleMaxWidth;
710  
711 <\/svg><\/svg> if (chart.isPrinting) { // block the button while in printing mode
712 <\/svg><\/svg> return;
713 <\/svg><\/svg> }
714  
715 <\/svg><\/svg> chart.isPrinting = true;
716 <\/svg><\/svg> chart.pointer.reset(null, 0);
717  
718 <\/svg><\/svg> fireEvent(chart, 'beforePrint');
719  
720 <\/svg><\/svg> // Handle printMaxWidth
721 <\/svg><\/svg> handleMaxWidth = printMaxWidth && chart.chartWidth > printMaxWidth;
722 <\/svg><\/svg> if (handleMaxWidth) {
723 <\/svg><\/svg> resetParams = [chart.options.chart.width, undefined, false];
724 <\/svg><\/svg> chart.setSize(printMaxWidth, undefined, false);
725 <\/svg><\/svg> }
726  
727 <\/svg><\/svg> // hide all body content
728 <\/svg><\/svg> each(childNodes, function(node, i) {
729 <\/svg><\/svg> if (node.nodeType === 1) {
730 <\/svg><\/svg> origDisplay[i] = node.style.display;
731 <\/svg><\/svg> node.style.display = 'none';
732 <\/svg><\/svg> }
733 <\/svg><\/svg> });
734  
735 <\/svg><\/svg> // pull out the chart
736 <\/svg><\/svg> body.appendChild(container);
737  
738 <\/svg><\/svg> // print
739 <\/svg><\/svg> win.focus(); // #1510
740 <\/svg><\/svg> win.print();
741  
742 <\/svg><\/svg> // allow the browser to prepare before reverting
743 <\/svg><\/svg> setTimeout(function() {
744  
745 <\/svg><\/svg> // put the chart back in
746 <\/svg><\/svg> origParent.appendChild(container);
747  
748 <\/svg><\/svg> // restore all body content
749 <\/svg><\/svg> each(childNodes, function(node, i) {
750 <\/svg><\/svg> if (node.nodeType === 1) {
751 <\/svg><\/svg> node.style.display = origDisplay[i];
752 <\/svg><\/svg> }
753 <\/svg><\/svg> });
754  
755 <\/svg><\/svg> chart.isPrinting = false;
756  
757 <\/svg><\/svg> // Reset printMaxWidth
758 <\/svg><\/svg> if (handleMaxWidth) {
759 <\/svg><\/svg> chart.setSize.apply(chart, resetParams);
760 <\/svg><\/svg> }
761  
762 <\/svg><\/svg> fireEvent(chart, 'afterPrint');
763  
764 <\/svg><\/svg> }, 1000);
765  
766 <\/svg><\/svg> },
767  
768 <\/svg><\/svg> /**
769 <\/svg><\/svg> * Display a popup menu for choosing the export type.
770 <\/svg><\/svg> *
771 <\/svg><\/svg> * @private
772 <\/svg><\/svg> *
773 <\/svg><\/svg> * @param {String} className An identifier for the menu
774 <\/svg><\/svg> * @param {Array} items A collection with text and onclicks for the items
775 <\/svg><\/svg> * @param {Number} x The x position of the opener button
776 <\/svg><\/svg> * @param {Number} y The y position of the opener button
777 <\/svg><\/svg> * @param {Number} width The width of the opener button
778 <\/svg><\/svg> * @param {Number} height The height of the opener button
779 <\/svg><\/svg> */
780 <\/svg><\/svg> contextMenu: function(className, items, x, y, width, height, button) {
781 <\/svg><\/svg> var chart = this,
782 <\/svg><\/svg> navOptions = chart.options.navigation,
783 <\/svg><\/svg> chartWidth = chart.chartWidth,
784 <\/svg><\/svg> chartHeight = chart.chartHeight,
785 <\/svg><\/svg> cacheName = 'cache-' + className,
786 <\/svg><\/svg> menu = chart[cacheName],
787 <\/svg><\/svg> menuPadding = Math.max(width, height), // for mouse leave detection
788 <\/svg><\/svg> innerMenu,
789 <\/svg><\/svg> hide,
790 <\/svg><\/svg> menuStyle;
791  
792 <\/svg><\/svg> // create the menu only the first time
793 <\/svg><\/svg> if (!menu) {
794  
795 <\/svg><\/svg> // create a HTML element above the SVG
796 <\/svg><\/svg> chart[cacheName] = menu = createElement('div', {
797 <\/svg><\/svg> className: className
798 <\/svg><\/svg> }, {
799 <\/svg><\/svg> position: 'absolute',
800 <\/svg><\/svg> zIndex: 1000,
801 <\/svg><\/svg> padding: menuPadding + 'px'
802 <\/svg><\/svg> }, chart.container);
803  
804 <\/svg><\/svg> innerMenu = createElement('div', {
805 <\/svg><\/svg> className: 'highcharts-menu'
806 <\/svg><\/svg> }, null, menu);
807  
808  
809  
810 <\/svg><\/svg> // hide on mouse out
811 <\/svg><\/svg> hide = function() {
812 <\/svg><\/svg> css(menu, {
813 <\/svg><\/svg> display: 'none'
814 <\/svg><\/svg> });
815 <\/svg><\/svg> if (button) {
816 <\/svg><\/svg> button.setState(0);
817 <\/svg><\/svg> }
818 <\/svg><\/svg> chart.openMenu = false;
819 <\/svg><\/svg> };
820  
821 <\/svg><\/svg> // Hide the menu some time after mouse leave (#1357)
822 <\/svg><\/svg> chart.exportEvents.push(
823 <\/svg><\/svg> addEvent(menu, 'mouseleave', function() {
824 <\/svg><\/svg> menu.hideTimer = setTimeout(hide, 500);
825 <\/svg><\/svg> }),
826 <\/svg><\/svg> addEvent(menu, 'mouseenter', function() {
827 <\/svg><\/svg> clearTimeout(menu.hideTimer);
828 <\/svg><\/svg> }),
829  
830 <\/svg><\/svg> // Hide it on clicking or touching outside the menu (#2258, #2335,
831 <\/svg><\/svg> // #2407)
832 <\/svg><\/svg> addEvent(doc, 'mouseup', function(e) {
833 <\/svg><\/svg> if (!chart.pointer.inClass(e.target, className)) {
834 <\/svg><\/svg> hide();
835 <\/svg><\/svg> }
836 <\/svg><\/svg> })
837 <\/svg><\/svg> );
838  
839 <\/svg><\/svg> // create the items
840 <\/svg><\/svg> each(items, function(item) {
841  
842 <\/svg><\/svg> if (typeof item === 'string') {
843 <\/svg><\/svg> item = chart.options.exporting.menuItemDefinitions[item];
844 <\/svg><\/svg> }
845  
846 <\/svg><\/svg> if (H.isObject(item, true)) {
847 <\/svg><\/svg> var element;
848  
849 <\/svg><\/svg> if (item.separator) {
850 <\/svg><\/svg> element = createElement('hr', null, null, innerMenu);
851  
852 <\/svg><\/svg> } else {
853 <\/svg><\/svg> element = createElement('div', {
854 <\/svg><\/svg> className: 'highcharts-menu-item',
855 <\/svg><\/svg> onclick: function(e) {
856 <\/svg><\/svg> if (e) { // IE7
857 <\/svg><\/svg> e.stopPropagation();
858 <\/svg><\/svg> }
859 <\/svg><\/svg> hide();
860 <\/svg><\/svg> if (item.onclick) {
861 <\/svg><\/svg> item.onclick.apply(chart, arguments);
862 <\/svg><\/svg> }
863 <\/svg><\/svg> },
864 <\/svg><\/svg> innerHTML: item.text || chart.options.lang[item.textKey]
865 <\/svg><\/svg> }, null, innerMenu);
866  
867  
868 <\/svg><\/svg> }
869  
870 <\/svg><\/svg> // Keep references to menu divs to be able to destroy them
871 <\/svg><\/svg> chart.exportDivElements.push(element);
872 <\/svg><\/svg> }
873 <\/svg><\/svg> });
874  
875 <\/svg><\/svg> // Keep references to menu and innerMenu div to be able to destroy them
876 <\/svg><\/svg> chart.exportDivElements.push(innerMenu, menu);
877  
878 <\/svg><\/svg> chart.exportMenuWidth = menu.offsetWidth;
879 <\/svg><\/svg> chart.exportMenuHeight = menu.offsetHeight;
880 <\/svg><\/svg> }
881  
882 <\/svg><\/svg> menuStyle = {
883 <\/svg><\/svg> display: 'block'
884 <\/svg><\/svg> };
885  
886 <\/svg><\/svg> // if outside right, right align it
887 <\/svg><\/svg> if (x + chart.exportMenuWidth > chartWidth) {
888 <\/svg><\/svg> menuStyle.right = (chartWidth - x - width - menuPadding) + 'px';
889 <\/svg><\/svg> } else {
890 <\/svg><\/svg> menuStyle.left = (x - menuPadding) + 'px';
891 <\/svg><\/svg> }
892 <\/svg><\/svg> // if outside bottom, bottom align it
893 <\/svg><\/svg> if (y + height + chart.exportMenuHeight > chartHeight && button.alignOptions.verticalAlign !== 'top') {
894 <\/svg><\/svg> menuStyle.bottom = (chartHeight - y - menuPadding) + 'px';
895 <\/svg><\/svg> } else {
896 <\/svg><\/svg> menuStyle.top = (y + height - menuPadding) + 'px';
897 <\/svg><\/svg> }
898  
899 <\/svg><\/svg> css(menu, menuStyle);
900 <\/svg><\/svg> chart.openMenu = true;
901 <\/svg><\/svg> },
902  
903 <\/svg><\/svg> /**
904 <\/svg><\/svg> * Add the export button to the chart, with options.
905 <\/svg><\/svg> *
906 <\/svg><\/svg> * @private
907 <\/svg><\/svg> */
908 <\/svg><\/svg> addButton: function(options) {
909 <\/svg><\/svg> var chart = this,
910 <\/svg><\/svg> renderer = chart.renderer,
911 <\/svg><\/svg> btnOptions = merge(chart.options.navigation.buttonOptions, options),
912 <\/svg><\/svg> onclick = btnOptions.onclick,
913 <\/svg><\/svg> menuItems = btnOptions.menuItems,
914 <\/svg><\/svg> symbol,
915 <\/svg><\/svg> button,
916 <\/svg><\/svg> symbolSize = btnOptions.symbolSize || 12;
917 <\/svg><\/svg> if (!chart.btnCount) {
918 <\/svg><\/svg> chart.btnCount = 0;
919 <\/svg><\/svg> }
920  
921 <\/svg><\/svg> // Keeps references to the button elements
922 <\/svg><\/svg> if (!chart.exportDivElements) {
923 <\/svg><\/svg> chart.exportDivElements = [];
924 <\/svg><\/svg> chart.exportSVGElements = [];
925 <\/svg><\/svg> }
926  
927 <\/svg><\/svg> if (btnOptions.enabled === false) {
928 <\/svg><\/svg> return;
929 <\/svg><\/svg> }
930  
931  
932 <\/svg><\/svg> var attr = btnOptions.theme,
933 <\/svg><\/svg> states = attr.states,
934 <\/svg><\/svg> hover = states && states.hover,
935 <\/svg><\/svg> select = states && states.select,
936 <\/svg><\/svg> callback;
937  
938 <\/svg><\/svg> delete attr.states;
939  
940 <\/svg><\/svg> if (onclick) {
941 <\/svg><\/svg> callback = function(e) {
942 <\/svg><\/svg> e.stopPropagation();
943 <\/svg><\/svg> onclick.call(chart, e);
944 <\/svg><\/svg> };
945  
946 <\/svg><\/svg> } else if (menuItems) {
947 <\/svg><\/svg> callback = function() {
948 <\/svg><\/svg> chart.contextMenu(
949 <\/svg><\/svg> button.menuClassName,
950 <\/svg><\/svg> menuItems,
951 <\/svg><\/svg> button.translateX,
952 <\/svg><\/svg> button.translateY,
953 <\/svg><\/svg> button.width,
954 <\/svg><\/svg> button.height,
955 <\/svg><\/svg> button
956 <\/svg><\/svg> );
957 <\/svg><\/svg> button.setState(2);
958 <\/svg><\/svg> };
959 <\/svg><\/svg> }
960  
961  
962 <\/svg><\/svg> if (btnOptions.text && btnOptions.symbol) {
963 <\/svg><\/svg> attr.paddingLeft = pick(attr.paddingLeft, 25);
964  
965 <\/svg><\/svg> } else if (!btnOptions.text) {
966 <\/svg><\/svg> extend(attr, {
967 <\/svg><\/svg> width: btnOptions.width,
968 <\/svg><\/svg> height: btnOptions.height,
969 <\/svg><\/svg> padding: 0
970 <\/svg><\/svg> });
971 <\/svg><\/svg> }
972  
973 <\/svg><\/svg> button = renderer.button(btnOptions.text, 0, 0, callback, attr, hover, select)
974 <\/svg><\/svg> .addClass(options.className)
975 <\/svg><\/svg> .attr({
976  
977 <\/svg><\/svg> title: chart.options.lang[btnOptions._titleKey],
978 <\/svg><\/svg> zIndex: 3 // #4955
979 <\/svg><\/svg> });
980 <\/svg><\/svg> button.menuClassName = options.menuClassName || 'highcharts-menu-' + chart.btnCount++;
981  
982 <\/svg><\/svg> if (btnOptions.symbol) {
983 <\/svg><\/svg> symbol = renderer.symbol(
984 <\/svg><\/svg> btnOptions.symbol,
985 <\/svg><\/svg> btnOptions.symbolX - (symbolSize / 2),
986 <\/svg><\/svg> btnOptions.symbolY - (symbolSize / 2),
987 <\/svg><\/svg> symbolSize,
988 <\/svg><\/svg> symbolSize
989 <\/svg><\/svg> )
990 <\/svg><\/svg> .addClass('highcharts-button-symbol')
991 <\/svg><\/svg> .attr({
992 <\/svg><\/svg> zIndex: 1
993 <\/svg><\/svg> }).add(button);
994  
995  
996 <\/svg><\/svg> }
997  
998 <\/svg><\/svg> button.add()
999 <\/svg><\/svg> .align(extend(btnOptions, {
1000 <\/svg><\/svg> width: button.width,
1001 <\/svg><\/svg> x: pick(btnOptions.x, chart.buttonOffset) // #1654
1002 <\/svg><\/svg> }), true, 'spacingBox');
1003  
1004 <\/svg><\/svg> chart.buttonOffset += (button.width + btnOptions.buttonSpacing) * (btnOptions.align === 'right' ? -1 : 1);
1005  
1006 <\/svg><\/svg> chart.exportSVGElements.push(button, symbol);
1007  
1008 <\/svg><\/svg> },
1009  
1010 <\/svg><\/svg> /**
1011 <\/svg><\/svg> * Destroy the export buttons.
1012 <\/svg><\/svg> *
1013 <\/svg><\/svg> * @private
1014 <\/svg><\/svg> */
1015 <\/svg><\/svg> destroyExport: function(e) {
1016 <\/svg><\/svg> var chart = e ? e.target : this,
1017 <\/svg><\/svg> exportSVGElements = chart.exportSVGElements,
1018 <\/svg><\/svg> exportDivElements = chart.exportDivElements,
1019 <\/svg><\/svg> exportEvents = chart.exportEvents,
1020 <\/svg><\/svg> cacheName;
1021  
1022 <\/svg><\/svg> // Destroy the extra buttons added
1023 <\/svg><\/svg> if (exportSVGElements) {
1024 <\/svg><\/svg> each(exportSVGElements, function(elem, i) {
1025  
1026 <\/svg><\/svg> // Destroy and null the svg/vml elements
1027 <\/svg><\/svg> if (elem) { // #1822
1028 <\/svg><\/svg> elem.onclick = elem.ontouchstart = null;
1029 <\/svg><\/svg> cacheName = 'cache-' + elem.menuClassName;
1030  
1031 <\/svg><\/svg> if (chart[cacheName]) {
1032 <\/svg><\/svg> delete chart[cacheName];
1033 <\/svg><\/svg> }
1034  
1035 <\/svg><\/svg> chart.exportSVGElements[i] = elem.destroy();
1036 <\/svg><\/svg> }
1037 <\/svg><\/svg> });
1038 <\/svg><\/svg> exportSVGElements.length = 0;
1039 <\/svg><\/svg> }
1040  
1041 <\/svg><\/svg> // Destroy the divs for the menu
1042 <\/svg><\/svg> if (exportDivElements) {
1043 <\/svg><\/svg> each(exportDivElements, function(elem, i) {
1044  
1045 <\/svg><\/svg> // Remove the event handler
1046 <\/svg><\/svg> clearTimeout(elem.hideTimer); // #5427
1047 <\/svg><\/svg> removeEvent(elem, 'mouseleave');
1048  
1049 <\/svg><\/svg> // Remove inline events
1050 <\/svg><\/svg> chart.exportDivElements[i] = elem.onmouseout = elem.onmouseover = elem.ontouchstart = elem.onclick = null;
1051  
1052 <\/svg><\/svg> // Destroy the div by moving to garbage bin
1053 <\/svg><\/svg> discardElement(elem);
1054 <\/svg><\/svg> });
1055 <\/svg><\/svg> exportDivElements.length = 0;
1056 <\/svg><\/svg> }
1057  
1058 <\/svg><\/svg> if (exportEvents) {
1059 <\/svg><\/svg> each(exportEvents, function(unbind) {
1060 <\/svg><\/svg> unbind();
1061 <\/svg><\/svg> });
1062 <\/svg><\/svg> exportEvents.length = 0;
1063 <\/svg><\/svg> }
1064 <\/svg><\/svg> }
1065 <\/svg><\/svg> });
1066  
1067  
1068 <\/svg><\/svg> // These ones are translated to attributes rather than styles
1069 <\/svg><\/svg> SVGRenderer.prototype.inlineToAttributes = [
1070 <\/svg><\/svg> 'fill',
1071 <\/svg><\/svg> 'stroke',
1072 <\/svg><\/svg> 'strokeLinecap',
1073 <\/svg><\/svg> 'strokeLinejoin',
1074 <\/svg><\/svg> 'strokeWidth',
1075 <\/svg><\/svg> 'textAnchor',
1076 <\/svg><\/svg> 'x',
1077 <\/svg><\/svg> 'y'
1078 <\/svg><\/svg> ];
1079 <\/svg><\/svg> // These CSS properties are not inlined. Remember camelCase.
1080 <\/svg><\/svg> SVGRenderer.prototype.inlineBlacklist = [
1081 <\/svg><\/svg> /-/, // In Firefox, both hyphened and camelCased names are listed
1082 <\/svg><\/svg> /^(clipPath|cssText|d|height|width)$/, // Full words
1083 <\/svg><\/svg> /^font$/, // more specific props are set
1084 <\/svg><\/svg> /[lL]ogical(Width|Height)$/,
1085 <\/svg><\/svg> /perspective/,
1086 <\/svg><\/svg> /TapHighlightColor/,
1087 <\/svg><\/svg> /^transition/
1088 <\/svg><\/svg> // /^text (border|color|cursor|height|webkitBorder)/
1089 <\/svg><\/svg> ];
1090 <\/svg><\/svg> SVGRenderer.prototype.unstyledElements = [
1091 <\/svg><\/svg> 'clipPath',
1092 <\/svg><\/svg> 'defs',
1093 <\/svg><\/svg> 'desc'
1094 <\/svg><\/svg> ];
1095  
1096 <\/svg><\/svg> /**
1097 <\/svg><\/svg> * Analyze inherited styles from stylesheets and add them inline
1098 <\/svg><\/svg> *
1099 <\/svg><\/svg> * @todo: What are the border styles for text about? In general, text has a lot of properties.
1100 <\/svg><\/svg> * @todo: Make it work with IE9 and IE10.
1101 <\/svg><\/svg> */
1102 <\/svg><\/svg> Chart.prototype.inlineStyles = function() {
1103 <\/svg><\/svg> var renderer = this.renderer,
1104 <\/svg><\/svg> inlineToAttributes = renderer.inlineToAttributes,
1105 <\/svg><\/svg> blacklist = renderer.inlineBlacklist,
1106 <\/svg><\/svg> whitelist = renderer.inlineWhitelist, // For IE
1107 <\/svg><\/svg> unstyledElements = renderer.unstyledElements,
1108 <\/svg><\/svg> defaultStyles = {},
1109 <\/svg><\/svg> dummySVG;
1110  
1111 <\/svg><\/svg> /**
1112 <\/svg><\/svg> * Make hyphenated property names out of camelCase
1113 <\/svg><\/svg> */
1114 <\/svg><\/svg> function hyphenate(prop) {
1115 <\/svg><\/svg> return prop.replace(
1116 <\/svg><\/svg> /([A-Z])/g,
1117 <\/svg><\/svg> function(a, b) {
1118 <\/svg><\/svg> return '-' + b.toLowerCase();
1119 <\/svg><\/svg> }
1120 <\/svg><\/svg> );
1121 <\/svg><\/svg> }
1122  
1123 <\/svg><\/svg> /**
1124 <\/svg><\/svg> * Call this on all elements and recurse to children
1125 <\/svg><\/svg> */
1126 <\/svg><\/svg> function recurse(node) {
1127 <\/svg><\/svg> var styles,
1128 <\/svg><\/svg> parentStyles,
1129 <\/svg><\/svg> cssText = '',
1130 <\/svg><\/svg> dummy,
1131 <\/svg><\/svg> styleAttr,
1132 <\/svg><\/svg> blacklisted,
1133 <\/svg><\/svg> whitelisted,
1134 <\/svg><\/svg> i;
1135  
1136 <\/svg><\/svg> // Check computed styles and whether they are in the white/blacklist for
1137 <\/svg><\/svg> // styles or atttributes
1138 <\/svg><\/svg> function filterStyles(val, prop) {
1139  
1140 <\/svg><\/svg> // Check against whitelist & blacklist
1141 <\/svg><\/svg> blacklisted = whitelisted = false;
1142 <\/svg><\/svg> if (whitelist) {
1143 <\/svg><\/svg> // Styled mode in IE has a whitelist instead.
1144 <\/svg><\/svg> // Exclude all props not in this list.
1145 <\/svg><\/svg> i = whitelist.length;
1146 <\/svg><\/svg> while (i-- && !whitelisted) {
1147 <\/svg><\/svg> whitelisted = whitelist[i].test(prop);
1148 <\/svg><\/svg> }
1149 <\/svg><\/svg> blacklisted = !whitelisted;
1150 <\/svg><\/svg> }
1151  
1152 <\/svg><\/svg> // Explicitly remove empty transforms
1153 <\/svg><\/svg> if (prop === 'transform' && val === 'none') {
1154 <\/svg><\/svg> blacklisted = true;
1155 <\/svg><\/svg> }
1156  
1157 <\/svg><\/svg> i = blacklist.length;
1158 <\/svg><\/svg> while (i-- && !blacklisted) {
1159 <\/svg><\/svg> blacklisted = blacklist[i].test(prop) || typeof val === 'function';
1160 <\/svg><\/svg> }
1161  
1162 <\/svg><\/svg> if (!blacklisted) {
1163 <\/svg><\/svg> // If parent node has the same style, it gets inherited, no need to inline it
1164 <\/svg><\/svg> if (parentStyles[prop] !== val && defaultStyles[node.nodeName][prop] !== val) {
1165 <\/svg><\/svg> // Attributes
1166 <\/svg><\/svg> if (inlineToAttributes.indexOf(prop) !== -1) {
1167 <\/svg><\/svg> node.setAttribute(hyphenate(prop), val);
1168 <\/svg><\/svg> // Styles
1169 <\/svg><\/svg> } else {
1170 <\/svg><\/svg> cssText += hyphenate(prop) + ':' + val + ';';
1171 <\/svg><\/svg> }
1172 <\/svg><\/svg> }
1173 <\/svg><\/svg> }
1174 <\/svg><\/svg> }
1175  
1176 <\/svg><\/svg> if (node.nodeType === 1 && unstyledElements.indexOf(node.nodeName) === -1) {
1177 <\/svg><\/svg> styles = win.getComputedStyle(node, null);
1178 <\/svg><\/svg> parentStyles = node.nodeName === 'svg' ? {} : win.getComputedStyle(node.parentNode, null);
1179  
1180 <\/svg><\/svg> // Get default styles from the browser so that we don't have to add these
1181 <\/svg><\/svg> if (!defaultStyles[node.nodeName]) {
1182 <\/svg><\/svg> if (!dummySVG) {
1183 <\/svg><\/svg> dummySVG = doc.createElementNS(H.SVG_NS, 'svg');
1184 <\/svg><\/svg> dummySVG.setAttribute('version', '1.1');
1185 <\/svg><\/svg> doc.body.appendChild(dummySVG);
1186 <\/svg><\/svg> }
1187 <\/svg><\/svg> dummy = doc.createElementNS(node.namespaceURI, node.nodeName);
1188 <\/svg><\/svg> dummySVG.appendChild(dummy);
1189 <\/svg><\/svg> defaultStyles[node.nodeName] = merge(win.getComputedStyle(dummy, null)); // Copy, so we can remove the node
1190 <\/svg><\/svg> dummySVG.removeChild(dummy);
1191 <\/svg><\/svg> }
1192  
1193 <\/svg><\/svg> // Loop through all styles and add them inline if they are ok
1194 <\/svg><\/svg> if (isFirefoxBrowser || isMSBrowser) {
1195 <\/svg><\/svg> // Some browsers put lots of styles on the prototype
1196 <\/svg><\/svg> for (var p in styles) {
1197 <\/svg><\/svg> filterStyles(styles[p], p);
1198 <\/svg><\/svg> }
1199 <\/svg><\/svg> } else {
1200 <\/svg><\/svg> objectEach(styles, filterStyles);
1201 <\/svg><\/svg> }
1202  
1203 <\/svg><\/svg> // Apply styles
1204 <\/svg><\/svg> if (cssText) {
1205 <\/svg><\/svg> styleAttr = node.getAttribute('style');
1206 <\/svg><\/svg> node.setAttribute('style', (styleAttr ? styleAttr + ';' : '') + cssText);
1207 <\/svg><\/svg> }
1208  
1209 <\/svg><\/svg> // Set default stroke width (needed at least for IE)
1210 <\/svg><\/svg> if (node.nodeName === 'svg') {
1211 <\/svg><\/svg> node.setAttribute('stroke-width', '1px');
1212 <\/svg><\/svg> }
1213  
1214 <\/svg><\/svg> if (node.nodeName === 'text') {
1215 <\/svg><\/svg> return;
1216 <\/svg><\/svg> }
1217  
1218 <\/svg><\/svg> // Recurse
1219 <\/svg><\/svg> each(node.children || node.childNodes, recurse);
1220 <\/svg><\/svg> }
1221 <\/svg><\/svg> }
1222  
1223 <\/svg><\/svg> /**
1224 <\/svg><\/svg> * Remove the dummy objects used to get defaults
1225 <\/svg><\/svg> */
1226 <\/svg><\/svg> function tearDown() {
1227 <\/svg><\/svg> dummySVG.parentNode.removeChild(dummySVG);
1228 <\/svg><\/svg> }
1229  
1230 <\/svg><\/svg> recurse(this.container.querySelector('svg'));
1231 <\/svg><\/svg> tearDown();
1232  
1233 <\/svg><\/svg> };
1234  
1235  
1236  
1237 <\/svg><\/svg> symbols.menu = function(x, y, width, height) {
1238 <\/svg><\/svg> var arr = [
1239 <\/svg><\/svg> 'M', x, y + 2.5,
1240 <\/svg><\/svg> 'L', x + width, y + 2.5,
1241 <\/svg><\/svg> 'M', x, y + height / 2 + 0.5,
1242 <\/svg><\/svg> 'L', x + width, y + height / 2 + 0.5,
1243 <\/svg><\/svg> 'M', x, y + height - 1.5,
1244 <\/svg><\/svg> 'L', x + width, y + height - 1.5
1245 <\/svg><\/svg> ];
1246 <\/svg><\/svg> return arr;
1247 <\/svg><\/svg> };
1248  
1249 <\/svg><\/svg> // Add the buttons on chart load
1250 <\/svg><\/svg> Chart.prototype.renderExporting = function() {
1251 <\/svg><\/svg> var chart = this,
1252 <\/svg><\/svg> exportingOptions = chart.options.exporting,
1253 <\/svg><\/svg> buttons = exportingOptions.buttons,
1254 <\/svg><\/svg> isDirty = chart.isDirtyExporting || !chart.exportSVGElements;
1255  
1256 <\/svg><\/svg> chart.buttonOffset = 0;
1257 <\/svg><\/svg> if (chart.isDirtyExporting) {
1258 <\/svg><\/svg> chart.destroyExport();
1259 <\/svg><\/svg> }
1260  
1261 <\/svg><\/svg> if (isDirty && exportingOptions.enabled !== false) {
1262 <\/svg><\/svg> chart.exportEvents = [];
1263  
1264 <\/svg><\/svg> objectEach(buttons, function(button) {
1265 <\/svg><\/svg> chart.addButton(button);
1266 <\/svg><\/svg> });
1267  
1268 <\/svg><\/svg> chart.isDirtyExporting = false;
1269 <\/svg><\/svg> }
1270  
1271 <\/svg><\/svg> // Destroy the export elements at chart destroy
1272 <\/svg><\/svg> addEvent(chart, 'destroy', chart.destroyExport);
1273 <\/svg><\/svg> };
1274  
1275 <\/svg><\/svg> Chart.prototype.callbacks.push(function(chart) {
1276  
1277 <\/svg><\/svg> function update(prop, options, redraw) {
1278 <\/svg><\/svg> chart.isDirtyExporting = true;
1279 <\/svg><\/svg> merge(true, chart.options[prop], options);
1280 <\/svg><\/svg> if (pick(redraw, true)) {
1281 <\/svg><\/svg> chart.redraw();
1282 <\/svg><\/svg> }
1283  
1284 <\/svg><\/svg> }
1285  
1286 <\/svg><\/svg> chart.renderExporting();
1287  
1288 <\/svg><\/svg> addEvent(chart, 'redraw', chart.renderExporting);
1289  
1290 <\/svg><\/svg> // Add update methods to handle chart.update and chart.exporting.update
1291 <\/svg><\/svg> // and chart.navigation.update.
1292 <\/svg><\/svg> each(['exporting', 'navigation'], function(prop) {
1293 <\/svg><\/svg> chart[prop] = {
1294 <\/svg><\/svg> update: function(options, redraw) {
1295 <\/svg><\/svg> update(prop, options, redraw);
1296 <\/svg><\/svg> }
1297 <\/svg><\/svg> };
1298 <\/svg><\/svg> });
1299  
1300 <\/svg><\/svg> // Uncomment this to see a button directly below the chart, for quick
1301 <\/svg><\/svg> // testing of export
1302 <\/svg><\/svg> /*
1303 <\/svg><\/svg> if (!chart.renderer.forExport) {
1304 <\/svg><\/svg> var button;
1305  
1306 <\/svg><\/svg> // View SVG Image
1307 <\/svg><\/svg> button = doc.createElement('button');
1308 <\/svg><\/svg> button.innerHTML = 'View SVG Image';
1309 <\/svg><\/svg> chart.renderTo.parentNode.appendChild(button);
1310 <\/svg><\/svg> button.onclick = function () {
1311 <\/svg><\/svg> var div = doc.createElement('div');
1312 <\/svg><\/svg> div.innerHTML = chart.getSVGForExport();
1313 <\/svg><\/svg> chart.renderTo.parentNode.appendChild(div);
1314 <\/svg><\/svg> };
1315  
1316 <\/svg><\/svg> // View SVG Source
1317 <\/svg><\/svg> button = doc.createElement('button');
1318 <\/svg><\/svg> button.innerHTML = 'View SVG Source';
1319 <\/svg><\/svg> chart.renderTo.parentNode.appendChild(button);
1320 <\/svg><\/svg> button.onclick = function () {
1321 <\/svg><\/svg> var pre = doc.createElement('pre');
1322 <\/svg><\/svg> pre.innerHTML = chart.getSVGForExport()
1323 <\/svg><\/svg> .replace(/</g, '\n&lt;')
1324 <\/svg><\/svg> .replace(/>/g, '&gt;');
1325 <\/svg><\/svg> chart.renderTo.parentNode.appendChild(pre);
1326 <\/svg><\/svg> };
1327 <\/svg><\/svg> }
1328 <\/svg><\/svg> // */
1329 <\/svg><\/svg> });
1330  
1331 <\/svg><\/svg> }(Highcharts));
1332 <\/svg><\/svg>}));