chartkick 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of chartkick might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d2cca10828cf50bfef4cf0d276ca3b5f03874c6
4
- data.tar.gz: 7dd04885900e535eda3bada4bb9efd91792dab01
3
+ metadata.gz: 06c3f38fbf6ee6a1981868e6c8b66d41b622573e
4
+ data.tar.gz: 1cd7e3761a9cfa989ae2add1f2715103edd8212a
5
5
  SHA512:
6
- metadata.gz: 0481002107a308918f2db7bdb4fa6c2e820ae4d305b497c3e3acde5c51702bc42107b3c6e81e6c188f41c67e7af904d581617b37f8bd6a35605e94297c3e228b
7
- data.tar.gz: 7ca0e4af5586b5b30f400452032ce81706775783ddd7414ee54d0fc570a96eac97ac741383d0de0d4ab5a97266b71fcccd4a6c9028900ef96cde4173a80c76a6
6
+ metadata.gz: 20b26ec98f97e04d04ca157c4731fbb035c12bcb93c30ea78a3f9d7ca5c0d96f859e82ba99a773cd4e413e988211dfcf46c6e914769151a9fa0b706dd2186d27
7
+ data.tar.gz: f7a0cc574921407145c356c91b987834e60d6e22677b005ff97d4185d8270c9fabbc4a8b8d36a310cecb400760b578e974c799ea1f67d3e644bffaec452a3138
@@ -1,3 +1,10 @@
1
+ ## 2.1.0 [unreleased]
2
+
3
+ - Added basic support for new Google Charts loader
4
+ - Added `configure` function
5
+ - Dropped jQuery and Zepto dependencies for AJAX
6
+ - Updated Chart.js to 2.2.2
7
+
1
8
  ## 2.0.2
2
9
 
3
10
  - Updated Chartkick.js to 2.0.1
data/README.md CHANGED
@@ -78,7 +78,7 @@ or
78
78
 
79
79
  ### Say Goodbye To Timeouts
80
80
 
81
- Make your pages load super fast and stop worrying about timeouts. Give each chart its own endpoint.
81
+ Make your pages load super fast and stop worrying about timeouts. Give each chart its own endpoint.
82
82
 
83
83
  ```erb
84
84
  <%= line_chart completed_tasks_charts_path %>
@@ -94,8 +94,6 @@ class ChartsController < ApplicationController
94
94
  end
95
95
  ```
96
96
 
97
- **Note:** This feature requires [jQuery](http://jquery.com/) or [Zepto](http://zeptojs.com/) at the moment.
98
-
99
97
  For multiple series, add `chart_json` at the end.
100
98
 
101
99
  ```ruby
@@ -260,16 +258,6 @@ In `application.js`, add:
260
258
 
261
259
  Works with Highcharts 2.1+
262
260
 
263
- ### For Rails 2.3 and 3.0
264
-
265
- You must include `chartkick.js` manually. [Download it here](https://raw.github.com/ankane/chartkick/master/app/assets/javascripts/chartkick.js)
266
-
267
- For Rails 2.3, you must use a script tag for Google Charts due to [this bug](https://rails.lighthouseapp.com/projects/8994/tickets/1664-javascript_include_tag-shouldnt-append-a-js-onto-external-urls).
268
-
269
- ```html
270
- <script src="https://www.google.com/jsapi"></script>
271
- ```
272
-
273
261
  ### For Sinatra
274
262
 
275
263
  You must include `chartkick.js` manually. [Download it here](https://raw.github.com/ankane/chartkick/master/app/assets/javascripts/chartkick.js)
@@ -291,13 +279,11 @@ You must include `chartkick.js` manually. [Download it here](https://raw.github
291
279
 
292
280
  To specify a language for Google Charts, add:
293
281
 
294
- ```html
295
- <script>
296
- var Chartkick = {"language": "de"};
297
- </script>
282
+ ```javascript
283
+ Chartkick.configure({"language": "de"});
298
284
  ```
299
285
 
300
- **before** the JavaScript files.
286
+ after the JavaScript files and before your charts.
301
287
 
302
288
  ## JavaScript API
303
289
 
@@ -2,7 +2,7 @@
2
2
  * Chartkick.js
3
3
  * Create beautiful JavaScript charts with minimal code
4
4
  * https://github.com/ankane/chartkick.js
5
- * v2.0.1
5
+ * v2.1.0
6
6
  * MIT License
7
7
  */
8
8
 
@@ -62,10 +62,10 @@
62
62
  function parseISO8601(input) {
63
63
  var day, hour, matches, milliseconds, minutes, month, offset, result, seconds, type, year;
64
64
  type = Object.prototype.toString.call(input);
65
- if (type === '[object Date]') {
65
+ if (type === "[object Date]") {
66
66
  return input;
67
67
  }
68
- if (type !== '[object String]') {
68
+ if (type !== "[object String]") {
69
69
  return;
70
70
  }
71
71
  matches = input.match(ISO8601_PATTERN);
@@ -83,7 +83,7 @@
83
83
  if (matches[17]) {
84
84
  offset += parseInt(matches[17], 10);
85
85
  }
86
- offset *= matches[14] === '-' ? -1 : 1;
86
+ offset *= matches[14] === "-" ? -1 : 1;
87
87
  result -= offset * 60 * 1000;
88
88
  }
89
89
  return new Date(result);
@@ -164,18 +164,37 @@
164
164
  }
165
165
 
166
166
  function getJSON(element, url, success) {
167
- var $ = window.jQuery || window.Zepto || window.$;
168
- $.ajax({
169
- dataType: "json",
170
- url: url,
171
- success: success,
172
- error: function (jqXHR, textStatus, errorThrown) {
173
- var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
174
- chartError(element, message);
175
- }
167
+ ajaxCall(url, success, function (jqXHR, textStatus, errorThrown) {
168
+ var message = (typeof errorThrown === "string") ? errorThrown : errorThrown.message;
169
+ chartError(element, message);
176
170
  });
177
171
  }
178
172
 
173
+ function ajaxCall(url, success, error) {
174
+ var $ = window.jQuery || window.Zepto || window.$;
175
+
176
+ if ($) {
177
+ $.ajax({
178
+ dataType: "json",
179
+ url: url,
180
+ success: success,
181
+ error: error
182
+ });
183
+ } else {
184
+ var xhr = new XMLHttpRequest();
185
+ xhr.open("GET", url, true);
186
+ xhr.setRequestHeader("Content-Type", "application/json");
187
+ xhr.onload = function () {
188
+ if (xhr.status === 200) {
189
+ success(JSON.parse(xhr.responseText), xhr.statusText, xhr);
190
+ } else {
191
+ error(xhr, "error", xhr.statusText);
192
+ }
193
+ };
194
+ xhr.send();
195
+ }
196
+ }
197
+
179
198
  function errorCatcher(chart, callback) {
180
199
  try {
181
200
  callback(chart);
@@ -344,7 +363,9 @@
344
363
  }
345
364
  var options = jsOptions(chart.data, chart.options, chartOptions), data, i, j;
346
365
  options.xAxis.type = chart.options.discrete ? "category" : "datetime";
347
- options.chart.type = chartType;
366
+ if (!options.chart.type) {
367
+ options.chart.type = chartType;
368
+ }
348
369
  options.chart.renderTo = chart.element.id;
349
370
 
350
371
  var series = chart.data;
@@ -364,7 +385,7 @@
364
385
  this.renderScatterChart = function (chart) {
365
386
  var chartOptions = {};
366
387
  var options = jsOptions(chart.data, chart.options, chartOptions);
367
- options.chart.type = 'scatter';
388
+ options.chart.type = "scatter";
368
389
  options.chart.renderTo = chart.element.id;
369
390
  options.series = chart.data;
370
391
  new Highcharts.Chart(options);
@@ -441,7 +462,7 @@
441
462
  };
442
463
  adapters.push(HighchartsAdapter);
443
464
  }
444
- if (!GoogleChartsAdapter && window.google && window.google.setOnLoadCallback) {
465
+ if (!GoogleChartsAdapter && window.google && (window.google.setOnLoadCallback || window.google.charts)) {
445
466
  GoogleChartsAdapter = new function () {
446
467
  var google = window.google;
447
468
 
@@ -484,7 +505,12 @@
484
505
  if (config.language) {
485
506
  loadOptions.language = config.language;
486
507
  }
487
- google.load("visualization", "1", loadOptions);
508
+
509
+ if (window.google.setOnLoadCallback) {
510
+ google.load("visualization", "1", loadOptions);
511
+ } else {
512
+ google.charts.load("current", loadOptions);
513
+ }
488
514
  }
489
515
  };
490
516
 
@@ -1385,7 +1411,14 @@
1385
1411
  Timeline: function (element, dataSource, opts) {
1386
1412
  setElement(this, element, dataSource, opts, processTimelineData);
1387
1413
  },
1388
- charts: {}
1414
+ charts: {},
1415
+ configure: function (options) {
1416
+ for (var key in options) {
1417
+ if (options.hasOwnProperty(key)) {
1418
+ config[key] = options[key];
1419
+ }
1420
+ }
1421
+ }
1389
1422
  };
1390
1423
 
1391
1424
  if (typeof module === "object" && typeof module.exports === "object") {
@@ -1,3 +1,3 @@
1
1
  module Chartkick
2
- VERSION = "2.0.2"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * Chart.js
3
3
  * http://chartjs.org/
4
- * Version: 2.2.1
4
+ * Version: 2.2.2
5
5
  *
6
6
  * Copyright 2016 Nick Downie
7
7
  * Released under the MIT license
@@ -6530,7 +6530,7 @@ module.exports = function(Chart) {
6530
6530
  categorySpacing: categorySpacing,
6531
6531
  fullBarHeight: fullBarHeight,
6532
6532
  barHeight: barHeight,
6533
- barSpacing: barSpacing,
6533
+ barSpacing: barSpacing
6534
6534
  };
6535
6535
  },
6536
6536
 
@@ -7111,6 +7111,7 @@ module.exports = function(Chart) {
7111
7111
  borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
7112
7112
  fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
7113
7113
  steppedLine: custom.steppedLine ? custom.steppedLine : helpers.getValueOrDefault(dataset.steppedLine, lineElementOptions.stepped),
7114
+ cubicInterpolationMode: custom.cubicInterpolationMode ? custom.cubicInterpolationMode : helpers.getValueOrDefault(dataset.cubicInterpolationMode, lineElementOptions.cubicInterpolationMode),
7114
7115
  // Scale
7115
7116
  scaleTop: scale.top,
7116
7117
  scaleBottom: scale.bottom,
@@ -7194,6 +7195,8 @@ module.exports = function(Chart) {
7194
7195
  var xScale = me.getScaleForId(meta.xAxisID);
7195
7196
  var pointOptions = me.chart.options.elements.point;
7196
7197
  var x, y;
7198
+ var labels = me.chart.data.labels || [];
7199
+ var includeOffset = (labels.length === 1 || dataset.data.length === 1) || me.chart.isCombo;
7197
7200
 
7198
7201
  // Compatibility: If the properties are defined with only the old name, use those values
7199
7202
  if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
@@ -7203,7 +7206,7 @@ module.exports = function(Chart) {
7203
7206
  dataset.pointHitRadius = dataset.hitRadius;
7204
7207
  }
7205
7208
 
7206
- x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex, me.chart.isCombo);
7209
+ x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex, includeOffset);
7207
7210
  y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex);
7208
7211
 
7209
7212
  // Utility
@@ -7269,30 +7272,45 @@ module.exports = function(Chart) {
7269
7272
  var meta = me.getMeta();
7270
7273
  var area = me.chart.chartArea;
7271
7274
 
7272
- // only consider points that are drawn in case the spanGaps option is ued
7273
- var points = (meta.data || []).filter(function(pt) { return !pt._model.skip; });
7275
+ // Only consider points that are drawn in case the spanGaps option is used
7276
+ var points = (meta.data || []);
7277
+ if (meta.dataset._model.spanGaps) points = points.filter(function(pt) { return !pt._model.skip; });
7274
7278
  var i, ilen, point, model, controlPoints;
7275
7279
 
7276
- var needToCap = me.chart.options.elements.line.capBezierPoints;
7277
- function capIfNecessary(pt, min, max) {
7278
- return needToCap ? Math.max(Math.min(pt, max), min) : pt;
7280
+ function capControlPoint(pt, min, max) {
7281
+ return Math.max(Math.min(pt, max), min);
7279
7282
  }
7280
7283
 
7281
- for (i=0, ilen=points.length; i<ilen; ++i) {
7282
- point = points[i];
7283
- model = point._model;
7284
- controlPoints = helpers.splineCurve(
7285
- helpers.previousItem(points, i)._model,
7286
- model,
7287
- helpers.nextItem(points, i)._model,
7288
- meta.dataset._model.tension
7289
- );
7284
+ if (meta.dataset._model.cubicInterpolationMode == 'monotone') {
7285
+ helpers.splineCurveMonotone(points);
7286
+ }
7287
+ else {
7288
+ for (i = 0, ilen = points.length; i < ilen; ++i) {
7289
+ point = points[i];
7290
+ model = point._model;
7291
+ controlPoints = helpers.splineCurve(
7292
+ helpers.previousItem(points, i)._model,
7293
+ model,
7294
+ helpers.nextItem(points, i)._model,
7295
+ meta.dataset._model.tension
7296
+ );
7297
+ model.controlPointPreviousX = controlPoints.previous.x;
7298
+ model.controlPointPreviousY = controlPoints.previous.y;
7299
+ model.controlPointNextX = controlPoints.next.x;
7300
+ model.controlPointNextY = controlPoints.next.y;
7301
+ }
7302
+ }
7290
7303
 
7291
- model.controlPointPreviousX = capIfNecessary(controlPoints.previous.x, area.left, area.right);
7292
- model.controlPointPreviousY = capIfNecessary(controlPoints.previous.y, area.top, area.bottom);
7293
- model.controlPointNextX = capIfNecessary(controlPoints.next.x, area.left, area.right);
7294
- model.controlPointNextY = capIfNecessary(controlPoints.next.y, area.top, area.bottom);
7304
+ if (me.chart.options.elements.line.capBezierPoints) {
7305
+ for (i = 0, ilen = points.length; i < ilen; ++i) {
7306
+ model = points[i]._model;
7307
+ model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right);
7308
+ model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom);
7309
+ model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right);
7310
+ model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom);
7311
+ }
7295
7312
  }
7313
+
7296
7314
  },
7297
7315
 
7298
7316
  draw: function(ease) {
@@ -9298,6 +9316,77 @@ module.exports = function(Chart) {
9298
9316
  }
9299
9317
  };
9300
9318
  };
9319
+ helpers.EPSILON = Number.EPSILON || 1e-14;
9320
+ helpers.splineCurveMonotone = function(points) {
9321
+ // This function calculates Bézier control points in a similar way than |splineCurve|,
9322
+ // but preserves monotonicity of the provided data and ensures no local extremums are added
9323
+ // between the dataset discrete points due to the interpolation.
9324
+ // See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation
9325
+
9326
+ var pointsWithTangents = (points || []).map(function(point) {
9327
+ return {
9328
+ model: point._model,
9329
+ deltaK: 0,
9330
+ mK: 0
9331
+ };
9332
+ });
9333
+
9334
+ // Calculate slopes (deltaK) and initialize tangents (mK)
9335
+ var pointsLen = pointsWithTangents.length;
9336
+ var i, pointBefore, pointCurrent, pointAfter;
9337
+ for (i = 0; i < pointsLen; ++i) {
9338
+ pointCurrent = pointsWithTangents[i];
9339
+ if (pointCurrent.model.skip) continue;
9340
+ pointBefore = i > 0 ? pointsWithTangents[i - 1] : null;
9341
+ pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null;
9342
+ if (pointAfter && !pointAfter.model.skip) {
9343
+ pointCurrent.deltaK = (pointAfter.model.y - pointCurrent.model.y) / (pointAfter.model.x - pointCurrent.model.x);
9344
+ }
9345
+ if (!pointBefore || pointBefore.model.skip) pointCurrent.mK = pointCurrent.deltaK;
9346
+ else if (!pointAfter || pointAfter.model.skip) pointCurrent.mK = pointBefore.deltaK;
9347
+ else if (this.sign(pointBefore.deltaK) != this.sign(pointCurrent.deltaK)) pointCurrent.mK = 0;
9348
+ else pointCurrent.mK = (pointBefore.deltaK + pointCurrent.deltaK) / 2;
9349
+ }
9350
+
9351
+ // Adjust tangents to ensure monotonic properties
9352
+ var alphaK, betaK, tauK, squaredMagnitude;
9353
+ for (i = 0; i < pointsLen - 1; ++i) {
9354
+ pointCurrent = pointsWithTangents[i];
9355
+ pointAfter = pointsWithTangents[i + 1];
9356
+ if (pointCurrent.model.skip || pointAfter.model.skip) continue;
9357
+ if (helpers.almostEquals(pointCurrent.deltaK, 0, this.EPSILON))
9358
+ {
9359
+ pointCurrent.mK = pointAfter.mK = 0;
9360
+ continue;
9361
+ }
9362
+ alphaK = pointCurrent.mK / pointCurrent.deltaK;
9363
+ betaK = pointAfter.mK / pointCurrent.deltaK;
9364
+ squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2);
9365
+ if (squaredMagnitude <= 9) continue;
9366
+ tauK = 3 / Math.sqrt(squaredMagnitude);
9367
+ pointCurrent.mK = alphaK * tauK * pointCurrent.deltaK;
9368
+ pointAfter.mK = betaK * tauK * pointCurrent.deltaK;
9369
+ }
9370
+
9371
+ // Compute control points
9372
+ var deltaX;
9373
+ for (i = 0; i < pointsLen; ++i) {
9374
+ pointCurrent = pointsWithTangents[i];
9375
+ if (pointCurrent.model.skip) continue;
9376
+ pointBefore = i > 0 ? pointsWithTangents[i - 1] : null;
9377
+ pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null;
9378
+ if (pointBefore && !pointBefore.model.skip) {
9379
+ deltaX = (pointCurrent.model.x - pointBefore.model.x) / 3;
9380
+ pointCurrent.model.controlPointPreviousX = pointCurrent.model.x - deltaX;
9381
+ pointCurrent.model.controlPointPreviousY = pointCurrent.model.y - deltaX * pointCurrent.mK;
9382
+ }
9383
+ if (pointAfter && !pointAfter.model.skip) {
9384
+ deltaX = (pointAfter.model.x - pointCurrent.model.x) / 3;
9385
+ pointCurrent.model.controlPointNextX = pointCurrent.model.x + deltaX;
9386
+ pointCurrent.model.controlPointNextY = pointCurrent.model.y + deltaX * pointCurrent.mK;
9387
+ }
9388
+ }
9389
+ };
9301
9390
  helpers.nextItem = function(collection, index, loop) {
9302
9391
  if (loop) {
9303
9392
  return index >= collection.length - 1 ? collection[0] : collection[index + 1];
@@ -9835,6 +9924,7 @@ module.exports = function(Chart) {
9835
9924
  }
9836
9925
 
9837
9926
  // Set the style
9927
+ hiddenIframe.tabIndex = -1;
9838
9928
  var style = hiddenIframe.style;
9839
9929
  style.width = '100%';
9840
9930
  style.display = 'block';
@@ -10961,7 +11051,9 @@ module.exports = function(Chart) {
10961
11051
  tickMarkLength: 10,
10962
11052
  zeroLineWidth: 1,
10963
11053
  zeroLineColor: "rgba(0,0,0,0.25)",
10964
- offsetGridLines: false
11054
+ offsetGridLines: false,
11055
+ borderDash: [],
11056
+ borderDashOffset: 0.0
10965
11057
  },
10966
11058
 
10967
11059
  // scale label
@@ -11217,6 +11309,7 @@ module.exports = function(Chart) {
11217
11309
  var globalDefaults = Chart.defaults.global;
11218
11310
  var tickOpts = opts.ticks;
11219
11311
  var scaleLabelOpts = opts.scaleLabel;
11312
+ var gridLineOpts = opts.gridLines;
11220
11313
  var display = opts.display;
11221
11314
  var isHorizontal = me.isHorizontal();
11222
11315
 
@@ -11234,12 +11327,12 @@ module.exports = function(Chart) {
11234
11327
  // subtract the margins to line up with the chartArea if we are a full width scale
11235
11328
  minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth;
11236
11329
  } else {
11237
- minSize.width = display ? tickMarkLength : 0;
11330
+ minSize.width = display && gridLineOpts.drawTicks ? tickMarkLength : 0;
11238
11331
  }
11239
11332
 
11240
11333
  // height
11241
11334
  if (isHorizontal) {
11242
- minSize.height = display ? tickMarkLength : 0;
11335
+ minSize.height = display && gridLineOpts.drawTicks ? tickMarkLength : 0;
11243
11336
  } else {
11244
11337
  minSize.height = me.maxHeight; // fill all the height
11245
11338
  }
@@ -11444,6 +11537,8 @@ module.exports = function(Chart) {
11444
11537
  var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);
11445
11538
  var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
11446
11539
  var tl = gridLines.tickMarkLength;
11540
+ var borderDash = helpers.getValueOrDefault(gridLines.borderDash, globalDefaults.borderDash);
11541
+ var borderDashOffset = helpers.getValueOrDefault(gridLines.borderDashOffset, globalDefaults.borderDashOffset);
11447
11542
 
11448
11543
  var scaleLabelFontColor = helpers.getValueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor);
11449
11544
  var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabel.fontSize, globalDefaults.defaultFontSize);
@@ -11583,6 +11678,8 @@ module.exports = function(Chart) {
11583
11678
  labelY: labelY,
11584
11679
  glWidth: lineWidth,
11585
11680
  glColor: lineColor,
11681
+ glBorderDash: borderDash,
11682
+ glBorderDashOffset: borderDashOffset,
11586
11683
  rotation: -1 * labelRotationRadians,
11587
11684
  label: label,
11588
11685
  textBaseline: textBaseline,
@@ -11593,8 +11690,13 @@ module.exports = function(Chart) {
11593
11690
  // Draw all of the tick labels, tick marks, and grid lines at the correct places
11594
11691
  helpers.each(itemsToDraw, function(itemToDraw) {
11595
11692
  if (gridLines.display) {
11693
+ context.save();
11596
11694
  context.lineWidth = itemToDraw.glWidth;
11597
11695
  context.strokeStyle = itemToDraw.glColor;
11696
+ if (context.setLineDash) {
11697
+ context.setLineDash(itemToDraw.glBorderDash);
11698
+ context.lineDashOffset = itemToDraw.glBorderDashOffset;
11699
+ }
11598
11700
 
11599
11701
  context.beginPath();
11600
11702
 
@@ -11609,6 +11711,7 @@ module.exports = function(Chart) {
11609
11711
  }
11610
11712
 
11611
11713
  context.stroke();
11714
+ context.restore();
11612
11715
  }
11613
11716
 
11614
11717
  if (optionTicks.display) {
@@ -12232,7 +12335,9 @@ module.exports = function(Chart) {
12232
12335
 
12233
12336
  // If the user provided a sorting function, use it to modify the tooltip items
12234
12337
  if (opts.itemSort) {
12235
- tooltipItems = tooltipItems.sort(opts.itemSort);
12338
+ tooltipItems = tooltipItems.sort(function(a,b) {
12339
+ return opts.itemSort(a,b, data);
12340
+ });
12236
12341
  }
12237
12342
 
12238
12343
  // If there is more than one item, show color items
@@ -12867,7 +12972,7 @@ module.exports = function(Chart) {
12867
12972
  }
12868
12973
  }
12869
12974
 
12870
- if (!loop) {
12975
+ if (!loop && lastDrawnIndex !== -1) {
12871
12976
  ctx.lineTo(points[lastDrawnIndex]._view.x, scaleZero);
12872
12977
  }
12873
12978
 
@@ -12901,9 +13006,7 @@ module.exports = function(Chart) {
12901
13006
 
12902
13007
  // First point moves to it's starting position no matter what
12903
13008
  if (index === 0) {
12904
- if (currentVM.skip) {
12905
-
12906
- } else {
13009
+ if (!currentVM.skip) {
12907
13010
  ctx.moveTo(currentVM.x, currentVM.y);
12908
13011
  lastDrawnIndex = index;
12909
13012
  }
@@ -13105,7 +13208,7 @@ module.exports = function(Chart) {
13105
13208
  // Implement this so that
13106
13209
  determineDataLimits: function() {
13107
13210
  var me = this;
13108
- var labels = me.getLabels();
13211
+ var labels = me.getLabels();
13109
13212
  me.minIndex = 0;
13110
13213
  me.maxIndex = labels.length - 1;
13111
13214
  var findIndex;
@@ -13143,7 +13246,7 @@ module.exports = function(Chart) {
13143
13246
  // 1 is added because we need the length but we have the indexes
13144
13247
  var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
13145
13248
 
13146
- if (value !== undefined) {
13249
+ if (value !== undefined && isNaN(index)) {
13147
13250
  var labels = me.getLabels();
13148
13251
  var idx = labels.indexOf(value);
13149
13252
  index = idx !== -1 ? idx : index;
@@ -13154,9 +13257,9 @@ module.exports = function(Chart) {
13154
13257
  var valueWidth = innerWidth / offsetAmt;
13155
13258
  var widthOffset = (valueWidth * (index - me.minIndex)) + me.paddingLeft;
13156
13259
 
13157
- if (me.options.gridLines.offsetGridLines && includeOffset) {
13260
+ if (me.options.gridLines.offsetGridLines && includeOffset || me.maxIndex === me.minIndex && includeOffset) {
13158
13261
  widthOffset += (valueWidth / 2);
13159
- }
13262
+ }
13160
13263
 
13161
13264
  return me.left + Math.round(widthOffset);
13162
13265
  } else {
@@ -13528,7 +13631,7 @@ module.exports = function(Chart) {
13528
13631
  me.zeroLineIndex = me.ticks.indexOf(0);
13529
13632
 
13530
13633
  Chart.Scale.prototype.convertTicksToLabels.call(me);
13531
- },
13634
+ }
13532
13635
  });
13533
13636
  };
13534
13637
  },{}],42:[function(require,module,exports){
@@ -13546,7 +13649,9 @@ module.exports = function(Chart) {
13546
13649
  callback: function(value, index, arr) {
13547
13650
  var remain = value / (Math.pow(10, Math.floor(helpers.log10(value))));
13548
13651
 
13549
- if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === arr.length - 1) {
13652
+ if (value === 0){
13653
+ return '0';
13654
+ } else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === arr.length - 1) {
13550
13655
  return value.toExponential();
13551
13656
  } else {
13552
13657
  return '';
@@ -13572,6 +13677,7 @@ module.exports = function(Chart) {
13572
13677
  // Calculate Range
13573
13678
  me.min = null;
13574
13679
  me.max = null;
13680
+ me.minNotZero = null;
13575
13681
 
13576
13682
  if (opts.stacked) {
13577
13683
  var valuesPerType = {};
@@ -13630,6 +13736,10 @@ module.exports = function(Chart) {
13630
13736
  } else if (value > me.max) {
13631
13737
  me.max = value;
13632
13738
  }
13739
+
13740
+ if(value !== 0 && (me.minNotZero === null || value < me.minNotZero)) {
13741
+ me.minNotZero = value;
13742
+ }
13633
13743
  });
13634
13744
  }
13635
13745
  });
@@ -13668,8 +13778,16 @@ module.exports = function(Chart) {
13668
13778
  while (tickVal < me.max) {
13669
13779
  ticks.push(tickVal);
13670
13780
 
13671
- var exp = Math.floor(helpers.log10(tickVal));
13672
- var significand = Math.floor(tickVal / Math.pow(10, exp)) + 1;
13781
+ var exp;
13782
+ var significand;
13783
+
13784
+ if(tickVal === 0){
13785
+ exp = Math.floor(helpers.log10(me.minNotZero));
13786
+ significand = Math.round(me.minNotZero / Math.pow(10, exp));
13787
+ } else {
13788
+ exp = Math.floor(helpers.log10(tickVal));
13789
+ significand = Math.floor(tickVal / Math.pow(10, exp)) + 1;
13790
+ }
13673
13791
 
13674
13792
  if (significand === 10) {
13675
13793
  significand = 1;
@@ -13721,13 +13839,15 @@ module.exports = function(Chart) {
13721
13839
 
13722
13840
  var start = me.start;
13723
13841
  var newVal = +me.getRightValue(value);
13724
- var range = helpers.log10(me.end) - helpers.log10(start);
13842
+ var range;
13725
13843
  var paddingTop = me.paddingTop;
13726
13844
  var paddingBottom = me.paddingBottom;
13727
13845
  var paddingLeft = me.paddingLeft;
13846
+ var opts = me.options;
13847
+ var tickOpts = opts.ticks;
13728
13848
 
13729
13849
  if (me.isHorizontal()) {
13730
-
13850
+ range = helpers.log10(me.end) - helpers.log10(start); // todo: if start === 0
13731
13851
  if (newVal === 0) {
13732
13852
  pixel = me.left + paddingLeft;
13733
13853
  } else {
@@ -13737,14 +13857,31 @@ module.exports = function(Chart) {
13737
13857
  }
13738
13858
  } else {
13739
13859
  // Bottom - top since pixels increase downard on a screen
13740
- if (newVal === 0) {
13741
- pixel = me.top + paddingTop;
13860
+ innerDimension = me.height - (paddingTop + paddingBottom);
13861
+ if(start === 0 && !tickOpts.reverse){
13862
+ range = helpers.log10(me.end) - helpers.log10(me.minNotZero);
13863
+ if (newVal === start) {
13864
+ pixel = me.bottom - paddingBottom;
13865
+ } else if(newVal === me.minNotZero){
13866
+ pixel = me.bottom - paddingBottom - innerDimension * 0.02;
13867
+ } else {
13868
+ pixel = me.bottom - paddingBottom - innerDimension * 0.02 - (innerDimension * 0.98/ range * (helpers.log10(newVal)-helpers.log10(me.minNotZero)));
13869
+ }
13870
+ } else if (me.end === 0 && tickOpts.reverse){
13871
+ range = helpers.log10(me.start) - helpers.log10(me.minNotZero);
13872
+ if (newVal === me.end) {
13873
+ pixel = me.top + paddingTop;
13874
+ } else if(newVal === me.minNotZero){
13875
+ pixel = me.top + paddingTop + innerDimension * 0.02;
13876
+ } else {
13877
+ pixel = me.top + paddingTop + innerDimension * 0.02 + (innerDimension * 0.98/ range * (helpers.log10(newVal)-helpers.log10(me.minNotZero)));
13878
+ }
13742
13879
  } else {
13880
+ range = helpers.log10(me.end) - helpers.log10(start);
13743
13881
  innerDimension = me.height - (paddingTop + paddingBottom);
13744
13882
  pixel = (me.bottom - paddingBottom) - (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));
13745
- }
13883
+ }
13746
13884
  }
13747
-
13748
13885
  return pixel;
13749
13886
  },
13750
13887
  getValueForPixel: function(pixel) {
@@ -13755,11 +13892,10 @@ module.exports = function(Chart) {
13755
13892
  if (me.isHorizontal()) {
13756
13893
  innerDimension = me.width - (me.paddingLeft + me.paddingRight);
13757
13894
  value = me.start * Math.pow(10, (pixel - me.left - me.paddingLeft) * range / innerDimension);
13758
- } else {
13895
+ } else { // todo: if start === 0
13759
13896
  innerDimension = me.height - (me.paddingTop + me.paddingBottom);
13760
13897
  value = Math.pow(10, (me.bottom - me.paddingBottom - pixel) * range / innerDimension) / me.start;
13761
13898
  }
13762
-
13763
13899
  return value;
13764
13900
  }
13765
13901
  });
@@ -14443,14 +14579,6 @@ module.exports = function(Chart) {
14443
14579
  me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true);
14444
14580
  }
14445
14581
 
14446
- me.smallestLabelSeparation = me.width;
14447
-
14448
- helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {
14449
- for (var i = 1; i < me.labelMoments[datasetIndex].length; i++) {
14450
- me.smallestLabelSeparation = Math.min(me.smallestLabelSeparation, me.labelMoments[datasetIndex][i].diff(me.labelMoments[datasetIndex][i - 1], me.tickUnit, true));
14451
- }
14452
- }, me);
14453
-
14454
14582
  // Tick displayFormat override
14455
14583
  if (me.options.time.displayFormat) {
14456
14584
  me.displayFormat = me.options.time.displayFormat;
@@ -14526,7 +14654,7 @@ module.exports = function(Chart) {
14526
14654
  var me = this;
14527
14655
  if (!value || !value.isValid) {
14528
14656
  // not already a moment object
14529
- value = moment(me.getRightValue(value));
14657
+ value = me.parseTime(me.getRightValue(value));
14530
14658
  }
14531
14659
  var labelMoment = value && value.isValid && value.isValid() ? value : me.getLabelMoment(datasetIndex, index);
14532
14660
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chartkick
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-11 00:00:00.000000000 Z
11
+ date: 2016-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -96,11 +96,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
96
  version: '0'
97
97
  requirements: []
98
98
  rubyforge_project:
99
- rubygems_version: 2.6.1
99
+ rubygems_version: 2.5.1
100
100
  signing_key:
101
101
  specification_version: 4
102
102
  summary: Create beautiful JavaScript charts with one line of Ruby
103
103
  test_files:
104
104
  - test/chartkick_test.rb
105
105
  - test/test_helper.rb
106
- has_rdoc: