diff --git a/src/chart.js b/src/chart.js index 8026cc856b7..49356868690 100644 --- a/src/chart.js +++ b/src/chart.js @@ -3,11 +3,10 @@ */ var Chart = require('./core/core')(); -require('./helpers/helpers.core')(Chart); -require('./helpers/helpers.easing')(Chart); +Chart.helpers = require('./helpers/index'); + +// @todo dispatch these helpers into appropriated helpers/helpers.* file and write unit tests! require('./core/core.helpers')(Chart); -require('./helpers/helpers.time')(Chart); -require('./helpers/helpers.canvas')(Chart); require('./platforms/platform')(Chart); require('./core/core.element')(Chart); @@ -66,3 +65,14 @@ module.exports = Chart; if (typeof window !== 'undefined') { window.Chart = Chart; } + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.helpers.canvas instead. + * @namespace Chart.canvasHelpers + * @deprecated since version 2.6.0 + * @todo remove at version 3 + * @private + */ +Chart.canvasHelpers = Chart.helpers.canvas; diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index c89631cb43d..93d285323c3 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -1,8 +1,8 @@ 'use strict'; -module.exports = function(Chart) { +var helpers = require('../helpers/index'); - var helpers = Chart.helpers; +module.exports = function(Chart) { Chart.defaults.bar = { hover: { diff --git a/src/controllers/controller.bubble.js b/src/controllers/controller.bubble.js index 3152cd09cfb..b91b15f1277 100644 --- a/src/controllers/controller.bubble.js +++ b/src/controllers/controller.bubble.js @@ -1,8 +1,8 @@ 'use strict'; -module.exports = function(Chart) { +var helpers = require('../helpers/index'); - var helpers = Chart.helpers; +module.exports = function(Chart) { Chart.defaults.bubble = { hover: { diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index e86eea26e16..c87c59bbcb0 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -1,9 +1,10 @@ 'use strict'; +var helpers = require('../helpers/index'); + module.exports = function(Chart) { - var helpers = Chart.helpers, - defaults = Chart.defaults; + var defaults = Chart.defaults; defaults.doughnut = { animation: { diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index 97982bded7c..c31e73f23d4 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -1,8 +1,8 @@ 'use strict'; -module.exports = function(Chart) { +var helpers = require('../helpers/index'); - var helpers = Chart.helpers; +module.exports = function(Chart) { Chart.defaults.line = { showLines: true, @@ -285,13 +285,13 @@ module.exports = function(Chart) { var ilen = points.length; var i = 0; - Chart.helpers.canvas.clipArea(chart.ctx, area); + helpers.canvas.clipArea(chart.ctx, area); if (lineEnabled(me.getDataset(), chart.options)) { meta.dataset.draw(); } - Chart.helpers.canvas.unclipArea(chart.ctx); + helpers.canvas.unclipArea(chart.ctx); // Draw the points for (; i= 0; i--) { - fn.call(thisArg, loopable[i], i); - } - } else { - for (i = 0; i < len; i++) { - fn.call(thisArg, loopable[i], i); - } - } - } else if (helpers.isObject(loopable)) { - keys = Object.keys(loopable); - len = keys.length; - for (i = 0; i < len; i++) { - fn.call(thisArg, loopable[keys[i]], keys[i]); - } - } - }, - - /** - * Returns true if the `a0` and `a1` arrays have the same content, else returns false. - * @see http://stackoverflow.com/a/14853974 - * @param {Array} a0 - The array to compare - * @param {Array} a1 - The array to compare - * @returns {Boolean} - */ - arrayEquals: function(a0, a1) { - var i, ilen, v0, v1; - - if (!a0 || !a1 || a0.length !== a1.length) { - return false; - } + noop: function() {}, - for (i = 0, ilen=a0.length; i < ilen; ++i) { - v0 = a0[i]; - v1 = a1[i]; - - if (v0 instanceof Array && v1 instanceof Array) { - if (!helpers.arrayEquals(v0, v1)) { - return false; - } - } else if (v0 !== v1) { - // NOTE: two different object instances will never be equal: {x:20} != {x:20} - return false; - } - } + /** + * Returns a unique id, sequentially generated from a global variable. + * @returns {Number} + * @function + */ + uid: (function() { + var id = 0; + return function() { + return id++; + }; + }()), - return true; - }, - - /** - * Returns a deep copy of `source` without keeping references on objects and arrays. - * @param {*} source - The value to clone. - * @returns {*} - */ - clone: function(source) { - if (helpers.isArray(source)) { - return source.map(helpers.clone); - } + /** + * Returns true if `value` is neither null nor undefined, else returns false. + * @param {*} value - The value to test. + * @returns {Boolean} + * @since 2.7.0 + */ + isNullOrUndef: function(value) { + return value === null || typeof value === 'undefined'; + }, - if (helpers.isObject(source)) { - var target = {}; - var keys = Object.keys(source); - var klen = keys.length; - var k = 0; + /** + * Returns true if `value` is an array, else returns false. + * @param {*} value - The value to test. + * @returns {Boolean} + * @function + */ + isArray: Array.isArray? Array.isArray : function(value) { + return Object.prototype.toString.call(value) === '[object Array]'; + }, - for (; k= 0; i--) { + fn.call(thisArg, loopable[i], i); + } } else { - target[key] = helpers.clone(sval); - } - }, - - /** - * Merges source[key] in target[key] only if target[key] is undefined. - * @private - */ - _mergerIf: function(key, target, source) { - var tval = target[key]; - var sval = source[key]; - - if (helpers.isObject(tval) && helpers.isObject(sval)) { - helpers.mergeIf(tval, sval); - } else if (!target.hasOwnProperty(key)) { - target[key] = helpers.clone(sval); + for (i = 0; i < len; i++) { + fn.call(thisArg, loopable[i], i); + } } - }, - - /** - * Recursively deep copies `source` properties into `target` with the given `options`. - * IMPORTANT: `target` is not cloned and will be updated with `source` properties. - * @param {Object} target - The target object in which all sources are merged into. - * @param {Object|Array(Object)} source - Object(s) to merge into `target`. - * @param {Object} [options] - Merging options: - * @param {Function} [options.merger] - The merge method (key, target, source, options) - * @returns {Object} The `target` object. - */ - merge: function(target, source, options) { - var sources = helpers.isArray(source)? source : [source]; - var ilen = sources.length; - var merge, i, keys, klen, k; - - if (!helpers.isObject(target)) { - return target; + } else if (helpers.isObject(loopable)) { + keys = Object.keys(loopable); + len = keys.length; + for (i = 0; i < len; i++) { + fn.call(thisArg, loopable[keys[i]], keys[i]); } + } + }, - options = options || {}; - merge = options.merger || helpers._merger; + /** + * Returns true if the `a0` and `a1` arrays have the same content, else returns false. + * @see http://stackoverflow.com/a/14853974 + * @param {Array} a0 - The array to compare + * @param {Array} a1 - The array to compare + * @returns {Boolean} + */ + arrayEquals: function(a0, a1) { + var i, ilen, v0, v1; - for (i=0; i maxTicks; i++) { + multiplier = unitDefinition.steps[i]; + sizeInUnits = Math.ceil(range / (unitSizeInMilliSeconds * multiplier)); } - - return null; - }, - - /** - * Determines how we scale the unit - * @param min {Number} the scale minimum - * @param max {Number} the scale maximum - * @param unit {String} the unit determined by the {@see determineUnit} method - * @return {Number} the axis step size as a multiple of unit - */ - determineStepSize: function(min, max, unit, maxTicks) { - // Using our unit, figure out what we need to scale as - var unitDefinition = interval[unit]; - var unitSizeInMilliSeconds = unitDefinition.size; - var sizeInUnits = Math.ceil((max - min) / unitSizeInMilliSeconds); - var multiplier = 1; - var range = max - min; - - if (unitDefinition.steps) { - // Have an array of steps - var numSteps = unitDefinition.steps.length; - for (var i = 0; i < numSteps && sizeInUnits > maxTicks; i++) { - multiplier = unitDefinition.steps[i]; - sizeInUnits = Math.ceil(range / (unitSizeInMilliSeconds * multiplier)); - } - } else { - while (sizeInUnits > maxTicks && maxTicks > 0) { - ++multiplier; - sizeInUnits = Math.ceil(range / (unitSizeInMilliSeconds * multiplier)); - } + } else { + while (sizeInUnits > maxTicks && maxTicks > 0) { + ++multiplier; + sizeInUnits = Math.ceil(range / (unitSizeInMilliSeconds * multiplier)); } + } - return multiplier; - }, + return multiplier; + }, - /** - * @function generateTicks - * @param options {ITimeGeneratorOptions} the options for generation - * @param dataRange {IRange} the data range - * @return {Number[]} ticks - */ - generateTicks: function(options, dataRange) { - var niceMin; - var niceMax; - var isoWeekday = options.timeOpts.isoWeekday; - if (options.unit === 'week' && isoWeekday !== false) { - niceMin = moment(dataRange.min).startOf('isoWeek').isoWeekday(isoWeekday).valueOf(); - niceMax = moment(dataRange.max).startOf('isoWeek').isoWeekday(isoWeekday); - if (dataRange.max - niceMax > 0) { - niceMax.add(1, 'week'); - } - niceMax = niceMax.valueOf(); - } else { - niceMin = moment(dataRange.min).startOf(options.unit).valueOf(); - niceMax = moment(dataRange.max).startOf(options.unit); - if (dataRange.max - niceMax > 0) { - niceMax.add(1, options.unit); - } - niceMax = niceMax.valueOf(); + /** + * @function generateTicks + * @param options {ITimeGeneratorOptions} the options for generation + * @param dataRange {IRange} the data range + * @return {Number[]} ticks + */ + generateTicks: function(options, dataRange) { + var niceMin; + var niceMax; + var isoWeekday = options.timeOpts.isoWeekday; + if (options.unit === 'week' && isoWeekday !== false) { + niceMin = moment(dataRange.min).startOf('isoWeek').isoWeekday(isoWeekday).valueOf(); + niceMax = moment(dataRange.max).startOf('isoWeek').isoWeekday(isoWeekday); + if (dataRange.max - niceMax > 0) { + niceMax.add(1, 'week'); + } + niceMax = niceMax.valueOf(); + } else { + niceMin = moment(dataRange.min).startOf(options.unit).valueOf(); + niceMax = moment(dataRange.max).startOf(options.unit); + if (dataRange.max - niceMax > 0) { + niceMax.add(1, options.unit); } - return generateTicksNiceRange(options, dataRange, { - min: niceMin, - max: niceMax - }); + niceMax = niceMax.valueOf(); } - - }; - + return generateTicksNiceRange(options, dataRange, { + min: niceMin, + max: niceMax + }); + } }; diff --git a/src/helpers/index.js b/src/helpers/index.js new file mode 100644 index 00000000000..a21c99aca13 --- /dev/null +++ b/src/helpers/index.js @@ -0,0 +1,6 @@ +'use strict'; + +module.exports = require('./helpers.core'); +module.exports.easing = require('./helpers.easing'); +module.exports.canvas = require('./helpers.canvas'); +module.exports.time = require('./helpers.time'); diff --git a/src/platforms/platform.dom.js b/src/platforms/platform.dom.js index a5345d1e76d..f8e328954bc 100644 --- a/src/platforms/platform.dom.js +++ b/src/platforms/platform.dom.js @@ -1,8 +1,9 @@ 'use strict'; +var helpers = require('../helpers/index'); + // Chart.Platform implementation for targeting a web browser -module.exports = function(Chart) { - var helpers = Chart.helpers; +module.exports = function() { // DOM event types -> Chart.js event types. // Note: only events with different types are mapped. diff --git a/src/platforms/platform.js b/src/platforms/platform.js index 0f27e5868a6..3464d5ff59c 100644 --- a/src/platforms/platform.js +++ b/src/platforms/platform.js @@ -1,8 +1,10 @@ 'use strict'; +var helpers = require('../helpers/index'); + // By default, select the browser (DOM) platform. // @TODO Make possible to select another platform at build time. -var implementation = require('./platform.dom.js'); +var implementation = require('./platform.dom'); module.exports = function(Chart) { /** @@ -65,5 +67,5 @@ module.exports = function(Chart) { * @prop {Number} y - The mouse y position, relative to the canvas (null for incompatible events) */ - Chart.helpers.extend(Chart.platform, implementation(Chart)); + helpers.extend(Chart.platform, implementation(Chart)); }; diff --git a/src/plugins/plugin.filler.js b/src/plugins/plugin.filler.js index 2a91d38e814..4f49064f084 100644 --- a/src/plugins/plugin.filler.js +++ b/src/plugins/plugin.filler.js @@ -1,5 +1,7 @@ 'use strict'; +var helpers = require('../helpers/index'); + module.exports = function(Chart) { /** * Plugin based on discussion from the following Chart.js issues: @@ -11,7 +13,6 @@ module.exports = function(Chart) { }; var defaults = Chart.defaults; - var helpers = Chart.helpers; var mappers = { dataset: function(source) { var index = source.fill; diff --git a/src/plugins/plugin.legend.js b/src/plugins/plugin.legend.js index 0e3b1e66530..3eb0f57dfcb 100644 --- a/src/plugins/plugin.legend.js +++ b/src/plugins/plugin.legend.js @@ -1,8 +1,9 @@ 'use strict'; +var helpers = require('../helpers/index'); + module.exports = function(Chart) { - var helpers = Chart.helpers; var layout = Chart.layoutService; var noop = helpers.noop; @@ -360,7 +361,7 @@ module.exports = function(Chart) { var centerY = y + offSet; // Draw pointStyle as legend symbol - Chart.helpers.canvas.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY); + helpers.canvas.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY); } else { // Draw box as legend symbol if (!isLineWidthZero) { diff --git a/src/plugins/plugin.title.js b/src/plugins/plugin.title.js index c8f815d763e..42ad1b0d3db 100644 --- a/src/plugins/plugin.title.js +++ b/src/plugins/plugin.title.js @@ -1,8 +1,9 @@ 'use strict'; +var helpers = require('../helpers/index'); + module.exports = function(Chart) { - var helpers = Chart.helpers; var layout = Chart.layoutService; var noop = helpers.noop; diff --git a/src/scales/scale.linear.js b/src/scales/scale.linear.js index c9a6af41ed3..34223c28383 100644 --- a/src/scales/scale.linear.js +++ b/src/scales/scale.linear.js @@ -1,8 +1,8 @@ 'use strict'; -module.exports = function(Chart) { +var helpers = require('../helpers/index'); - var helpers = Chart.helpers; +module.exports = function(Chart) { var defaultConfig = { position: 'left', diff --git a/src/scales/scale.linearbase.js b/src/scales/scale.linearbase.js index 28cde52d655..33bc22517bf 100644 --- a/src/scales/scale.linearbase.js +++ b/src/scales/scale.linearbase.js @@ -1,9 +1,10 @@ 'use strict'; +var helpers = require('../helpers/index'); + module.exports = function(Chart) { - var helpers = Chart.helpers, - noop = helpers.noop; + var noop = helpers.noop; Chart.LinearScaleBase = Chart.Scale.extend({ handleTickRangeOptions: function() { diff --git a/src/scales/scale.logarithmic.js b/src/scales/scale.logarithmic.js index a343aaf73b0..a5c5fa918a2 100644 --- a/src/scales/scale.logarithmic.js +++ b/src/scales/scale.logarithmic.js @@ -1,8 +1,8 @@ 'use strict'; -module.exports = function(Chart) { +var helpers = require('../helpers/index'); - var helpers = Chart.helpers; +module.exports = function(Chart) { var defaultConfig = { position: 'left', diff --git a/src/scales/scale.radialLinear.js b/src/scales/scale.radialLinear.js index 90cb52cd090..93036c691e5 100644 --- a/src/scales/scale.radialLinear.js +++ b/src/scales/scale.radialLinear.js @@ -1,8 +1,9 @@ 'use strict'; +var helpers = require('../helpers/index'); + module.exports = function(Chart) { - var helpers = Chart.helpers; var globalDefaults = Chart.defaults.global; var defaultConfig = { diff --git a/src/scales/scale.time.js b/src/scales/scale.time.js index 14621ba7a8b..fab5ccd6416 100644 --- a/src/scales/scale.time.js +++ b/src/scales/scale.time.js @@ -4,9 +4,10 @@ var moment = require('moment'); moment = typeof(moment) === 'function' ? moment : window.moment; +var helpers = require('../helpers/index'); + module.exports = function(Chart) { - var helpers = Chart.helpers; var timeHelpers = helpers.time; var defaultConfig = {