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-method-constructor'><span id='Ext-chart-axis-Time'>/**
19 </span></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.
53 Ext.define('Ext.chart.axis.Time', {
55 /* Begin Definitions */
57 extend: 'Ext.chart.axis.Category',
59 alternateClassName: 'Ext.chart.TimeAxis',
63 requires: ['Ext.data.Store', 'Ext.data.JsonStore'],
67 <span id='Ext-chart-axis-Time-property-calculateByLabelSize'> /**
68 </span> * The minimum value drawn by the axis. If not set explicitly, the axis
69 * minimum will be calculated automatically.
70 * @property calculateByLabelSize
73 calculateByLabelSize: true,
75 <span id='Ext-chart-axis-Time-property-dateFormat'> /**
76 </span> * Indicates the format the date will be rendered on.
77 * For example: 'M d' will render the dates as 'Jan 30', etc.
79 * @property dateFormat
80 * @type {String|Boolean}
84 <span id='Ext-chart-axis-Time-property-timeUnit'> /**
85 </span> * Indicates the time unit to use for each step. Can be 'day', 'month', 'year' or a comma-separated combination of all of them.
86 * Default's 'year,month,day'.
91 groupBy: 'year,month,day',
93 <span id='Ext-chart-axis-Time-property-aggregateOp'> /**
94 </span> * Aggregation operation when grouping. Possible options are 'sum', 'avg', 'max', 'min'. Default's 'sum'.
96 * @property aggregateOp
101 <span id='Ext-chart-axis-Time-property-fromDate'> /**
102 </span> * The starting date for the time axis.
108 <span id='Ext-chart-axis-Time-property-toDate'> /**
109 </span> * The ending date for the time axis.
115 <span id='Ext-chart-axis-Time-property-step'> /**
116 </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.).
117 * Default's [Ext.Date.DAY, 1].
122 step: [Ext.Date.DAY, 1],
124 <span id='Ext-chart-axis-Time-property-constrain'> /**
125 </span> * If true, the values of the chart will be rendered only if they belong between the fromDate and toDate.
126 * If false, the time axis will adapt to the new values by adding/removing steps.
127 * Default's [Ext.Date.DAY, 1].
129 * @property constrain
134 // @private a wrapper for date methods.
136 'year': function(date) {
137 return date.getFullYear();
139 'month': function(date) {
140 return date.getMonth() + 1;
142 'day': function(date) {
143 return date.getDate();
145 'hour': function(date) {
146 return date.getHours();
148 'minute': function(date) {
149 return date.getMinutes();
151 'second': function(date) {
152 return date.getSeconds();
154 'millisecond': function(date) {
155 return date.getMilliseconds();
159 // @private holds aggregate functions.
160 aggregateFn: (function() {
161 var etype = (function() {
162 var rgxp = /^\[object\s(.*)\]$/,
163 toString = Object.prototype.toString;
165 return toString.call(e).match(rgxp)[1];
169 'sum': function(list) {
170 var i = 0, l = list.length, acum = 0;
171 if (!list.length || etype(list[0]) != 'Number') {
174 for (; i < l; i++) {
179 'max': function(list) {
180 if (!list.length || etype(list[0]) != 'Number') {
183 return Math.max.apply(Math, list);
185 'min': function(list) {
186 if (!list.length || etype(list[0]) != 'Number') {
189 return Math.min.apply(Math, list);
191 'avg': function(list) {
192 var i = 0, l = list.length, acum = 0;
193 if (!list.length || etype(list[0]) != 'Number') {
196 for (; i < l; i++) {
204 // @private normalized the store to fill date gaps in the time interval.
205 constrainDates: function() {
206 var fromDate = Ext.Date.clone(this.fromDate),
207 toDate = Ext.Date.clone(this.toDate),
210 store = this.chart.store,
211 record, recObj, fieldNames = [],
212 newStore = Ext.create('Ext.data.Store', {
216 var getRecordByDate = (function() {
217 var index = 0, l = store.getCount();
218 return function(date) {
220 for (; index < l; index++) {
221 rec = store.getAt(index);
222 recDate = rec.get(field);
223 if (+recDate > +date) {
225 } else if (+recDate == +date) {
233 if (!this.constrain) {
234 this.chart.filteredStore = this.chart.store;
238 while(+fromDate <= +toDate) {
239 record = getRecordByDate(fromDate);
242 newStore.add(record.data);
244 newStore.model.prototype.fields.each(function(f) {
245 recObj[f.name] = false;
247 recObj.date = fromDate;
248 newStore.add(recObj);
250 fromDate = Ext.Date.add(fromDate, step[0], step[1]);
253 this.chart.filteredStore = newStore;
256 // @private aggregates values if multiple store elements belong to the same time step.
257 aggregate: function() {
259 aggKeys = [], key, value,
260 op = this.aggregateOp,
261 field = this.fields, i,
262 fields = this.groupBy.split(','),
270 dateMethods = this.dateMethods,
271 aggregateFn = this.aggregateFn,
272 store = this.chart.filteredStore || this.chart.store;
274 store.each(function(rec) {
275 //get all record field names in a simple array
276 if (!recFields.length) {
277 rec.fields.each(function(f) {
278 recFields.push(f.name);
280 recFieldsLen = recFields.length;
282 //get record date value
283 value = rec.get(field);
284 //generate key for grouping records
285 for (i = 0; i < l; i++) {
287 key = String(dateMethods[fields[i]](value));
289 key += '||' + dateMethods[fields[i]](value);
292 //get aggregation record from hash
293 if (key in aggStore) {
296 obj = aggStore[key] = {};
300 //append record values to an aggregation record
301 for (i = 0; i < recFieldsLen; i++) {
302 curField = recFields[i];
303 if (!obj[curField]) {
306 if (rec.get(curField) !== undefined) {
307 obj[curField].push(rec.get(curField));
311 //perform aggregation operations on fields
312 for (key in aggStore) {
314 for (i = 0; i < recFieldsLen; i++) {
315 curField = recFields[i];
316 obj[curField] = aggregateFn[op](obj[curField]);
320 this.chart.substore = Ext.create('Ext.data.JsonStore', {
328 // @private creates a label array to be used as the axis labels.
329 setLabels: function() {
330 var store = this.chart.substore,
331 fields = this.fields,
332 format = this.dateFormat,
333 labels, i, dates = this.dates,
334 formatFn = Ext.Date.format;
335 this.labels = labels = [];
336 store.each(function(record, i) {
338 labels.push(record.get(fields));
340 labels.push(formatFn(dates[i], format));
345 processView: function() {
346 //TODO(nico): fix this eventually...
347 if (this.constrain) {
348 this.constrainDates();
350 this.chart.substore = this.chart.filteredStore;
356 // @private modifies the store and creates the labels for the axes.
357 applyData: function() {
359 var count = this.chart.substore.getCount();