highcharts-rails 2.3.5 → 3.0.0

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,7 +1,8 @@
1
1
  /**
2
- * @license Data plugin for Highcharts v0.1
2
+ * @license Data plugin for Highcharts
3
3
  *
4
- * (c) 2012 Torstein Hønsi
4
+ * (c) 2012-2013 Torstein Hønsi
5
+ * Last revision 2012-11-27
5
6
  *
6
7
  * License: www.highcharts.com/license
7
8
  */
@@ -44,7 +45,7 @@
44
45
  * A Google Spreadsheet key. See https://developers.google.com/gdata/samples/spreadsheet_sample
45
46
  * for general information on GS.
46
47
  *
47
- * - googleSpreadsheetKey : String
48
+ * - googleSpreadsheetWorksheet : String
48
49
  * The Google Spreadsheet worksheet. The available id's can be read from
49
50
  * https://spreadsheets.google.com/feeds/worksheets/{key}/public/basic
50
51
  *
@@ -76,7 +77,9 @@
76
77
  * endRow, startColumn and endColumn to delimit what part of the table is used.
77
78
  */
78
79
 
80
+ // JSLint options:
79
81
  /*global jQuery */
82
+
80
83
  (function (Highcharts) {
81
84
 
82
85
  // Utilities
@@ -118,7 +121,6 @@
118
121
  },
119
122
 
120
123
  dataFound: function () {
121
-
122
124
  // Interpret the values into right types
123
125
  this.parseTypes();
124
126
 
@@ -213,13 +215,18 @@
213
215
  /**
214
216
  * TODO:
215
217
  * - switchRowsAndColumns
216
- * - startRow, endRow etc.
217
218
  */
218
219
  parseGoogleSpreadsheet: function () {
219
220
  var self = this,
220
221
  options = this.options,
221
222
  googleSpreadsheetKey = options.googleSpreadsheetKey,
222
- columns = this.columns;
223
+ columns = this.columns,
224
+ startRow = options.startRow || 0,
225
+ endRow = options.endRow || Number.MAX_VALUE,
226
+ startColumn = options.startColumn || 0,
227
+ endColumn = options.endColumn || Number.MAX_VALUE,
228
+ gr, // google row
229
+ gc; // google column
223
230
 
224
231
  if (googleSpreadsheetKey) {
225
232
  jQuery.getJSON('https://spreadsheets.google.com/feeds/cells/' +
@@ -245,15 +252,28 @@
245
252
 
246
253
  // Set up arrays containing the column data
247
254
  for (i = 0; i < colCount; i++) {
248
- columns[i] = new Array(rowCount);
255
+ if (i >= startColumn && i <= endColumn) {
256
+ // Create new columns with the length of either end-start or rowCount
257
+ columns[i - startColumn] = [];
258
+
259
+ // Setting the length to avoid jslint warning
260
+ columns[i - startColumn].length = Math.min(rowCount, endRow - startRow);
261
+ }
249
262
  }
250
263
 
251
264
  // Loop over the cells and assign the value to the right
252
265
  // place in the column arrays
253
266
  for (i = 0; i < cellCount; i++) {
254
267
  cell = cells[i];
255
- columns[cell.gs$cell.col - 1][cell.gs$cell.row - 1] =
256
- cell.content.$t;
268
+ gr = cell.gs$cell.row - 1; // rows start at 1
269
+ gc = cell.gs$cell.col - 1; // columns start at 1
270
+
271
+ // If both row and col falls inside start and end
272
+ // set the transposed cell value in the newly created columns
273
+ if (gc >= startColumn && gc <= endColumn &&
274
+ gr >= startRow && gr <= endRow) {
275
+ columns[gc - startColumn][gr - startRow] = cell.content.$t;
276
+ }
257
277
  }
258
278
  self.dataFound();
259
279
  });
@@ -322,7 +342,7 @@
322
342
  columns[col].isDatetime = true;
323
343
 
324
344
  } else { // string
325
- columns[col][row] = trimVal;
345
+ columns[col][row] = trimVal === '' ? null : trimVal;
326
346
  }
327
347
  }
328
348
 
@@ -486,21 +506,17 @@
486
506
  if (userOptions && userOptions.data) {
487
507
  Highcharts.data(Highcharts.extend(userOptions.data, {
488
508
  complete: function (dataOptions) {
489
- var datasets = [];
490
-
491
- // Don't merge the data arrays themselves
492
- each(dataOptions.series, function (series, i) {
493
- datasets[i] = series.data;
494
- series.data = null;
495
- });
496
509
 
510
+ // Merge series configs
511
+ if (userOptions.series) {
512
+ each(userOptions.series, function (series, i) {
513
+ userOptions.series[i] = Highcharts.merge(series, dataOptions.series[i]);
514
+ });
515
+ }
516
+
497
517
  // Do the merge
498
518
  userOptions = Highcharts.merge(dataOptions, userOptions);
499
-
500
- // Re-insert the data
501
- each(datasets, function (data, i) {
502
- userOptions.series[i].data = data;
503
- });
519
+
504
520
  proceed.call(chart, userOptions, callback);
505
521
  }
506
522
  }));
@@ -1,8 +1,8 @@
1
1
  /**
2
- * @license Highcharts JS v2.3.5 (2012-12-19)
2
+ * @license Highcharts JS v3.0.0 (2013-03-22)
3
3
  * Exporting module
4
4
  *
5
- * (c) 2010-2011 Torstein Hønsi
5
+ * (c) 2010-2013 Torstein Hønsi
6
6
  *
7
7
  * License: www.highcharts.com/license
8
8
  */
@@ -37,7 +37,8 @@ var Chart = Highcharts.Chart,
37
37
  PX = 'px',
38
38
  UNDEFINED,
39
39
  symbols = Highcharts.Renderer.prototype.symbols,
40
- defaultOptions = Highcharts.getOptions();
40
+ defaultOptions = Highcharts.getOptions(),
41
+ buttonOffset;
41
42
 
42
43
  // Add language
43
44
  extend(defaultOptions.lang, {
@@ -45,19 +46,21 @@ var Chart = Highcharts.Chart,
45
46
  downloadJPEG: 'Download JPEG image',
46
47
  downloadPDF: 'Download PDF document',
47
48
  downloadSVG: 'Download SVG vector image',
48
- exportButtonTitle: 'Export to raster or vector image',
49
- printButtonTitle: 'Print the chart'
49
+ contextButtonTitle: 'Chart context menu'
50
50
  });
51
51
 
52
+ // docs: update the new defaults and explain the compatibility pack
53
+
52
54
  // Buttons and menus are collected in a separate config option set called 'navigation'.
53
55
  // This can be extended later to add control buttons like zoom and pan right click menus.
54
56
  defaultOptions.navigation = {
55
57
  menuStyle: {
56
58
  border: '1px solid #A0A0A0',
57
- background: '#FFFFFF'
59
+ background: '#FFFFFF',
60
+ padding: '5px 0'
58
61
  },
59
62
  menuItemStyle: {
60
- padding: '0 5px',
63
+ padding: '0 10px',
61
64
  background: NONE,
62
65
  color: '#303030',
63
66
  fontSize: isTouchDevice ? '14px' : '11px'
@@ -67,32 +70,22 @@ defaultOptions.navigation = {
67
70
  color: '#FFFFFF'
68
71
  },
69
72
 
70
- buttonOptions: {
71
- align: 'right',
72
- backgroundColor: {
73
- linearGradient: [0, 0, 0, 20],
74
- stops: [
75
- [0.4, '#F7F7F7'],
76
- [0.6, '#E3E3E3']
77
- ]
78
- },
79
- borderColor: '#B0B0B0',
80
- borderRadius: 3,
81
- borderWidth: 1,
82
- //enabled: true,
83
- height: 20,
84
- hoverBorderColor: '#909090',
85
- hoverSymbolFill: '#81A7CF',
86
- hoverSymbolStroke: '#4572A5',
73
+ buttonOptions: { // docs
87
74
  symbolFill: '#E0E0E0',
88
- //symbolSize: 12,
89
- symbolStroke: '#A0A0A0',
90
- //symbolStrokeWidth: 1,
91
- symbolX: 11.5,
75
+ symbolSize: 14,
76
+ symbolStroke: '#666',
77
+ symbolStrokeWidth: 3,
78
+ symbolX: 12.5,
92
79
  symbolY: 10.5,
80
+ align: 'right',
81
+ buttonSpacing: 3,
82
+ height: 22,
83
+ theme: {
84
+ fill: 'white', // capture hover
85
+ stroke: 'none'
86
+ },
93
87
  verticalAlign: 'top',
94
- width: 24,
95
- y: 10
88
+ width: 24
96
89
  }
97
90
  };
98
91
 
@@ -104,17 +97,21 @@ defaultOptions.exporting = {
104
97
  //filename: 'chart',
105
98
  type: 'image/png',
106
99
  url: 'http://export.highcharts.com/',
107
- width: 800,
100
+ //width: undefined, // docs
101
+ //scale: 2 // docs
108
102
  buttons: {
109
- exportButton: {
110
- //enabled: true,
111
- symbol: 'exportIcon',
112
- x: -10,
113
- symbolFill: '#A8BF77',
114
- hoverSymbolFill: '#768F3E',
115
- _id: 'exportButton',
116
- _titleKey: 'exportButtonTitle',
103
+ contextButton: { // docs
104
+ //x: -10, // docs: x is different now
105
+ symbol: 'menu',
106
+ _titleKey: 'contextButtonTitle',
117
107
  menuItems: [{
108
+ text: 'Print chart',
109
+ onclick: function () {
110
+ this.print();
111
+ }
112
+ }, {
113
+ separator: true
114
+ }, {
118
115
  textKey: 'downloadPNG',
119
116
  onclick: function () {
120
117
  this.exportChart();
@@ -155,19 +152,6 @@ defaultOptions.exporting = {
155
152
  }
156
153
  } // */
157
154
  ]
158
-
159
- },
160
- printButton: {
161
- //enabled: true,
162
- symbol: 'printIcon',
163
- x: -36,
164
- symbolFill: '#B5C9DF',
165
- hoverSymbolFill: '#779ABF',
166
- _id: 'printButton',
167
- _titleKey: 'printButtonTitle',
168
- onclick: function () {
169
- this.print();
170
- }
171
155
  }
172
156
  }
173
157
  };
@@ -203,6 +187,7 @@ Highcharts.post = function (url, data) {
203
187
  };
204
188
 
205
189
  extend(Chart.prototype, {
190
+
206
191
  /**
207
192
  * Return an SVG representation of the chart
208
193
  *
@@ -214,6 +199,10 @@ extend(Chart.prototype, {
214
199
  sandbox,
215
200
  svg,
216
201
  seriesOptions,
202
+ sourceWidth,
203
+ sourceHeight,
204
+ cssWidth,
205
+ cssHeight,
217
206
  options = merge(chart.options, additionalOptions); // copy the options and add extra options
218
207
 
219
208
  // IE compatibility hack for generating SVG content that it doesn't really understand
@@ -232,11 +221,27 @@ extend(Chart.prototype, {
232
221
  width: chart.chartWidth + PX,
233
222
  height: chart.chartHeight + PX
234
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
+
235
237
 
236
238
  // override some options
237
239
  extend(options.chart, {
240
+ animation: false,
238
241
  renderTo: sandbox,
239
- forExport: true
242
+ forExport: true,
243
+ width: sourceWidth, // docs,
244
+ height: sourceHeight // docs
240
245
  });
241
246
  options.exporting.enabled = false; // hide buttons in print
242
247
  options.chart.plotBackgroundImage = null; // the converter doesn't handle images
@@ -256,7 +261,7 @@ extend(Chart.prototype, {
256
261
  });
257
262
 
258
263
  // generate the chart copy
259
- chartCopy = new Highcharts.Chart(options);
264
+ chartCopy = new Highcharts.Chart(options, chart.callback);
260
265
 
261
266
  // reflect axis extremes in the export
262
267
  each(['xAxis', 'yAxis'], function (axisType) {
@@ -286,7 +291,6 @@ extend(Chart.prototype, {
286
291
  .replace(/isShadow="[^"]+"/g, '')
287
292
  .replace(/symbolName="[^"]+"/g, '')
288
293
  .replace(/jQuery[0-9]+="[^"]+"/g, '')
289
- .replace(/isTracker="[^"]+"/g, '')
290
294
  .replace(/url\([^#]+#/g, 'url(#')
291
295
  .replace(/<svg /, '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ')
292
296
  .replace(/ href=/g, ' xlink:href=')
@@ -330,17 +334,30 @@ extend(Chart.prototype, {
330
334
  * @param {Object} chartOptions Additional chart options for the SVG representation of the chart
331
335
  */
332
336
  exportChart: function (options, chartOptions) {
333
- var exportingOptions = this.options.exporting,
334
- svg = this.getSVG(merge(exportingOptions.chartOptions, chartOptions));
337
+
338
+ options = options || {};
339
+
340
+ var chart = this,
341
+ svg = chart.getSVG(merge(
342
+ { chart: { borderRadius: 0 } }, // docs: defaults to 0 for exported charts
343
+ chart.options.exporting.chartOptions, // docs
344
+ chartOptions,
345
+ {
346
+ exporting: {
347
+ sourceWidth: options.sourceWidth, // docs
348
+ sourceHeight: options.sourceHeight // docs
349
+ }
350
+ }
351
+ ));
335
352
 
336
353
  // merge the options
337
- options = merge(exportingOptions, options);
354
+ options = merge(chart.options.exporting, options);
338
355
 
339
356
  // do the post
340
357
  Highcharts.post(options.url, {
341
358
  filename: options.filename || 'chart',
342
359
  type: options.type,
343
- width: options.width,
360
+ width: options.width || 0, // IE8 fails to post undefined correctly, so use 0
344
361
  scale: options.scale || 2,
345
362
  svg: svg
346
363
  });
@@ -377,6 +394,7 @@ extend(Chart.prototype, {
377
394
  body.appendChild(container);
378
395
 
379
396
  // print
397
+ win.focus(); // #1510
380
398
  win.print();
381
399
 
382
400
  // allow the browser to prepare before reverting
@@ -408,7 +426,7 @@ extend(Chart.prototype, {
408
426
  * @param {Number} width The width of the opener button
409
427
  * @param {Number} height The height of the opener button
410
428
  */
411
- contextMenu: function (name, items, x, y, width, height) {
429
+ contextMenu: function (name, items, x, y, width, height, button) {
412
430
  var chart = this,
413
431
  navOptions = chart.options.navigation,
414
432
  menuItemStyle = navOptions.menuItemStyle,
@@ -445,6 +463,9 @@ extend(Chart.prototype, {
445
463
  // hide on mouse out
446
464
  hide = function () {
447
465
  css(menu, { display: NONE });
466
+ if (button) {
467
+ button.setState(0);
468
+ }
448
469
  };
449
470
 
450
471
  // Hide the menu some time after mouse leave (#1357)
@@ -459,25 +480,27 @@ extend(Chart.prototype, {
459
480
  // create the items
460
481
  each(items, function (item) {
461
482
  if (item) {
462
- var div = createElement(DIV, {
463
- onmouseover: function () {
464
- css(this, navOptions.menuItemHoverStyle);
465
- },
466
- onmouseout: function () {
467
- css(this, menuItemStyle);
468
- },
469
- innerHTML: item.text || chart.options.lang[item.textKey]
470
- }, extend({
471
- cursor: 'pointer'
472
- }, menuItemStyle), innerMenu);
473
-
474
- div.onclick = function () {
475
- hide();
476
- item.onclick.apply(chart, arguments);
477
- };
483
+ var element = item.separator ?
484
+ createElement('hr', null, null, innerMenu) :
485
+ createElement(DIV, {
486
+ onmouseover: function () {
487
+ css(this, navOptions.menuItemHoverStyle);
488
+ },
489
+ onmouseout: function () {
490
+ css(this, menuItemStyle);
491
+ },
492
+ onclick: function () {
493
+ hide();
494
+ item.onclick.apply(chart, arguments);
495
+ },
496
+ innerHTML: item.text || chart.options.lang[item.textKey]
497
+ }, extend({
498
+ cursor: 'pointer'
499
+ }, menuItemStyle), innerMenu);
500
+
478
501
 
479
502
  // Keep references to menu divs to be able to destroy them
480
- chart.exportDivElements.push(div);
503
+ chart.exportDivElements.push(element);
481
504
  }
482
505
  });
483
506
 
@@ -515,22 +538,14 @@ extend(Chart.prototype, {
515
538
  btnOptions = merge(chart.options.navigation.buttonOptions, options),
516
539
  onclick = btnOptions.onclick,
517
540
  menuItems = btnOptions.menuItems,
518
- buttonWidth = btnOptions.width,
519
- buttonHeight = btnOptions.height,
520
- box,
521
541
  symbol,
522
542
  button,
523
- menuKey,
524
- borderWidth = btnOptions.borderWidth,
525
- boxAttr = {
526
- stroke: btnOptions.borderColor
527
-
528
- },
529
543
  symbolAttr = {
530
544
  stroke: btnOptions.symbolStroke,
531
545
  fill: btnOptions.symbolFill
532
546
  },
533
- symbolSize = btnOptions.symbolSize || 12;
547
+ symbolSize = btnOptions.symbolSize || 12,
548
+ menuKey;
534
549
 
535
550
  if (!chart.btnCount) {
536
551
  chart.btnCount = 0;
@@ -547,99 +562,85 @@ extend(Chart.prototype, {
547
562
  return;
548
563
  }
549
564
 
550
- // element to capture the click
551
- function revert() {
552
- symbol.attr(symbolAttr);
553
- box.attr(boxAttr);
565
+
566
+ var attr = btnOptions.theme,
567
+ states = attr.states,
568
+ hover = states && states.hover,
569
+ select = states && states.select,
570
+ callback;
571
+
572
+ delete attr.states;
573
+
574
+ if (onclick) {
575
+ callback = function () {
576
+ onclick.apply(chart, arguments);
577
+ };
578
+
579
+ } else if (menuItems) {
580
+ callback = function () {
581
+ chart.contextMenu(
582
+ 'contextmenu',
583
+ menuItems,
584
+ button.translateX,
585
+ button.translateY,
586
+ button.width,
587
+ button.height,
588
+ button
589
+ );
590
+ button.setState(2);
591
+ };
592
+ }
593
+
594
+
595
+ if (btnOptions.text && btnOptions.symbol) {
596
+ attr.paddingLeft = Highcharts.pick(attr.paddingLeft, 25);
597
+
598
+ } else if (!btnOptions.text) {
599
+ extend(attr, {
600
+ width: btnOptions.width,
601
+ height: btnOptions.height,
602
+ padding: 0
603
+ });
554
604
  }
555
605
 
556
- // the box border
557
- box = renderer.rect(
558
- 0,
559
- 0,
560
- buttonWidth,
561
- buttonHeight,
562
- btnOptions.borderRadius,
563
- borderWidth
564
- )
565
- //.translate(buttonLeft, buttonTop) // to allow gradients
566
- .align(btnOptions, true)
567
- .attr(extend({
568
- fill: btnOptions.backgroundColor,
569
- 'stroke-width': borderWidth,
570
- zIndex: 19
571
- }, boxAttr)).add();
572
-
573
- // the invisible element to track the clicks
574
- button = renderer.rect(
575
- 0,
576
- 0,
577
- buttonWidth,
578
- buttonHeight,
579
- 0
580
- )
581
- .align(btnOptions)
606
+ button = renderer.button(btnOptions.text, 0, 0, callback, attr, hover, select)
582
607
  .attr({
583
- id: btnOptions._id,
584
- fill: 'rgba(255, 255, 255, 0.001)',
585
608
  title: chart.options.lang[btnOptions._titleKey],
586
- zIndex: 21
587
- }).css({
588
- cursor: 'pointer'
589
- })
590
- .on('mouseover', function () {
591
- symbol.attr({
592
- stroke: btnOptions.hoverSymbolStroke,
593
- fill: btnOptions.hoverSymbolFill
594
- });
595
- box.attr({
596
- stroke: btnOptions.hoverBorderColor
597
- });
598
- })
599
- .on('mouseout', revert)
600
- .on('click', revert)
601
- .add();
602
-
603
- // add the click event
604
- if (menuItems) {
605
-
606
- onclick = function () {
607
- revert();
608
- var bBox = button.getBBox();
609
- chart.contextMenu('menu' + menuKey, menuItems, bBox.x, bBox.y, buttonWidth, buttonHeight);
610
- };
609
+ 'stroke-linecap': 'round'
610
+ });
611
+
612
+ if (btnOptions.symbol) {
613
+ symbol = renderer.symbol(
614
+ btnOptions.symbol,
615
+ btnOptions.symbolX - (symbolSize / 2),
616
+ btnOptions.symbolY - (symbolSize / 2),
617
+ symbolSize,
618
+ symbolSize
619
+ )
620
+ .attr(extend(symbolAttr, {
621
+ 'stroke-width': btnOptions.symbolStrokeWidth || 1,
622
+ zIndex: 1
623
+ })).add(button);
611
624
  }
612
- /*addEvent(button.element, 'click', function() {
613
- onclick.apply(chart, arguments);
614
- });*/
615
- button.on('click', function () {
616
- onclick.apply(chart, arguments);
617
- });
618
625
 
619
- // the icon
620
- symbol = renderer.symbol(
621
- btnOptions.symbol,
622
- btnOptions.symbolX - (symbolSize / 2),
623
- btnOptions.symbolY - (symbolSize / 2),
624
- symbolSize,
625
- symbolSize
626
- )
627
- .align(btnOptions, true)
628
- .attr(extend(symbolAttr, {
629
- 'stroke-width': btnOptions.symbolStrokeWidth || 1,
630
- zIndex: 20
631
- })).add();
632
-
633
- // Keep references to the renderer element so to be able to destroy them later.
634
- chart.exportSVGElements.push(box, button, symbol);
626
+ button.add()
627
+ .align(extend(btnOptions, {
628
+ width: button.width,
629
+ x: buttonOffset
630
+ }), true, 'spacingBox');
631
+
632
+ buttonOffset += (button.width + btnOptions.buttonSpacing) * (btnOptions.align === 'right' ? -1 : 1);
633
+
634
+ chart.exportSVGElements.push(button, symbol);
635
+
635
636
  },
636
637
 
637
638
  /**
638
639
  * Destroy the buttons.
639
640
  */
640
- destroyExport: function () {
641
- var i,
642
- chart = this,
641
+ destroyExport: function (e) {
642
+ var chart = e.target,
643
+ i,
643
644
  elem;
644
645
 
645
646
  // Destroy the extra buttons added
@@ -666,69 +667,18 @@ extend(Chart.prototype, {
666
667
  }
667
668
  });
668
669
 
669
- /**
670
- * Crisp for 1px stroke width, which is default. In the future, consider a smarter,
671
- * global function.
672
- */
673
- function crisp(arr) {
674
- var i = arr.length;
675
- while (i--) {
676
- if (typeof arr[i] === 'number') {
677
- arr[i] = Math.round(arr[i]) - 0.5;
678
- }
679
- }
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
680
  return arr;
681
- }
682
-
683
- // Create the export icon
684
- symbols.exportIcon = function (x, y, width, height) {
685
- return crisp([
686
- M, // the disk
687
- x, y + width,
688
- L,
689
- x + width, y + height,
690
- x + width, y + height * 0.8,
691
- x, y + height * 0.8,
692
- 'Z',
693
- M, // the arrow
694
- x + width * 0.5, y + height * 0.8,
695
- L,
696
- x + width * 0.8, y + height * 0.4,
697
- x + width * 0.4, y + height * 0.4,
698
- x + width * 0.4, y,
699
- x + width * 0.6, y,
700
- x + width * 0.6, y + height * 0.4,
701
- x + width * 0.2, y + height * 0.4,
702
- 'Z'
703
- ]);
704
681
  };
705
- // Create the print icon
706
- symbols.printIcon = function (x, y, width, height) {
707
- return crisp([
708
- M, // the printer
709
- x, y + height * 0.7,
710
- L,
711
- x + width, y + height * 0.7,
712
- x + width, y + height * 0.4,
713
- x, y + height * 0.4,
714
- 'Z',
715
- M, // the upper sheet
716
- x + width * 0.2, y + height * 0.4,
717
- L,
718
- x + width * 0.2, y,
719
- x + width * 0.8, y,
720
- x + width * 0.8, y + height * 0.4,
721
- 'Z',
722
- M, // the lower sheet
723
- x + width * 0.2, y + height * 0.7,
724
- L,
725
- x, y + height,
726
- x + width, y + height,
727
- x + width * 0.8, y + height * 0.7,
728
- 'Z'
729
- ]);
730
- };
731
-
732
682
 
733
683
  // Add the buttons on chart load
734
684
  Chart.prototype.callbacks.push(function (chart) {
@@ -736,6 +686,8 @@ Chart.prototype.callbacks.push(function (chart) {
736
686
  exportingOptions = chart.options.exporting,
737
687
  buttons = exportingOptions.buttons;
738
688
 
689
+ buttonOffset = 0;
690
+
739
691
  if (exportingOptions.enabled !== false) {
740
692
 
741
693
  for (n in buttons) {