corrade-nucleus-nucleons – Blame information for rev

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