1 | /** |
---|
2 | * @license Highcharts JS v3.0.5 (2013-08-23) |
---|
3 | * Exporting module |
---|
4 | * |
---|
5 | * (c) 2010-2013 Torstein HÞnsi |
---|
6 | * |
---|
7 | * License: www.highcharts.com/license |
---|
8 | */ |
---|
9 | |
---|
10 | // JSLint options: |
---|
11 | /*global Highcharts, document, window, Math, setTimeout */ |
---|
12 | |
---|
13 | (function (Highcharts) { // encapsulate |
---|
14 | |
---|
15 | // create shortcuts |
---|
16 | var Chart = Highcharts.Chart, |
---|
17 | addEvent = Highcharts.addEvent, |
---|
18 | removeEvent = Highcharts.removeEvent, |
---|
19 | createElement = Highcharts.createElement, |
---|
20 | discardElement = Highcharts.discardElement, |
---|
21 | css = Highcharts.css, |
---|
22 | merge = Highcharts.merge, |
---|
23 | each = Highcharts.each, |
---|
24 | extend = Highcharts.extend, |
---|
25 | math = Math, |
---|
26 | mathMax = math.max, |
---|
27 | doc = document, |
---|
28 | win = window, |
---|
29 | isTouchDevice = Highcharts.isTouchDevice, |
---|
30 | M = 'M', |
---|
31 | L = 'L', |
---|
32 | DIV = 'div', |
---|
33 | HIDDEN = 'hidden', |
---|
34 | NONE = 'none', |
---|
35 | PREFIX = 'highcharts-', |
---|
36 | ABSOLUTE = 'absolute', |
---|
37 | PX = 'px', |
---|
38 | UNDEFINED, |
---|
39 | symbols = Highcharts.Renderer.prototype.symbols, |
---|
40 | defaultOptions = Highcharts.getOptions(), |
---|
41 | buttonOffset; |
---|
42 | |
---|
43 | // Add language |
---|
44 | extend(defaultOptions.lang, { |
---|
45 | printChart: 'Imprimir Gráfico', |
---|
46 | downloadPNG: 'Descargar imagen PNG', |
---|
47 | downloadJPEG: 'Descargar imagen JPEG', |
---|
48 | downloadPDF: 'Descargar documento PDF', |
---|
49 | downloadSVG: 'Descargar imagen de vector SVG', |
---|
50 | contextButtonTitle: 'Chart context menu' |
---|
51 | }); |
---|
52 | |
---|
53 | // Buttons and menus are collected in a separate config option set called 'navigation'. |
---|
54 | // This can be extended later to add control buttons like zoom and pan right click menus. |
---|
55 | defaultOptions.navigation = { |
---|
56 | menuStyle: { |
---|
57 | border: '1px solid #A0A0A0', |
---|
58 | background: '#FFFFFF', |
---|
59 | padding: '5px 0' |
---|
60 | }, |
---|
61 | menuItemStyle: { |
---|
62 | padding: '0 10px', |
---|
63 | background: NONE, |
---|
64 | color: '#303030', |
---|
65 | fontSize: isTouchDevice ? '14px' : '11px' |
---|
66 | }, |
---|
67 | menuItemHoverStyle: { |
---|
68 | background: '#4572A5', |
---|
69 | color: '#FFFFFF' |
---|
70 | }, |
---|
71 | |
---|
72 | buttonOptions: { |
---|
73 | symbolFill: '#E0E0E0', |
---|
74 | symbolSize: 14, |
---|
75 | symbolStroke: '#666', |
---|
76 | symbolStrokeWidth: 3, |
---|
77 | symbolX: 12.5, |
---|
78 | symbolY: 10.5, |
---|
79 | align: 'right', |
---|
80 | buttonSpacing: 3, |
---|
81 | height: 22, |
---|
82 | // text: null, |
---|
83 | theme: { |
---|
84 | fill: 'white', // capture hover |
---|
85 | stroke: 'none' |
---|
86 | }, |
---|
87 | verticalAlign: 'top', |
---|
88 | width: 24 |
---|
89 | } |
---|
90 | }; |
---|
91 | |
---|
92 | |
---|
93 | |
---|
94 | // Add the export related options |
---|
95 | defaultOptions.exporting = { |
---|
96 | //enabled: true, |
---|
97 | //filename: 'chart', |
---|
98 | type: 'image/png', |
---|
99 | url: 'http://export.highcharts.com/', |
---|
100 | //width: undefined, |
---|
101 | //scale: 2 |
---|
102 | buttons: { |
---|
103 | contextButton: { |
---|
104 | //x: -10, |
---|
105 | symbol: 'menu', |
---|
106 | _titleKey: 'contextButtonTitle', |
---|
107 | menuItems: [{ |
---|
108 | textKey: 'printChart', |
---|
109 | onclick: function () { |
---|
110 | this.print(); |
---|
111 | } |
---|
112 | }, { |
---|
113 | separator: true |
---|
114 | }, { |
---|
115 | textKey: 'downloadPNG', |
---|
116 | onclick: function () { |
---|
117 | this.exportChart(); |
---|
118 | } |
---|
119 | }, { |
---|
120 | textKey: 'downloadJPEG', |
---|
121 | onclick: function () { |
---|
122 | this.exportChart({ |
---|
123 | type: 'image/jpeg' |
---|
124 | }); |
---|
125 | } |
---|
126 | }, { |
---|
127 | textKey: 'downloadPDF', |
---|
128 | onclick: function () { |
---|
129 | this.exportChart({ |
---|
130 | type: 'application/pdf' |
---|
131 | }); |
---|
132 | } |
---|
133 | }, { |
---|
134 | textKey: 'downloadSVG', |
---|
135 | onclick: function () { |
---|
136 | this.exportChart({ |
---|
137 | type: 'image/svg+xml' |
---|
138 | }); |
---|
139 | } |
---|
140 | } |
---|
141 | // Enable this block to add "View SVG" to the dropdown menu |
---|
142 | /* |
---|
143 | ,{ |
---|
144 | |
---|
145 | text: 'View SVG', |
---|
146 | onclick: function () { |
---|
147 | var svg = this.getSVG() |
---|
148 | .replace(/</g, '\n<') |
---|
149 | .replace(/>/g, '>'); |
---|
150 | |
---|
151 | doc.body.innerHTML = '<pre>' + svg + '</pre>'; |
---|
152 | } |
---|
153 | } // */ |
---|
154 | ] |
---|
155 | } |
---|
156 | } |
---|
157 | }; |
---|
158 | |
---|
159 | // Add the Highcharts.post utility |
---|
160 | Highcharts.post = function (url, data) { |
---|
161 | var name, |
---|
162 | form; |
---|
163 | |
---|
164 | // create the form |
---|
165 | form = createElement('form', { |
---|
166 | method: 'post', |
---|
167 | action: url, |
---|
168 | enctype: 'multipart/form-data' |
---|
169 | }, { |
---|
170 | display: NONE |
---|
171 | }, doc.body); |
---|
172 | |
---|
173 | // add the data |
---|
174 | for (name in data) { |
---|
175 | createElement('input', { |
---|
176 | type: HIDDEN, |
---|
177 | name: name, |
---|
178 | value: data[name] |
---|
179 | }, null, form); |
---|
180 | } |
---|
181 | |
---|
182 | // submit |
---|
183 | form.submit(); |
---|
184 | |
---|
185 | // clean up |
---|
186 | discardElement(form); |
---|
187 | }; |
---|
188 | |
---|
189 | extend(Chart.prototype, { |
---|
190 | |
---|
191 | /** |
---|
192 | * Return an SVG representation of the chart |
---|
193 | * |
---|
194 | * @param additionalOptions {Object} Additional chart options for the generated SVG representation |
---|
195 | */ |
---|
196 | getSVG: function (additionalOptions) { |
---|
197 | var chart = this, |
---|
198 | chartCopy, |
---|
199 | sandbox, |
---|
200 | svg, |
---|
201 | seriesOptions, |
---|
202 | sourceWidth, |
---|
203 | sourceHeight, |
---|
204 | cssWidth, |
---|
205 | cssHeight, |
---|
206 | options = merge(chart.options, additionalOptions); // copy the options and add extra options |
---|
207 | |
---|
208 | // IE compatibility hack for generating SVG content that it doesn't really understand |
---|
209 | if (!doc.createElementNS) { |
---|
210 | /*jslint unparam: true*//* allow unused parameter ns in function below */ |
---|
211 | doc.createElementNS = function (ns, tagName) { |
---|
212 | return doc.createElement(tagName); |
---|
213 | }; |
---|
214 | /*jslint unparam: false*/ |
---|
215 | } |
---|
216 | |
---|
217 | // create a sandbox where a new chart will be generated |
---|
218 | sandbox = createElement(DIV, null, { |
---|
219 | position: ABSOLUTE, |
---|
220 | top: '-9999em', |
---|
221 | width: chart.chartWidth + PX, |
---|
222 | height: chart.chartHeight + PX |
---|
223 | }, doc.body); |
---|
224 | |
---|
225 | // get the source size |
---|
226 | cssWidth = chart.renderTo.style.width; |
---|
227 | cssHeight = chart.renderTo.style.height; |
---|
228 | sourceWidth = options.exporting.sourceWidth || |
---|
229 | options.chart.width || |
---|
230 | (/px$/.test(cssWidth) && parseInt(cssWidth, 10)) || |
---|
231 | 600; |
---|
232 | sourceHeight = options.exporting.sourceHeight || |
---|
233 | options.chart.height || |
---|
234 | (/px$/.test(cssHeight) && parseInt(cssHeight, 10)) || |
---|
235 | 400; |
---|
236 | |
---|
237 | // override some options |
---|
238 | extend(options.chart, { |
---|
239 | animation: false, |
---|
240 | renderTo: sandbox, |
---|
241 | forExport: true, |
---|
242 | width: sourceWidth, |
---|
243 | height: sourceHeight |
---|
244 | }); |
---|
245 | options.exporting.enabled = false; // hide buttons in print |
---|
246 | |
---|
247 | // prepare for replicating the chart |
---|
248 | options.series = []; |
---|
249 | each(chart.series, function (serie) { |
---|
250 | seriesOptions = merge(serie.options, { |
---|
251 | animation: false, // turn off animation |
---|
252 | showCheckbox: false, |
---|
253 | visible: serie.visible |
---|
254 | }); |
---|
255 | |
---|
256 | if (!seriesOptions.isInternal) { // used for the navigator series that has its own option set |
---|
257 | options.series.push(seriesOptions); |
---|
258 | } |
---|
259 | }); |
---|
260 | |
---|
261 | // generate the chart copy |
---|
262 | chartCopy = new Highcharts.Chart(options, chart.callback); |
---|
263 | |
---|
264 | // reflect axis extremes in the export |
---|
265 | each(['xAxis', 'yAxis'], function (axisType) { |
---|
266 | each(chart[axisType], function (axis, i) { |
---|
267 | var axisCopy = chartCopy[axisType][i], |
---|
268 | extremes = axis.getExtremes(), |
---|
269 | userMin = extremes.userMin, |
---|
270 | userMax = extremes.userMax; |
---|
271 | |
---|
272 | if (axisCopy && (userMin !== UNDEFINED || userMax !== UNDEFINED)) { |
---|
273 | axisCopy.setExtremes(userMin, userMax, true, false); |
---|
274 | } |
---|
275 | }); |
---|
276 | }); |
---|
277 | |
---|
278 | // get the SVG from the container's innerHTML |
---|
279 | svg = chartCopy.container.innerHTML; |
---|
280 | |
---|
281 | // free up memory |
---|
282 | options = null; |
---|
283 | chartCopy.destroy(); |
---|
284 | discardElement(sandbox); |
---|
285 | |
---|
286 | // sanitize |
---|
287 | svg = svg |
---|
288 | .replace(/zIndex="[^"]+"/g, '') |
---|
289 | .replace(/isShadow="[^"]+"/g, '') |
---|
290 | .replace(/symbolName="[^"]+"/g, '') |
---|
291 | .replace(/jQuery[0-9]+="[^"]+"/g, '') |
---|
292 | .replace(/url\([^#]+#/g, 'url(#') |
---|
293 | .replace(/<svg /, '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ') |
---|
294 | .replace(/ href=/g, ' xlink:href=') |
---|
295 | .replace(/\n/, ' ') |
---|
296 | .replace(/<\/svg>.*?$/, '</svg>') // any HTML added to the container after the SVG (#894) |
---|
297 | /* This fails in IE < 8 |
---|
298 | .replace(/([0-9]+)\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight |
---|
299 | return s2 +'.'+ s3[0]; |
---|
300 | })*/ |
---|
301 | |
---|
302 | // Replace HTML entities, issue #347 |
---|
303 | .replace(/ /g, '\u00A0') // no-break space |
---|
304 | .replace(/­/g, '\u00AD') // soft hyphen |
---|
305 | |
---|
306 | // IE specific |
---|
307 | .replace(/<IMG /g, '<image ') |
---|
308 | .replace(/height=([^" ]+)/g, 'height="$1"') |
---|
309 | .replace(/width=([^" ]+)/g, 'width="$1"') |
---|
310 | .replace(/hc-svg-href="([^"]+)">/g, 'xlink:href="$1"/>') |
---|
311 | .replace(/id=([^" >]+)/g, 'id="$1"') |
---|
312 | .replace(/class=([^" >]+)/g, 'class="$1"') |
---|
313 | .replace(/ transform /g, ' ') |
---|
314 | .replace(/:(path|rect)/g, '$1') |
---|
315 | .replace(/style="([^"]+)"/g, function (s) { |
---|
316 | return s.toLowerCase(); |
---|
317 | }); |
---|
318 | |
---|
319 | // IE9 beta bugs with innerHTML. Test again with final IE9. |
---|
320 | svg = svg.replace(/(url\(#highcharts-[0-9]+)"/g, '$1') |
---|
321 | .replace(/"/g, "'"); |
---|
322 | |
---|
323 | return svg; |
---|
324 | }, |
---|
325 | |
---|
326 | /** |
---|
327 | * Submit the SVG representation of the chart to the server |
---|
328 | * @param {Object} options Exporting options. Possible members are url, type and width. |
---|
329 | * @param {Object} chartOptions Additional chart options for the SVG representation of the chart |
---|
330 | */ |
---|
331 | exportChart: function (options, chartOptions) { |
---|
332 | options = options || {}; |
---|
333 | |
---|
334 | var chart = this, |
---|
335 | chartExportingOptions = chart.options.exporting, |
---|
336 | svg = chart.getSVG(merge( |
---|
337 | { chart: { borderRadius: 0 } }, |
---|
338 | chartExportingOptions.chartOptions, |
---|
339 | chartOptions, |
---|
340 | { |
---|
341 | exporting: { |
---|
342 | sourceWidth: options.sourceWidth || chartExportingOptions.sourceWidth, |
---|
343 | sourceHeight: options.sourceHeight || chartExportingOptions.sourceHeight |
---|
344 | } |
---|
345 | } |
---|
346 | )); |
---|
347 | |
---|
348 | // merge the options |
---|
349 | options = merge(chart.options.exporting, options); |
---|
350 | |
---|
351 | // do the post |
---|
352 | Highcharts.post(options.url, { |
---|
353 | filename: options.filename || 'chart', |
---|
354 | type: options.type, |
---|
355 | width: options.width || 0, // IE8 fails to post undefined correctly, so use 0 |
---|
356 | scale: options.scale || 2, |
---|
357 | svg: svg |
---|
358 | }); |
---|
359 | |
---|
360 | }, |
---|
361 | |
---|
362 | /** |
---|
363 | * Print the chart |
---|
364 | */ |
---|
365 | print: function () { |
---|
366 | |
---|
367 | var chart = this, |
---|
368 | container = chart.container, |
---|
369 | origDisplay = [], |
---|
370 | origParent = container.parentNode, |
---|
371 | body = doc.body, |
---|
372 | childNodes = body.childNodes; |
---|
373 | |
---|
374 | if (chart.isPrinting) { // block the button while in printing mode |
---|
375 | return; |
---|
376 | } |
---|
377 | |
---|
378 | chart.isPrinting = true; |
---|
379 | |
---|
380 | // hide all body content |
---|
381 | each(childNodes, function (node, i) { |
---|
382 | if (node.nodeType === 1) { |
---|
383 | origDisplay[i] = node.style.display; |
---|
384 | node.style.display = NONE; |
---|
385 | } |
---|
386 | }); |
---|
387 | |
---|
388 | // pull out the chart |
---|
389 | body.appendChild(container); |
---|
390 | |
---|
391 | // print |
---|
392 | win.focus(); // #1510 |
---|
393 | win.print(); |
---|
394 | |
---|
395 | // allow the browser to prepare before reverting |
---|
396 | setTimeout(function () { |
---|
397 | |
---|
398 | // put the chart back in |
---|
399 | origParent.appendChild(container); |
---|
400 | |
---|
401 | // restore all body content |
---|
402 | each(childNodes, function (node, i) { |
---|
403 | if (node.nodeType === 1) { |
---|
404 | node.style.display = origDisplay[i]; |
---|
405 | } |
---|
406 | }); |
---|
407 | |
---|
408 | chart.isPrinting = false; |
---|
409 | |
---|
410 | }, 1000); |
---|
411 | |
---|
412 | }, |
---|
413 | |
---|
414 | /** |
---|
415 | * Display a popup menu for choosing the export type |
---|
416 | * |
---|
417 | * @param {String} name An identifier for the menu |
---|
418 | * @param {Array} items A collection with text and onclicks for the items |
---|
419 | * @param {Number} x The x position of the opener button |
---|
420 | * @param {Number} y The y position of the opener button |
---|
421 | * @param {Number} width The width of the opener button |
---|
422 | * @param {Number} height The height of the opener button |
---|
423 | */ |
---|
424 | contextMenu: function (name, items, x, y, width, height, button) { |
---|
425 | var chart = this, |
---|
426 | navOptions = chart.options.navigation, |
---|
427 | menuItemStyle = navOptions.menuItemStyle, |
---|
428 | chartWidth = chart.chartWidth, |
---|
429 | chartHeight = chart.chartHeight, |
---|
430 | cacheName = 'cache-' + name, |
---|
431 | menu = chart[cacheName], |
---|
432 | menuPadding = mathMax(width, height), // for mouse leave detection |
---|
433 | boxShadow = '3px 3px 10px #888', |
---|
434 | innerMenu, |
---|
435 | hide, |
---|
436 | hideTimer, |
---|
437 | menuStyle; |
---|
438 | |
---|
439 | // create the menu only the first time |
---|
440 | if (!menu) { |
---|
441 | |
---|
442 | // create a HTML element above the SVG |
---|
443 | chart[cacheName] = menu = createElement(DIV, { |
---|
444 | className: PREFIX + name |
---|
445 | }, { |
---|
446 | position: ABSOLUTE, |
---|
447 | zIndex: 1000, |
---|
448 | padding: menuPadding + PX |
---|
449 | }, chart.container); |
---|
450 | |
---|
451 | innerMenu = createElement(DIV, null, |
---|
452 | extend({ |
---|
453 | MozBoxShadow: boxShadow, |
---|
454 | WebkitBoxShadow: boxShadow, |
---|
455 | boxShadow: boxShadow |
---|
456 | }, navOptions.menuStyle), menu); |
---|
457 | |
---|
458 | // hide on mouse out |
---|
459 | hide = function () { |
---|
460 | css(menu, { display: NONE }); |
---|
461 | if (button) { |
---|
462 | button.setState(0); |
---|
463 | } |
---|
464 | chart.openMenu = false; |
---|
465 | }; |
---|
466 | |
---|
467 | // Hide the menu some time after mouse leave (#1357) |
---|
468 | addEvent(menu, 'mouseleave', function () { |
---|
469 | hideTimer = setTimeout(hide, 500); |
---|
470 | }); |
---|
471 | addEvent(menu, 'mouseenter', function () { |
---|
472 | clearTimeout(hideTimer); |
---|
473 | }); |
---|
474 | |
---|
475 | |
---|
476 | // create the items |
---|
477 | each(items, function (item) { |
---|
478 | if (item) { |
---|
479 | var element = item.separator ? |
---|
480 | createElement('hr', null, null, innerMenu) : |
---|
481 | createElement(DIV, { |
---|
482 | onmouseover: function () { |
---|
483 | css(this, navOptions.menuItemHoverStyle); |
---|
484 | }, |
---|
485 | onmouseout: function () { |
---|
486 | css(this, menuItemStyle); |
---|
487 | }, |
---|
488 | onclick: function () { |
---|
489 | hide(); |
---|
490 | item.onclick.apply(chart, arguments); |
---|
491 | }, |
---|
492 | innerHTML: item.text || chart.options.lang[item.textKey] |
---|
493 | }, extend({ |
---|
494 | cursor: 'pointer' |
---|
495 | }, menuItemStyle), innerMenu); |
---|
496 | |
---|
497 | |
---|
498 | // Keep references to menu divs to be able to destroy them |
---|
499 | chart.exportDivElements.push(element); |
---|
500 | } |
---|
501 | }); |
---|
502 | |
---|
503 | // Keep references to menu and innerMenu div to be able to destroy them |
---|
504 | chart.exportDivElements.push(innerMenu, menu); |
---|
505 | |
---|
506 | chart.exportMenuWidth = menu.offsetWidth; |
---|
507 | chart.exportMenuHeight = menu.offsetHeight; |
---|
508 | } |
---|
509 | |
---|
510 | menuStyle = { display: 'block' }; |
---|
511 | |
---|
512 | // if outside right, right align it |
---|
513 | if (x + chart.exportMenuWidth > chartWidth) { |
---|
514 | menuStyle.right = (chartWidth - x - width - menuPadding) + PX; |
---|
515 | } else { |
---|
516 | menuStyle.left = (x - menuPadding) + PX; |
---|
517 | } |
---|
518 | // if outside bottom, bottom align it |
---|
519 | if (y + height + chart.exportMenuHeight > chartHeight && button.alignOptions.verticalAlign !== 'top') { |
---|
520 | menuStyle.bottom = (chartHeight - y - menuPadding) + PX; |
---|
521 | } else { |
---|
522 | menuStyle.top = (y + height - menuPadding) + PX; |
---|
523 | } |
---|
524 | |
---|
525 | css(menu, menuStyle); |
---|
526 | chart.openMenu = true; |
---|
527 | }, |
---|
528 | |
---|
529 | /** |
---|
530 | * Add the export button to the chart |
---|
531 | */ |
---|
532 | addButton: function (options) { |
---|
533 | var chart = this, |
---|
534 | renderer = chart.renderer, |
---|
535 | btnOptions = merge(chart.options.navigation.buttonOptions, options), |
---|
536 | onclick = btnOptions.onclick, |
---|
537 | menuItems = btnOptions.menuItems, |
---|
538 | symbol, |
---|
539 | button, |
---|
540 | symbolAttr = { |
---|
541 | stroke: btnOptions.symbolStroke, |
---|
542 | fill: btnOptions.symbolFill |
---|
543 | }, |
---|
544 | symbolSize = btnOptions.symbolSize || 12, |
---|
545 | menuKey; |
---|
546 | |
---|
547 | if (!chart.btnCount) { |
---|
548 | chart.btnCount = 0; |
---|
549 | } |
---|
550 | menuKey = chart.btnCount++; |
---|
551 | |
---|
552 | // Keeps references to the button elements |
---|
553 | if (!chart.exportDivElements) { |
---|
554 | chart.exportDivElements = []; |
---|
555 | chart.exportSVGElements = []; |
---|
556 | } |
---|
557 | |
---|
558 | if (btnOptions.enabled === false) { |
---|
559 | return; |
---|
560 | } |
---|
561 | |
---|
562 | |
---|
563 | var attr = btnOptions.theme, |
---|
564 | states = attr.states, |
---|
565 | hover = states && states.hover, |
---|
566 | select = states && states.select, |
---|
567 | callback; |
---|
568 | |
---|
569 | delete attr.states; |
---|
570 | |
---|
571 | if (onclick) { |
---|
572 | callback = function () { |
---|
573 | onclick.apply(chart, arguments); |
---|
574 | }; |
---|
575 | |
---|
576 | } else if (menuItems) { |
---|
577 | callback = function () { |
---|
578 | chart.contextMenu( |
---|
579 | 'contextmenu', |
---|
580 | menuItems, |
---|
581 | button.translateX, |
---|
582 | button.translateY, |
---|
583 | button.width, |
---|
584 | button.height, |
---|
585 | button |
---|
586 | ); |
---|
587 | button.setState(2); |
---|
588 | }; |
---|
589 | } |
---|
590 | |
---|
591 | |
---|
592 | if (btnOptions.text && btnOptions.symbol) { |
---|
593 | attr.paddingLeft = Highcharts.pick(attr.paddingLeft, 25); |
---|
594 | |
---|
595 | } else if (!btnOptions.text) { |
---|
596 | extend(attr, { |
---|
597 | width: btnOptions.width, |
---|
598 | height: btnOptions.height, |
---|
599 | padding: 0 |
---|
600 | }); |
---|
601 | } |
---|
602 | |
---|
603 | button = renderer.button(btnOptions.text, 0, 0, callback, attr, hover, select) |
---|
604 | .attr({ |
---|
605 | title: chart.options.lang[btnOptions._titleKey], |
---|
606 | 'stroke-linecap': 'round' |
---|
607 | }); |
---|
608 | |
---|
609 | if (btnOptions.symbol) { |
---|
610 | symbol = renderer.symbol( |
---|
611 | btnOptions.symbol, |
---|
612 | btnOptions.symbolX - (symbolSize / 2), |
---|
613 | btnOptions.symbolY - (symbolSize / 2), |
---|
614 | symbolSize, |
---|
615 | symbolSize |
---|
616 | ) |
---|
617 | .attr(extend(symbolAttr, { |
---|
618 | 'stroke-width': btnOptions.symbolStrokeWidth || 1, |
---|
619 | zIndex: 1 |
---|
620 | })).add(button); |
---|
621 | } |
---|
622 | |
---|
623 | button.add() |
---|
624 | .align(extend(btnOptions, { |
---|
625 | width: button.width, |
---|
626 | x: Highcharts.pick(btnOptions.x, buttonOffset) // #1654 |
---|
627 | }), true, 'spacingBox'); |
---|
628 | |
---|
629 | buttonOffset += (button.width + btnOptions.buttonSpacing) * (btnOptions.align === 'right' ? -1 : 1); |
---|
630 | |
---|
631 | chart.exportSVGElements.push(button, symbol); |
---|
632 | |
---|
633 | }, |
---|
634 | |
---|
635 | /** |
---|
636 | * Destroy the buttons. |
---|
637 | */ |
---|
638 | destroyExport: function (e) { |
---|
639 | var chart = e.target, |
---|
640 | i, |
---|
641 | elem; |
---|
642 | |
---|
643 | // Destroy the extra buttons added |
---|
644 | for (i = 0; i < chart.exportSVGElements.length; i++) { |
---|
645 | elem = chart.exportSVGElements[i]; |
---|
646 | |
---|
647 | // Destroy and null the svg/vml elements |
---|
648 | if (elem) { // #1822 |
---|
649 | elem.onclick = elem.ontouchstart = null; |
---|
650 | chart.exportSVGElements[i] = elem.destroy(); |
---|
651 | } |
---|
652 | } |
---|
653 | |
---|
654 | // Destroy the divs for the menu |
---|
655 | for (i = 0; i < chart.exportDivElements.length; i++) { |
---|
656 | elem = chart.exportDivElements[i]; |
---|
657 | |
---|
658 | // Remove the event handler |
---|
659 | removeEvent(elem, 'mouseleave'); |
---|
660 | |
---|
661 | // Remove inline events |
---|
662 | chart.exportDivElements[i] = elem.onmouseout = elem.onmouseover = elem.ontouchstart = elem.onclick = null; |
---|
663 | |
---|
664 | // Destroy the div by moving to garbage bin |
---|
665 | discardElement(elem); |
---|
666 | } |
---|
667 | } |
---|
668 | }); |
---|
669 | |
---|
670 | |
---|
671 | symbols.menu = function (x, y, width, height) { |
---|
672 | var arr = [ |
---|
673 | M, x, y + 2.5, |
---|
674 | L, x + width, y + 2.5, |
---|
675 | M, x, y + height / 2 + 0.5, |
---|
676 | L, x + width, y + height / 2 + 0.5, |
---|
677 | M, x, y + height - 1.5, |
---|
678 | L, x + width, y + height - 1.5 |
---|
679 | ]; |
---|
680 | return arr; |
---|
681 | }; |
---|
682 | |
---|
683 | // Add the buttons on chart load |
---|
684 | Chart.prototype.callbacks.push(function (chart) { |
---|
685 | var n, |
---|
686 | exportingOptions = chart.options.exporting, |
---|
687 | buttons = exportingOptions.buttons; |
---|
688 | |
---|
689 | buttonOffset = 0; |
---|
690 | |
---|
691 | if (exportingOptions.enabled !== false) { |
---|
692 | |
---|
693 | for (n in buttons) { |
---|
694 | chart.addButton(buttons[n]); |
---|
695 | } |
---|
696 | |
---|
697 | // Destroy the export elements at chart destroy |
---|
698 | addEvent(chart, 'destroy', chart.destroyExport); |
---|
699 | } |
---|
700 | |
---|
701 | }); |
---|
702 | |
---|
703 | |
---|
704 | }(Highcharts)); |
---|