highstocks-rails 0.0.2 → 0.0.3

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