<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The source code</title>
- <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
- <script type="text/javascript" src="../prettify/prettify.js"></script>
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
<style type="text/css">
.highlight { display: block; background-color: #ddd; }
</style>
</script>
</head>
<body onload="prettyPrint(); highlight();">
- <pre class="prettyprint lang-js"><span id='Ext-chart-axis-Time-method-constructor'><span id='Ext-chart-axis-Time'>/**
-</span></span> * @class Ext.chart.axis.Time
- * @extends Ext.chart.axis.Axis
+ <pre class="prettyprint lang-js"><span id='Ext-chart-axis-Time'>/**
+</span> * @class Ext.chart.axis.Time
+ * @extends Ext.chart.axis.Numeric
*
* A type of axis whose units are measured in time values. Use this axis
* for listing dates that you will want to group or dynamically change.
* fields: 'date',
* title: 'Day',
* dateFormat: 'M d',
- * groupBy: 'year,month,day',
- * aggregateOp: 'sum',
- *
+ *
* constrain: true,
* fromDate: new Date('1/1/11'),
* toDate: new Date('1/7/11')
* The time axis will show values for dates between `fromDate` and `toDate`.
* Since `constrain` is set to true all other values for other dates not between
* the fromDate and toDate will not be displayed.
- *
- * @constructor
+ *
*/
Ext.define('Ext.chart.axis.Time', {
/* Begin Definitions */
- extend: 'Ext.chart.axis.Category',
+ extend: 'Ext.chart.axis.Numeric',
alternateClassName: 'Ext.chart.TimeAxis',
/* End Definitions */
-<span id='Ext-chart-axis-Time-property-calculateByLabelSize'> /**
-</span> * The minimum value drawn by the axis. If not set explicitly, the axis
- * minimum will be calculated automatically.
- * @property calculateByLabelSize
- * @type Boolean
- */
- calculateByLabelSize: true,
-
-<span id='Ext-chart-axis-Time-property-dateFormat'> /**
-</span> * Indicates the format the date will be rendered on.
+<span id='Ext-chart-axis-Time-cfg-dateFormat'> /**
+</span> * @cfg {String/Boolean} dateFormat
+ * Indicates the format the date will be rendered on.
* For example: 'M d' will render the dates as 'Jan 30', etc.
- *
- * @property dateFormat
- * @type {String|Boolean}
- */
- dateFormat: false,
-
-<span id='Ext-chart-axis-Time-property-timeUnit'> /**
-</span> * Indicates the time unit to use for each step. Can be 'day', 'month', 'year' or a comma-separated combination of all of them.
- * Default's 'year,month,day'.
- *
- * @property timeUnit
- * @type {String}
+ * For a list of possible format strings see {@link Ext.Date Date}
*/
- groupBy: 'year,month,day',
-
-<span id='Ext-chart-axis-Time-property-aggregateOp'> /**
-</span> * Aggregation operation when grouping. Possible options are 'sum', 'avg', 'max', 'min'. Default's 'sum'.
- *
- * @property aggregateOp
- * @type {String}
- */
- aggregateOp: 'sum',
-
-<span id='Ext-chart-axis-Time-property-fromDate'> /**
-</span> * The starting date for the time axis.
- * @property fromDate
- * @type Date
+ dateFormat: false,
+
+<span id='Ext-chart-axis-Time-cfg-fromDate'> /**
+</span> * @cfg {Date} fromDate The starting date for the time axis.
*/
fromDate: false,
-
-<span id='Ext-chart-axis-Time-property-toDate'> /**
-</span> * The ending date for the time axis.
- * @property toDate
- * @type Date
+
+<span id='Ext-chart-axis-Time-cfg-toDate'> /**
+</span> * @cfg {Date} toDate The ending date for the time axis.
*/
toDate: false,
-
-<span id='Ext-chart-axis-Time-property-step'> /**
-</span> * An array with two components: The first is the unit of the step (day, month, year, etc). The second one is the number of units for the step (1, 2, etc.).
- * Default's [Ext.Date.DAY, 1].
- *
- * @property step
- * @type Array
+
+<span id='Ext-chart-axis-Time-cfg-step'> /**
+</span> * @cfg {Array/Boolean} step
+ * An array with two components: The first is the unit of the step (day, month, year, etc).
+ * The second one is the number of units for the step (1, 2, etc.).
+ * Defaults to `[Ext.Date.DAY, 1]`.
*/
step: [Ext.Date.DAY, 1],
-<span id='Ext-chart-axis-Time-property-constrain'> /**
-</span> * If true, the values of the chart will be rendered only if they belong between the fromDate and toDate.
+<span id='Ext-chart-axis-Time-cfg-constrain'> /**
+</span> * @cfg {Boolean} constrain
+ * If true, the values of the chart will be rendered only if they belong between the fromDate and toDate.
* If false, the time axis will adapt to the new values by adding/removing steps.
- * Default's [Ext.Date.DAY, 1].
- *
- * @property constrain
- * @type Boolean
*/
constrain: false,
-
- // @private a wrapper for date methods.
- dateMethods: {
- 'year': function(date) {
- return date.getFullYear();
- },
- 'month': function(date) {
- return date.getMonth() + 1;
- },
- 'day': function(date) {
- return date.getDate();
- },
- 'hour': function(date) {
- return date.getHours();
- },
- 'minute': function(date) {
- return date.getMinutes();
- },
- 'second': function(date) {
- return date.getSeconds();
- },
- 'millisecond': function(date) {
- return date.getMilliseconds();
- }
- },
-
- // @private holds aggregate functions.
- aggregateFn: (function() {
- var etype = (function() {
- var rgxp = /^\[object\s(.*)\]$/,
- toString = Object.prototype.toString;
- return function(e) {
- return toString.call(e).match(rgxp)[1];
- };
- })();
- return {
- 'sum': function(list) {
- var i = 0, l = list.length, acum = 0;
- if (!list.length || etype(list[0]) != 'Number') {
- return list[0];
- }
- for (; i < l; i++) {
- acum += list[i];
- }
- return acum;
- },
- 'max': function(list) {
- if (!list.length || etype(list[0]) != 'Number') {
- return list[0];
- }
- return Math.max.apply(Math, list);
- },
- 'min': function(list) {
- if (!list.length || etype(list[0]) != 'Number') {
- return list[0];
- }
- return Math.min.apply(Math, list);
- },
- 'avg': function(list) {
- var i = 0, l = list.length, acum = 0;
- if (!list.length || etype(list[0]) != 'Number') {
- return list[0];
- }
- for (; i < l; i++) {
- acum += list[i];
- }
- return acum / l;
- }
- };
- })(),
-
- // @private normalized the store to fill date gaps in the time interval.
- constrainDates: function() {
- var fromDate = Ext.Date.clone(this.fromDate),
- toDate = Ext.Date.clone(this.toDate),
- step = this.step,
- field = this.fields,
- store = this.chart.store,
- record, recObj, fieldNames = [],
- newStore = Ext.create('Ext.data.Store', {
- model: store.model
- });
-
- var getRecordByDate = (function() {
- var index = 0, l = store.getCount();
- return function(date) {
- var rec, recDate;
- for (; index < l; index++) {
- rec = store.getAt(index);
- recDate = rec.get(field);
- if (+recDate > +date) {
- return false;
- } else if (+recDate == +date) {
- return rec;
- }
- }
- return false;
- };
- })();
-
- if (!this.constrain) {
- this.chart.filteredStore = this.chart.store;
- return;
- }
- while(+fromDate <= +toDate) {
- record = getRecordByDate(fromDate);
- recObj = {};
- if (record) {
- newStore.add(record.data);
+ // Avoid roundtoDecimal call in Numeric Axis's constructor
+ roundToDecimal: false,
+
+ constructor: function (config) {
+ var me = this, label, f, df;
+ me.callParent([config]);
+ label = me.label || {};
+ df = this.dateFormat;
+ if (df) {
+ if (label.renderer) {
+ f = label.renderer;
+ label.renderer = function(v) {
+ v = f(v);
+ return Ext.Date.format(new Date(f(v)), df);
+ };
} else {
- newStore.model.prototype.fields.each(function(f) {
- recObj[f.name] = false;
- });
- recObj.date = fromDate;
- newStore.add(recObj);
+ label.renderer = function(v) {
+ return Ext.Date.format(new Date(v >> 0), df);
+ };
}
- fromDate = Ext.Date.add(fromDate, step[0], step[1]);
}
-
- this.chart.filteredStore = newStore;
},
-
- // @private aggregates values if multiple store elements belong to the same time step.
- aggregate: function() {
- var aggStore = {},
- aggKeys = [], key, value,
- op = this.aggregateOp,
- field = this.fields, i,
- fields = this.groupBy.split(','),
- curField,
- recFields = [],
- recFieldsLen = 0,
- obj,
- dates = [],
- json = [],
- l = fields.length,
- dateMethods = this.dateMethods,
- aggregateFn = this.aggregateFn,
- store = this.chart.filteredStore || this.chart.store;
-
- store.each(function(rec) {
- //get all record field names in a simple array
- if (!recFields.length) {
- rec.fields.each(function(f) {
- recFields.push(f.name);
- });
- recFieldsLen = recFields.length;
- }
- //get record date value
- value = rec.get(field);
- //generate key for grouping records
- for (i = 0; i < l; i++) {
- if (i == 0) {
- key = String(dateMethods[fields[i]](value));
- } else {
- key += '||' + dateMethods[fields[i]](value);
- }
- }
- //get aggregation record from hash
- if (key in aggStore) {
- obj = aggStore[key];
- } else {
- obj = aggStore[key] = {};
- aggKeys.push(key);
- dates.push(value);
- }
- //append record values to an aggregation record
- for (i = 0; i < recFieldsLen; i++) {
- curField = recFields[i];
- if (!obj[curField]) {
- obj[curField] = [];
- }
- if (rec.get(curField) !== undefined) {
- obj[curField].push(rec.get(curField));
+
+ doConstrain: function () {
+ var me = this,
+ store = me.chart.store,
+ data = [],
+ series = me.chart.series.items,
+ math = Math,
+ mmax = math.max,
+ mmin = math.min,
+ fields = me.fields,
+ ln = fields.length,
+ range = me.getRange(),
+ min = range.min, max = range.max, i, l, excludes = [],
+ value, values, rec, data = [];
+ for (i = 0, l = series.length; i < l; i++) {
+ excludes[i] = series[i].__excludes;
+ }
+ store.each(function(record) {
+ for (i = 0; i < ln; i++) {
+ if (excludes[i]) {
+ continue;
}
+ value = record.get(fields[i]);
+ if (+value < +min) return;
+ if (+value > +max) return;
}
- });
- //perform aggregation operations on fields
- for (key in aggStore) {
- obj = aggStore[key];
- for (i = 0; i < recFieldsLen; i++) {
- curField = recFields[i];
- obj[curField] = aggregateFn[op](obj[curField]);
- }
- json.push(obj);
- }
- this.chart.substore = Ext.create('Ext.data.JsonStore', {
- fields: recFields,
- data: json
- });
-
- this.dates = dates;
+ data.push(record);
+ })
+ me.chart.substore = Ext.create('Ext.data.JsonStore', { model: store.model, data: data });
},
-
- // @private creates a label array to be used as the axis labels.
- setLabels: function() {
- var store = this.chart.substore,
- fields = this.fields,
- format = this.dateFormat,
- labels, i, dates = this.dates,
- formatFn = Ext.Date.format;
- this.labels = labels = [];
- store.each(function(record, i) {
- if (!format) {
- labels.push(record.get(fields));
- } else {
- labels.push(formatFn(dates[i], format));
- }
- }, this);
- },
- processView: function() {
- //TODO(nico): fix this eventually...
- if (this.constrain) {
- this.constrainDates();
- this.aggregate();
- this.chart.substore = this.chart.filteredStore;
- } else {
- this.aggregate();
- }
- },
+ // Before rendering, set current default step count to be number of records.
+ processView: function () {
+ var me = this;
+ if (me.fromDate) {
+ me.minimum = +me.fromDate;
+ }
+ if (me.toDate) {
+ me.maximum = +me.toDate;
+ }
+ if (me.constrain) {
+ me.doConstrain();
+ }
+ },
- // @private modifies the store and creates the labels for the axes.
- applyData: function() {
- this.setLabels();
- var count = this.chart.substore.getCount();
- return {
- from: 0,
- to: count,
- steps: count - 1,
- step: 1
- };
- }
+ // @private modifies the store and creates the labels for the axes.
+ calcEnds: function() {
+ var me = this, range, step = me.step;
+ if (step) {
+ range = me.getRange();
+ range = Ext.draw.Draw.snapEndsByDateAndStep(new Date(range.min), new Date(range.max), Ext.isNumber(step) ? [Date.MILLI, step]: step);
+ if (me.minimum) {
+ range.from = me.minimum;
+ }
+ if (me.maximum) {
+ range.to = me.maximum;
+ }
+ range.step = (range.to - range.from) / range.steps;
+ return range;
+ } else {
+ return me.callParent(arguments);
+ }
+ }
});
</pre>