2
YUI 3.10.3 (build 2fb5187)
3
Copyright 2013 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
8
YUI.add('axis-numeric-base', function (Y, NAME) {
11
* Provides functionality for the handling of numeric axis data for a chart.
14
* @submodule axis-numeric-base
18
* NumericImpl contains logic for numeric data. NumericImpl is used by the following classes:
20
* <li>{{#crossLink "NumericAxisBase"}}{{/crossLink}}</li>
21
* <li>{{#crossLink "NumericAxis"}}{{/crossLink}}</li>
26
* @submodule axis-numeric-base
28
function NumericImpl()
32
NumericImpl.NAME = "numericImpl";
36
* Indicates whether 0 should always be displayed.
38
* @attribute alwaysShowZero
46
* Method used for formatting a label. This attribute allows for the default label formatting method to overridden.
47
* The method use would need to implement the arguments below and return a `String` or an `HTMLElement`. The default
48
* implementation of the method returns a `String`. The output of this method will be rendered to the DOM using
49
* `appendChild`. If you override the `labelFunction` method and return an html string, you will also need to override
50
* the Data' `appendLabelFunction` to accept html as a `String`.
52
* <dt>val</dt><dd>Label to be formatted. (`String`)</dd>
53
* <dt>format</dt><dd>Object containing properties used to format the label. (optional)</dd>
56
* @attribute labelFunction
61
* Object containing properties used by the `labelFunction` to format a
64
* @attribute labelFormat
70
thousandsSeparator: "",
78
*Indicates how to round unit values.
80
* <dt>niceNumber</dt><dd>Units will be smoothed based on the number of ticks and data range.</dd>
81
* <dt>auto</dt><dd>If the range is greater than 1, the units will be rounded.</dd>
82
* <dt>numeric value</dt><dd>Units will be equal to the numeric value.</dd>
83
* <dt>null</dt><dd>No rounding will occur.</dd>
86
* @attribute roundingMethod
95
NumericImpl.prototype = {
100
initializer: function() {
101
this.after("alwaysShowZeroChange", this._keyChangeHandler);
102
this.after("roundingMethodChange", this._keyChangeHandler);
106
* Formats a label based on the axis type and optionally specified format.
109
* @param {Object} value
110
* @param {Object} format Pattern used to format the value.
113
formatLabel: function(val, format)
117
return Y.DataType.Number.format(val, format);
123
* Returns the sum of all values per key.
125
* @method getTotalByKey
126
* @param {String} key The identifier for the array whose values will be calculated.
129
getTotalByKey: function(key)
132
values = this.getDataByKey(key),
135
len = values ? values.length : 0;
138
val = parseFloat(values[i]);
148
* Type of data used in `Data`.
157
* Helper method for getting a `roundingUnit` when calculating the minimum and maximum values.
159
* @method _getMinimumUnit
160
* @param {Number} max Maximum number
161
* @param {Number} min Minimum number
162
* @param {Number} units Number of units on the axis
166
_getMinimumUnit:function(max, min, units)
168
return this._getNiceNumber(Math.ceil((max - min)/units));
172
* Calculates a nice rounding unit based on the range.
174
* @method _getNiceNumber
175
* @param {Number} roundingUnit The calculated rounding unit.
179
_getNiceNumber: function(roundingUnit)
181
var tempMajorUnit = roundingUnit,
182
order = Math.ceil(Math.log(tempMajorUnit) * 0.4342944819032518),
183
roundedMajorUnit = Math.pow(10, order),
186
if (roundedMajorUnit / 2 >= tempMajorUnit)
188
roundedDiff = Math.floor((roundedMajorUnit / 2 - tempMajorUnit) / (Math.pow(10,order-1)/2));
189
tempMajorUnit = roundedMajorUnit/2 - roundedDiff*Math.pow(10,order-1)/2;
193
tempMajorUnit = roundedMajorUnit;
195
if(!isNaN(tempMajorUnit))
197
return tempMajorUnit;
204
* Calculates the maximum and minimum values for the `Data`.
206
* @method _updateMinAndMax
209
_updateMinAndMax: function()
211
var data = this.get("data"),
217
setMax = this.get("setMax"),
218
setMin = this.get("setMin");
219
if(!setMax || !setMin)
221
if(data && data.length && data.length > 0)
229
max = setMax ? this._setMaximum : max;
230
min = setMin ? this._setMinimum : min;
236
min = this._setMinimum;
238
else if(min === undefined)
244
min = Math.min(num, min);
248
max = this._setMaximum;
250
else if(max === undefined)
256
max = Math.max(num, max);
259
this._actualMaximum = max;
260
this._actualMinimum = min;
263
this._roundMinAndMax(min, max, setMin, setMax);
268
* Rounds the mimimum and maximum values based on the `roundingUnit` attribute.
270
* @method _roundMinAndMax
271
* @param {Number} min Minimum value
272
* @param {Number} max Maximum value
275
_roundMinAndMax: function(min, max, setMin, setMax)
279
minGreaterThanZero = min >= 0,
280
maxGreaterThanZero = max > 0,
288
units = this.getTotalMajorUnits() - 1,
289
alwaysShowZero = this.get("alwaysShowZero"),
290
roundingMethod = this.get("roundingMethod"),
291
useIntegers = (max - min)/units >= 1;
294
if(roundingMethod === "niceNumber")
296
roundingUnit = this._getMinimumUnit(max, min, units);
297
if(minGreaterThanZero && maxGreaterThanZero)
299
if((alwaysShowZero || min < roundingUnit) && !setMin)
302
roundingUnit = this._getMinimumUnit(max, min, units);
306
min = this._roundDownToNearest(min, roundingUnit);
312
min = max - (roundingUnit * units);
317
max = min + (roundingUnit * units);
321
max = this._roundUpToNearest(max, roundingUnit);
324
else if(maxGreaterThanZero && !minGreaterThanZero)
328
topTicks = Math.round(units/((-1 * min)/max + 1));
329
topTicks = Math.max(Math.min(topTicks, units - 1), 1);
330
botTicks = units - topTicks;
331
tempMax = Math.ceil( max/topTicks );
332
tempMin = Math.floor( min/botTicks ) * -1;
336
while(tempMin < tempMax && botTicks >= 0)
340
tempMax = Math.ceil( max/topTicks );
341
tempMin = Math.floor( min/botTicks ) * -1;
343
//if there are any bottom ticks left calcualate the maximum by multiplying by the tempMin value
344
//if not, it's impossible to ensure that a zero is shown. skip it
347
max = tempMin * topTicks;
351
max = min + (roundingUnit * units);
356
while(tempMax < tempMin && topTicks >= 0)
360
tempMin = Math.floor( min/botTicks ) * -1;
361
tempMax = Math.ceil( max/topTicks );
363
//if there are any top ticks left calcualate the minimum by multiplying by the tempMax value
364
//if not, it's impossible to ensure that a zero is shown. skip it
367
min = tempMax * botTicks * -1;
371
min = max - (roundingUnit * units);
376
roundingUnit = Math.max(tempMax, tempMin);
377
roundingUnit = this._getNiceNumber(roundingUnit);
378
max = roundingUnit * topTicks;
379
min = roundingUnit * botTicks * -1;
386
min = max - (roundingUnit * units);
390
max = min + (roundingUnit * units);
394
min = this._roundDownToNearest(min, roundingUnit);
395
max = this._roundUpToNearest(max, roundingUnit);
409
max = min + (roundingUnit * units);
414
if(alwaysShowZero || max === 0 || max + roundingUnit > 0)
417
roundingUnit = this._getMinimumUnit(max, min, units);
418
min = max - (roundingUnit * units);
422
min = this._roundDownToNearest(min, roundingUnit);
423
max = this._roundUpToNearest(max, roundingUnit);
428
min = max - (roundingUnit * units);
432
else if(roundingMethod === "auto")
434
if(minGreaterThanZero && maxGreaterThanZero)
436
if((alwaysShowZero || min < (max-min)/units) && !setMin)
441
roundingUnit = (max - min)/units;
444
roundingUnit = Math.ceil(roundingUnit);
445
max = min + (roundingUnit * units);
449
max = min + Math.ceil(roundingUnit * units * 100000)/100000;
453
else if(maxGreaterThanZero && !minGreaterThanZero)
457
topTicks = Math.round( units / ( (-1 * min) /max + 1) );
458
topTicks = Math.max(Math.min(topTicks, units - 1), 1);
459
botTicks = units - topTicks;
463
tempMax = Math.ceil( max/topTicks );
464
tempMin = Math.floor( min/botTicks ) * -1;
465
roundingUnit = Math.max(tempMax, tempMin);
466
max = roundingUnit * topTicks;
467
min = roundingUnit * botTicks * -1;
471
tempMax = max/topTicks;
472
tempMin = min/botTicks * -1;
473
roundingUnit = Math.max(tempMax, tempMin);
474
max = Math.ceil(roundingUnit * topTicks * 100000)/100000;
475
min = Math.ceil(roundingUnit * botTicks * 100000)/100000 * -1;
480
roundingUnit = (max - min)/units;
483
roundingUnit = Math.ceil(roundingUnit);
485
min = Math.round(this._roundDownToNearest(min, roundingUnit) * 100000)/100000;
486
max = Math.round(this._roundUpToNearest(max, roundingUnit) * 100000)/100000;
491
roundingUnit = (max - min)/units;
494
roundingUnit = Math.ceil(roundingUnit);
496
if(alwaysShowZero || max === 0 || max + roundingUnit > 0)
499
roundingUnit = (max - min)/units;
502
Math.ceil(roundingUnit);
503
min = max - (roundingUnit * units);
507
min = max - Math.ceil(roundingUnit * units * 100000)/100000;
512
min = this._roundDownToNearest(min, roundingUnit);
513
max = this._roundUpToNearest(max, roundingUnit);
518
else if(!isNaN(roundingMethod) && isFinite(roundingMethod))
520
roundingUnit = roundingMethod;
521
minimumRange = roundingUnit * units;
522
dataRangeGreater = (max - min) > minimumRange;
523
minRound = this._roundDownToNearest(min, roundingUnit);
524
maxRound = this._roundUpToNearest(max, roundingUnit);
527
min = max - minimumRange;
531
max = min + minimumRange;
533
else if(minGreaterThanZero && maxGreaterThanZero)
535
if(alwaysShowZero || minRound <= 0)
543
max = min + minimumRange;
545
else if(maxGreaterThanZero && !minGreaterThanZero)
552
if(alwaysShowZero || maxRound >= 0)
560
min = max - minimumRange;
564
this._dataMaximum = max;
565
this._dataMinimum = min;
569
* Rounds a Number to the nearest multiple of an input. For example, by rounding
570
* 16 to the nearest 10, you will receive 20. Similar to the built-in function Math.round().
572
* @method _roundToNearest
573
* @param {Number} number Number to round
574
* @param {Number} nearest Multiple to round towards.
578
_roundToNearest: function(number, nearest)
580
nearest = nearest || 1;
581
var roundedNumber = Math.round(this._roundToPrecision(number / nearest, 10)) * nearest;
582
return this._roundToPrecision(roundedNumber, 10);
586
* Rounds a Number up to the nearest multiple of an input. For example, by rounding
587
* 16 up to the nearest 10, you will receive 20. Similar to the built-in function Math.ceil().
589
* @method _roundUpToNearest
590
* @param {Number} number Number to round
591
* @param {Number} nearest Multiple to round towards.
595
_roundUpToNearest: function(number, nearest)
597
nearest = nearest || 1;
598
return Math.ceil(this._roundToPrecision(number / nearest, 10)) * nearest;
602
* Rounds a Number down to the nearest multiple of an input. For example, by rounding
603
* 16 down to the nearest 10, you will receive 10. Similar to the built-in function Math.floor().
605
* @method _roundDownToNearest
606
* @param {Number} number Number to round
607
* @param {Number} nearest Multiple to round towards.
611
_roundDownToNearest: function(number, nearest)
613
nearest = nearest || 1;
614
return Math.floor(this._roundToPrecision(number / nearest, 10)) * nearest;
618
* Rounds a number to a certain level of precision. Useful for limiting the number of
619
* decimal places on a fractional number.
621
* @method _roundToPrecision
622
* @param {Number} number Number to round
623
* @param {Number} precision Multiple to round towards.
627
_roundToPrecision: function(number, precision)
629
precision = precision || 0;
630
var decimalPlaces = Math.pow(10, precision);
631
return Math.round(decimalPlaces * number) / decimalPlaces;
635
Y.NumericImpl = NumericImpl;
638
* NumericAxisBase manages numeric data for an axis.
640
* @class NumericAxisBase
644
* @param {Object} config (optional) Configuration parameters.
645
* @submodule axis-numeric-base
647
Y.NumericAxisBase = Y.Base.create("numericAxisBase", Y.AxisBase, [Y.NumericImpl]);
650
}, '3.10.3', {"requires": ["axis-base"]});