+++ /dev/null
-/** \r
- * @license Highcharts JS v2.1.6 (2011-07-08)\r
- * Exporting module\r
- * \r
- * (c) 2010-2011 Torstein Hønsi\r
- * \r
- * License: www.highcharts.com/license\r
- */\r
-\r
-// JSLint options:\r
-/*global Highcharts, document, window, Math, setTimeout */\r
-\r
-(function() { // encapsulate\r
-\r
-// create shortcuts\r
-var HC = Highcharts,\r
- Chart = HC.Chart,\r
- addEvent = HC.addEvent,\r
- createElement = HC.createElement,\r
- discardElement = HC.discardElement,\r
- css = HC.css,\r
- merge = HC.merge,\r
- each = HC.each,\r
- extend = HC.extend,\r
- math = Math,\r
- mathMax = math.max,\r
- doc = document,\r
- win = window,\r
- hasTouch = 'ontouchstart' in doc.documentElement, \r
- M = 'M',\r
- L = 'L',\r
- DIV = 'div',\r
- HIDDEN = 'hidden',\r
- NONE = 'none',\r
- PREFIX = 'highcharts-',\r
- ABSOLUTE = 'absolute',\r
- PX = 'px',\r
- UNDEFINED = undefined,\r
-\r
- // Add language and get the defaultOptions\r
- defaultOptions = HC.setOptions({\r
- lang: {\r
- downloadPNG: 'Download PNG image',\r
- downloadJPEG: 'Download JPEG image',\r
- downloadPDF: 'Download PDF document',\r
- downloadSVG: 'Download SVG vector image',\r
- exportButtonTitle: 'Export to raster or vector image',\r
- printButtonTitle: 'Print the chart'\r
- }\r
- });\r
-\r
-// Buttons and menus are collected in a separate config option set called 'navigation'.\r
-// This can be extended later to add control buttons like zoom and pan right click menus.\r
-defaultOptions.navigation = {\r
- menuStyle: {\r
- border: '1px solid #A0A0A0',\r
- background: '#FFFFFF'\r
- },\r
- menuItemStyle: {\r
- padding: '0 5px',\r
- background: NONE,\r
- color: '#303030',\r
- fontSize: hasTouch ? '14px' : '11px'\r
- },\r
- menuItemHoverStyle: {\r
- background: '#4572A5',\r
- color: '#FFFFFF'\r
- },\r
- \r
- buttonOptions: {\r
- align: 'right',\r
- backgroundColor: {\r
- linearGradient: [0, 0, 0, 20],\r
- stops: [\r
- [0.4, '#F7F7F7'],\r
- [0.6, '#E3E3E3']\r
- ]\r
- },\r
- borderColor: '#B0B0B0',\r
- borderRadius: 3,\r
- borderWidth: 1,\r
- //enabled: true,\r
- height: 20,\r
- hoverBorderColor: '#909090',\r
- hoverSymbolFill: '#81A7CF',\r
- hoverSymbolStroke: '#4572A5',\r
- symbolFill: '#E0E0E0',\r
- //symbolSize: 12,\r
- symbolStroke: '#A0A0A0',\r
- //symbolStrokeWidth: 1,\r
- symbolX: 11.5,\r
- symbolY: 10.5,\r
- verticalAlign: 'top',\r
- width: 24,\r
- y: 10 \r
- }\r
-};\r
-\r
-\r
-\r
-// Add the export related options\r
-defaultOptions.exporting = {\r
- //enabled: true,\r
- //filename: 'chart',\r
- type: 'image/png',\r
- url: 'http://export.highcharts.com/',\r
- width: 800,\r
- enableImages: false,\r
- buttons: {\r
- exportButton: {\r
- //enabled: true,\r
- symbol: 'exportIcon',\r
- x: -10,\r
- symbolFill: '#A8BF77',\r
- hoverSymbolFill: '#768F3E',\r
- _titleKey: 'exportButtonTitle',\r
- menuItems: [{\r
- textKey: 'downloadPNG',\r
- onclick: function() {\r
- this.exportChart();\r
- }\r
- }, {\r
- textKey: 'downloadJPEG',\r
- onclick: function() {\r
- this.exportChart({\r
- type: 'image/jpeg'\r
- });\r
- }\r
- }, {\r
- textKey: 'downloadPDF',\r
- onclick: function() {\r
- this.exportChart({\r
- type: 'application/pdf'\r
- });\r
- }\r
- }, {\r
- textKey: 'downloadSVG',\r
- onclick: function() {\r
- this.exportChart({\r
- type: 'image/svg+xml'\r
- });\r
- }\r
- }/*, {\r
- text: 'View SVG',\r
- onclick: function() {\r
- var svg = this.getSVG()\r
- .replace(/</g, '\n<')\r
- .replace(/>/g, '>');\r
- \r
- doc.body.innerHTML = '<pre>'+ svg +'</pre>';\r
- }\r
- }*/]\r
- \r
- },\r
- printButton: {\r
- //enabled: true,\r
- symbol: 'printIcon',\r
- x: -36,\r
- symbolFill: '#B5C9DF',\r
- hoverSymbolFill: '#779ABF',\r
- _titleKey: 'printButtonTitle',\r
- onclick: function() {\r
- this.print();\r
- }\r
- }\r
- }\r
-};\r
-\r
-\r
-\r
-extend(Chart.prototype, {\r
- /**\r
- * Return an SVG representation of the chart\r
- * \r
- * @param additionalOptions {Object} Additional chart options for the generated SVG representation\r
- */ \r
- getSVG: function(additionalOptions) {\r
- var chart = this,\r
- chartCopy,\r
- sandbox,\r
- svg,\r
- seriesOptions,\r
- config,\r
- pointOptions,\r
- pointMarker,\r
- options = merge(chart.options, additionalOptions); // copy the options and add extra options\r
- \r
- // IE compatibility hack for generating SVG content that it doesn't really understand\r
- if (!doc.createElementNS) {\r
- doc.createElementNS = function(ns, tagName) {\r
- var elem = doc.createElement(tagName);\r
- elem.getBBox = function() {\r
- return HC.Renderer.prototype.Element.prototype.getBBox.apply({ element: elem });\r
- };\r
- return elem;\r
- };\r
- }\r
- \r
- // create a sandbox where a new chart will be generated\r
- sandbox = createElement(DIV, null, {\r
- position: ABSOLUTE,\r
- top: '-9999em',\r
- width: chart.chartWidth + PX,\r
- height: chart.chartHeight + PX\r
- }, doc.body);\r
- \r
- // override some options\r
- extend(options.chart, {\r
- renderTo: sandbox,\r
- forExport: true\r
- });\r
- options.exporting.enabled = false; // hide buttons in print\r
-\r
- if (!options.exporting.enableImages) {\r
- options.chart.plotBackgroundImage = null; // the converter doesn't handle images\r
- }\r
- \r
- // prepare for replicating the chart\r
- options.series = [];\r
- each(chart.series, function(serie) {\r
- seriesOptions = serie.options; \r
- \r
- seriesOptions.animation = false; // turn off animation\r
- seriesOptions.showCheckbox = false;\r
- seriesOptions.visible = serie.visible;\r
- \r
- if (!options.exporting.enableImages) {\r
- // remove image markers\r
- if (seriesOptions && seriesOptions.marker && /^url\(/.test(seriesOptions.marker.symbol)) { \r
- seriesOptions.marker.symbol = 'circle';\r
- }\r
- }\r
- \r
- seriesOptions.data = [];\r
- \r
- each(serie.data, function(point) {\r
- \r
- // extend the options by those values that can be expressed in a number or array config\r
- config = point.config;\r
- pointOptions = {\r
- x: point.x,\r
- y: point.y,\r
- name: point.name\r
- };\r
-\r
- if (typeof config == 'object' && point.config && config.constructor != Array) {\r
- extend(pointOptions, config);\r
- }\r
-\r
- pointOptions.visible = point.visible;\r
- seriesOptions.data.push(pointOptions); // copy fresh updated data\r
- \r
- if (!options.exporting.enableImages) {\r
- // remove image markers\r
- pointMarker = point.config && point.config.marker;\r
- if (pointMarker && /^url\(/.test(pointMarker.symbol)) { \r
- delete pointMarker.symbol;\r
- }\r
- }\r
- }); \r
- \r
- options.series.push(seriesOptions);\r
- });\r
- \r
- // generate the chart copy\r
- chartCopy = new Highcharts.Chart(options); \r
- \r
- // reflect axis extremes in the export\r
- each(['xAxis', 'yAxis'], function(axisType) {\r
- each (chart[axisType], function(axis, i) {\r
- var axisCopy = chartCopy[axisType][i],\r
- extremes = axis.getExtremes(),\r
- userMin = extremes.userMin,\r
- userMax = extremes.userMax;\r
- \r
- if (userMin !== UNDEFINED || userMax !== UNDEFINED) {\r
- axisCopy.setExtremes(userMin, userMax, true, false);\r
- }\r
- });\r
- });\r
- \r
- // get the SVG from the container's innerHTML\r
- svg = chartCopy.container.innerHTML;\r
- \r
- // free up memory\r
- options = null;\r
- chartCopy.destroy();\r
- discardElement(sandbox);\r
- \r
- // sanitize\r
- svg = svg\r
- .replace(/zIndex="[^"]+"/g, '') \r
- .replace(/isShadow="[^"]+"/g, '')\r
- .replace(/symbolName="[^"]+"/g, '')\r
- .replace(/jQuery[0-9]+="[^"]+"/g, '')\r
- .replace(/isTracker="[^"]+"/g, '')\r
- .replace(/url\([^#]+#/g, 'url(#')\r
- .replace(/<svg /, '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ')\r
- .replace(/ href=/g, ' xlink:href=')\r
- /*.replace(/preserveAspectRatio="none">/g, 'preserveAspectRatio="none"/>')*/\r
- /* This fails in IE < 8\r
- .replace(/([0-9]+)\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight\r
- return s2 +'.'+ s3[0];\r
- })*/ \r
- \r
- // IE specific\r
- .replace(/id=([^" >]+)/g, 'id="$1"') \r
- .replace(/class=([^" ]+)/g, 'class="$1"')\r
- .replace(/ transform /g, ' ')\r
- .replace(/:(path|rect)/g, '$1')\r
- .replace(/<img ([^>]*)>/gi, '<image $1 />')\r
- .replace(/<\/image>/g, '') // remove closing tags for images as they'll never have any content\r
- .replace(/<image ([^>]*)([^\/])>/gi, '<image $1$2 />') // closes image tags for firefox\r
- .replace(/width=(\d+)/g, 'width="$1"')\r
- .replace(/height=(\d+)/g, 'height="$1"')\r
- .replace(/hc-svg-href="/g, 'xlink:href="')\r
- .replace(/style="([^"]+)"/g, function(s) {\r
- return s.toLowerCase();\r
- });\r
- \r
- // IE9 beta bugs with innerHTML. Test again with final IE9.\r
- svg = svg.replace(/(url\(#highcharts-[0-9]+)"/g, '$1')\r
- .replace(/"/g, "'");\r
- if (svg.match(/ xmlns="/g).length == 2) {\r
- svg = svg.replace(/xmlns="[^"]+"/, '');\r
- }\r
- \r
- return svg;\r
- },\r
- \r
- /**\r
- * Submit the SVG representation of the chart to the server\r
- * @param {Object} options Exporting options. Possible members are url, type and width.\r
- * @param {Object} chartOptions Additional chart options for the SVG representation of the chart\r
- */\r
- exportChart: function(options, chartOptions) {\r
- var form,\r
- chart = this,\r
- svg = chart.getSVG(chartOptions);\r
- \r
- // merge the options\r
- options = merge(chart.options.exporting, options);\r
- \r
- // create the form\r
- form = createElement('form', {\r
- method: 'post',\r
- action: options.url\r
- }, {\r
- display: NONE\r
- }, doc.body);\r
- \r
- // add the values\r
- each(['filename', 'type', 'width', 'svg'], function(name) {\r
- createElement('input', {\r
- type: HIDDEN,\r
- name: name,\r
- value: { \r
- filename: options.filename || 'chart', \r
- type: options.type, \r
- width: options.width, \r
- svg: svg \r
- }[name]\r
- }, null, form);\r
- });\r
- \r
- // submit\r
- form.submit();\r
- \r
- // clean up\r
- discardElement(form);\r
- },\r
- \r
- /**\r
- * Print the chart\r
- */\r
- print: function() {\r
- \r
- var chart = this,\r
- container = chart.container,\r
- origDisplay = [],\r
- origParent = container.parentNode,\r
- body = doc.body,\r
- childNodes = body.childNodes;\r
- \r
- if (chart.isPrinting) { // block the button while in printing mode\r
- return;\r
- }\r
- \r
- chart.isPrinting = true;\r
- \r
- // hide all body content \r
- each(childNodes, function(node, i) {\r
- if (node.nodeType == 1) {\r
- origDisplay[i] = node.style.display;\r
- node.style.display = NONE;\r
- }\r
- });\r
- \r
- // pull out the chart\r
- body.appendChild(container);\r
- \r
- // print\r
- win.print(); \r
- \r
- // allow the browser to prepare before reverting\r
- setTimeout(function() {\r
-\r
- // put the chart back in\r
- origParent.appendChild(container);\r
- \r
- // restore all body content\r
- each(childNodes, function(node, i) {\r
- if (node.nodeType == 1) {\r
- node.style.display = origDisplay[i];\r
- }\r
- });\r
- \r
- chart.isPrinting = false;\r
- \r
- }, 1000);\r
-\r
- },\r
- \r
- /**\r
- * Display a popup menu for choosing the export type \r
- * \r
- * @param {String} name An identifier for the menu\r
- * @param {Array} items A collection with text and onclicks for the items\r
- * @param {Number} x The x position of the opener button\r
- * @param {Number} y The y position of the opener button\r
- * @param {Number} width The width of the opener button\r
- * @param {Number} height The height of the opener button\r
- */\r
- contextMenu: function(name, items, x, y, width, height) {\r
- var chart = this,\r
- navOptions = chart.options.navigation,\r
- menuItemStyle = navOptions.menuItemStyle,\r
- chartWidth = chart.chartWidth,\r
- chartHeight = chart.chartHeight,\r
- cacheName = 'cache-'+ name,\r
- menu = chart[cacheName],\r
- menuPadding = mathMax(width, height), // for mouse leave detection\r
- boxShadow = '3px 3px 10px #888',\r
- innerMenu,\r
- hide,\r
- menuStyle; \r
- \r
- // create the menu only the first time\r
- if (!menu) {\r
- \r
- // create a HTML element above the SVG \r
- chart[cacheName] = menu = createElement(DIV, {\r
- className: PREFIX + name\r
- }, {\r
- position: ABSOLUTE,\r
- zIndex: 1000,\r
- padding: menuPadding + PX\r
- }, chart.container);\r
- \r
- innerMenu = createElement(DIV, null, \r
- extend({\r
- MozBoxShadow: boxShadow,\r
- WebkitBoxShadow: boxShadow,\r
- boxShadow: boxShadow\r
- }, navOptions.menuStyle) , menu);\r
- \r
- // hide on mouse out\r
- hide = function() {\r
- css(menu, { display: NONE });\r
- };\r
- \r
- addEvent(menu, 'mouseleave', hide);\r
- \r
- \r
- // create the items\r
- each(items, function(item) {\r
- if (item) {\r
- var div = createElement(DIV, {\r
- onmouseover: function() {\r
- css(this, navOptions.menuItemHoverStyle);\r
- },\r
- onmouseout: function() {\r
- css(this, menuItemStyle);\r
- },\r
- innerHTML: item.text || HC.getOptions().lang[item.textKey]\r
- }, extend({\r
- cursor: 'pointer'\r
- }, menuItemStyle), innerMenu);\r
- \r
- div[hasTouch ? 'ontouchstart' : 'onclick'] = function() {\r
- hide();\r
- item.onclick.apply(chart, arguments);\r
- };\r
- \r
- }\r
- });\r
- \r
- chart.exportMenuWidth = menu.offsetWidth;\r
- chart.exportMenuHeight = menu.offsetHeight;\r
- }\r
- \r
- menuStyle = { display: 'block' };\r
- \r
- // if outside right, right align it\r
- if (x + chart.exportMenuWidth > chartWidth) {\r
- menuStyle.right = (chartWidth - x - width - menuPadding) + PX;\r
- } else {\r
- menuStyle.left = (x - menuPadding) + PX;\r
- }\r
- // if outside bottom, bottom align it\r
- if (y + height + chart.exportMenuHeight > chartHeight) {\r
- menuStyle.bottom = (chartHeight - y - menuPadding) + PX;\r
- } else {\r
- menuStyle.top = (y + height - menuPadding) + PX;\r
- }\r
- \r
- css(menu, menuStyle);\r
- },\r
- \r
- /**\r
- * Add the export button to the chart\r
- */\r
- addButton: function(options) {\r
- var chart = this,\r
- renderer = chart.renderer,\r
- btnOptions = merge(chart.options.navigation.buttonOptions, options),\r
- onclick = btnOptions.onclick,\r
- menuItems = btnOptions.menuItems,\r
- /*position = chart.getAlignment(btnOptions),\r
- buttonLeft = position.x,\r
- buttonTop = position.y,*/\r
- buttonWidth = btnOptions.width,\r
- buttonHeight = btnOptions.height,\r
- box,\r
- symbol,\r
- button, \r
- borderWidth = btnOptions.borderWidth,\r
- boxAttr = {\r
- stroke: btnOptions.borderColor\r
- \r
- },\r
- symbolAttr = {\r
- stroke: btnOptions.symbolStroke,\r
- fill: btnOptions.symbolFill\r
- };\r
- \r
- if (btnOptions.enabled === false) {\r
- return;\r
- }\r
- \r
- // element to capture the click\r
- function revert() {\r
- symbol.attr(symbolAttr);\r
- box.attr(boxAttr);\r
- }\r
- \r
- // the box border\r
- box = renderer.rect(\r
- 0,\r
- 0,\r
- buttonWidth, \r
- buttonHeight,\r
- btnOptions.borderRadius,\r
- borderWidth\r
- )\r
- //.translate(buttonLeft, buttonTop) // to allow gradients\r
- .align(btnOptions, true)\r
- .attr(extend({\r
- fill: btnOptions.backgroundColor,\r
- 'stroke-width': borderWidth,\r
- zIndex: 19\r
- }, boxAttr)).add();\r
- \r
- // the invisible element to track the clicks\r
- button = renderer.rect( \r
- 0,\r
- 0,\r
- buttonWidth,\r
- buttonHeight,\r
- 0\r
- )\r
- .align(btnOptions)\r
- .attr({\r
- fill: 'rgba(255, 255, 255, 0.001)',\r
- title: HC.getOptions().lang[btnOptions._titleKey],\r
- zIndex: 21\r
- }).css({\r
- cursor: 'pointer'\r
- })\r
- .on('mouseover', function() {\r
- symbol.attr({\r
- stroke: btnOptions.hoverSymbolStroke,\r
- fill: btnOptions.hoverSymbolFill\r
- });\r
- box.attr({\r
- stroke: btnOptions.hoverBorderColor\r
- });\r
- })\r
- .on('mouseout', revert)\r
- .on('click', revert)\r
- .add();\r
- \r
- //addEvent(button.element, 'click', revert);\r
- \r
- // add the click event\r
- if (menuItems) {\r
- onclick = function(e) {\r
- revert();\r
- var bBox = button.getBBox();\r
- chart.contextMenu('export-menu', menuItems, bBox.x, bBox.y, buttonWidth, buttonHeight);\r
- };\r
- }\r
- /*addEvent(button.element, 'click', function() {\r
- onclick.apply(chart, arguments);\r
- });*/\r
- button.on('click', function() {\r
- onclick.apply(chart, arguments);\r
- });\r
- \r
- // the icon\r
- symbol = renderer.symbol(\r
- btnOptions.symbol, \r
- btnOptions.symbolX, \r
- btnOptions.symbolY, \r
- (btnOptions.symbolSize || 12) / 2\r
- )\r
- .align(btnOptions, true)\r
- .attr(extend(symbolAttr, {\r
- 'stroke-width': btnOptions.symbolStrokeWidth || 1,\r
- zIndex: 20 \r
- })).add();\r
- \r
- \r
- \r
- }\r
-});\r
-\r
-// Create the export icon\r
-HC.Renderer.prototype.symbols.exportIcon = function(x, y, radius) {\r
- return [\r
- M, // the disk\r
- x - radius, y + radius,\r
- L,\r
- x + radius, y + radius,\r
- x + radius, y + radius * 0.5,\r
- x - radius, y + radius * 0.5,\r
- 'Z',\r
- M, // the arrow\r
- x, y + radius * 0.5,\r
- L,\r
- x - radius * 0.5, y - radius / 3,\r
- x - radius / 6, y - radius / 3,\r
- x - radius / 6, y - radius,\r
- x + radius / 6, y - radius,\r
- x + radius / 6, y - radius / 3,\r
- x + radius * 0.5, y - radius / 3,\r
- 'Z'\r
- ];\r
-};\r
-// Create the print icon\r
-HC.Renderer.prototype.symbols.printIcon = function(x, y, radius) {\r
- return [\r
- M, // the printer\r
- x - radius, y + radius * 0.5,\r
- L,\r
- x + radius, y + radius * 0.5,\r
- x + radius, y - radius / 3,\r
- x - radius, y - radius / 3,\r
- 'Z',\r
- M, // the upper sheet\r
- x - radius * 0.5, y - radius / 3,\r
- L,\r
- x - radius * 0.5, y - radius,\r
- x + radius * 0.5, y - radius,\r
- x + radius * 0.5, y - radius / 3,\r
- 'Z',\r
- M, // the lower sheet\r
- x - radius * 0.5, y + radius * 0.5,\r
- L,\r
- x - radius * 0.75, y + radius,\r
- x + radius * 0.75, y + radius,\r
- x + radius * 0.5, y + radius * 0.5,\r
- 'Z'\r
- ];\r
-};\r
-\r
-\r
-// Add the buttons on chart load\r
-Chart.prototype.callbacks.push(function(chart) {\r
- var n,\r
- exportingOptions = chart.options.exporting,\r
- buttons = exportingOptions.buttons;\r
-\r
- if (exportingOptions.enabled !== false) {\r
-\r
- for (n in buttons) {\r
- chart.addButton(buttons[n]);\r
- }\r
- }\r
-});\r
-\r
-\r
-})();
\ No newline at end of file