4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-chart-axis-Time'>/**
19 </span> * @class Ext.chart.axis.Time
20 * @extends Ext.chart.axis.Axis
22 * A type of axis whose units are measured in time values. Use this axis
23 * for listing dates that you will want to group or dynamically change.
24 * If you just want to display dates as categories then use the
25 * Category class for axis instead.
35 * groupBy: 'year,month,day',
39 * fromDate: new Date('1/1/11'),
40 * toDate: new Date('1/7/11')
43 * In this example we're creating a time axis that has as title *Day*.
44 * The field the axis is bound to is `date`.
45 * The date format to use to display the text for the axis labels is `M d`
46 * which is a three letter month abbreviation followed by the day number.
47 * The time axis will show values for dates between `fromDate` and `toDate`.
48 * Since `constrain` is set to true all other values for other dates not between
49 * the fromDate and toDate will not be displayed.
52 Ext.define('Ext.chart.axis.Time', {
54 /* Begin Definitions */
56 extend: 'Ext.chart.axis.Category',
58 alternateClassName: 'Ext.chart.TimeAxis',
62 requires: ['Ext.data.Store', 'Ext.data.JsonStore'],
66 <span id='Ext-chart-axis-Time-property-calculateByLabelSize'> /**
67 </span> * The minimum value drawn by the axis. If not set explicitly, the axis
68 * minimum will be calculated automatically.
69 * @property calculateByLabelSize
72 calculateByLabelSize: true,
74 <span id='Ext-chart-axis-Time-property-dateFormat'> /**
75 </span> * Indicates the format the date will be rendered on.
76 * For example: 'M d' will render the dates as 'Jan 30', etc.
78 * @property dateFormat
79 * @type {String|Boolean}
83 <span id='Ext-chart-axis-Time-property-timeUnit'> /**
84 </span> * Indicates the time unit to use for each step. Can be 'day', 'month', 'year' or a comma-separated combination of all of them.
85 * Default's 'year,month,day'.
90 groupBy: 'year,month,day',
92 <span id='Ext-chart-axis-Time-property-aggregateOp'> /**
93 </span> * Aggregation operation when grouping. Possible options are 'sum', 'avg', 'max', 'min'. Default's 'sum'.
95 * @property aggregateOp
100 <span id='Ext-chart-axis-Time-property-fromDate'> /**
101 </span> * The starting date for the time axis.
107 <span id='Ext-chart-axis-Time-property-toDate'> /**
108 </span> * The ending date for the time axis.
114 <span id='Ext-chart-axis-Time-property-step'> /**
115 </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.).
116 * Default's [Ext.Date.DAY, 1].
121 step: [Ext.Date.DAY, 1],
123 <span id='Ext-chart-axis-Time-property-constrain'> /**
124 </span> * If true, the values of the chart will be rendered only if they belong between the fromDate and toDate.
125 * If false, the time axis will adapt to the new values by adding/removing steps.
126 * Default's [Ext.Date.DAY, 1].
128 * @property constrain
133 // @private a wrapper for date methods.
135 'year': function(date) {
136 return date.getFullYear();
138 'month': function(date) {
139 return date.getMonth() + 1;
141 'day': function(date) {
142 return date.getDate();
144 'hour': function(date) {
145 return date.getHours();
147 'minute': function(date) {
148 return date.getMinutes();
150 'second': function(date) {
151 return date.getSeconds();
153 'millisecond': function(date) {
154 return date.getMilliseconds();
158 // @private holds aggregate functions.
159 aggregateFn: (function() {
160 var etype = (function() {
161 var rgxp = /^\[object\s(.*)\]$/,
162 toString = Object.prototype.toString;
164 return toString.call(e).match(rgxp)[1];
168 'sum': function(list) {
169 var i = 0, l = list.length, acum = 0;
170 if (!list.length || etype(list[0]) != 'Number') {
173 for (; i < l; i++) {
178 'max': function(list) {
179 if (!list.length || etype(list[0]) != 'Number') {
182 return Math.max.apply(Math, list);
184 'min': function(list) {
185 if (!list.length || etype(list[0]) != 'Number') {
188 return Math.min.apply(Math, list);
190 'avg': function(list) {
191 var i = 0, l = list.length, acum = 0;
192 if (!list.length || etype(list[0]) != 'Number') {
195 for (; i < l; i++) {
203 // @private normalized the store to fill date gaps in the time interval.
204 constrainDates: function() {
205 var fromDate = Ext.Date.clone(this.fromDate),
206 toDate = Ext.Date.clone(this.toDate),
209 store = this.chart.store,
210 record, recObj, fieldNames = [],
211 newStore = Ext.create('Ext.data.Store', {
215 var getRecordByDate = (function() {
216 var index = 0, l = store.getCount();
217 return function(date) {
219 for (; index < l; index++) {
220 rec = store.getAt(index);
221 recDate = rec.get(field);
222 if (+recDate > +date) {
224 } else if (+recDate == +date) {
232 if (!this.constrain) {
233 this.chart.filteredStore = this.chart.store;
237 while(+fromDate <= +toDate) {
238 record = getRecordByDate(fromDate);
241 newStore.add(record.data);
243 newStore.model.prototype.fields.each(function(f) {
244 recObj[f.name] = false;
246 recObj.date = fromDate;
247 newStore.add(recObj);
249 fromDate = Ext.Date.add(fromDate, step[0], step[1]);
252 this.chart.filteredStore = newStore;
255 // @private aggregates values if multiple store elements belong to the same time step.
256 aggregate: function() {
258 aggKeys = [], key, value,
259 op = this.aggregateOp,
260 field = this.fields, i,
261 fields = this.groupBy.split(','),
269 dateMethods = this.dateMethods,
270 aggregateFn = this.aggregateFn,
271 store = this.chart.filteredStore || this.chart.store;
273 store.each(function(rec) {
274 //get all record field names in a simple array
275 if (!recFields.length) {
276 rec.fields.each(function(f) {
277 recFields.push(f.name);
279 recFieldsLen = recFields.length;
281 //get record date value
282 value = rec.get(field);
283 //generate key for grouping records
284 for (i = 0; i < l; i++) {
286 key = String(dateMethods[fields[i]](value));
288 key += '||' + dateMethods[fields[i]](value);
291 //get aggregation record from hash
292 if (key in aggStore) {
295 obj = aggStore[key] = {};
299 //append record values to an aggregation record
300 for (i = 0; i < recFieldsLen; i++) {
301 curField = recFields[i];
302 if (!obj[curField]) {
305 if (rec.get(curField) !== undefined) {
306 obj[curField].push(rec.get(curField));
310 //perform aggregation operations on fields
311 for (key in aggStore) {
313 for (i = 0; i < recFieldsLen; i++) {
314 curField = recFields[i];
315 obj[curField] = aggregateFn[op](obj[curField]);
319 this.chart.substore = Ext.create('Ext.data.JsonStore', {
327 // @private creates a label array to be used as the axis labels.
328 setLabels: function() {
329 var store = this.chart.substore,
330 fields = this.fields,
331 format = this.dateFormat,
332 labels, i, dates = this.dates,
333 formatFn = Ext.Date.format;
334 this.labels = labels = [];
335 store.each(function(record, i) {
337 labels.push(record.get(fields));
339 labels.push(formatFn(dates[i], format));
344 processView: function() {
345 //TODO(nico): fix this eventually...
346 if (this.constrain) {
347 this.constrainDates();
349 this.chart.substore = this.chart.filteredStore;
355 // @private modifies the store and creates the labels for the axes.
356 applyData: function() {
358 var count = this.chart.substore.getCount();