Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Time3.html
index 9ffc062..7e64fd3 100644 (file)
@@ -3,8 +3,8 @@
 <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>
@@ -17,7 +17,7 @@
 <body onload="prettyPrint(); highlight();">
   <pre class="prettyprint lang-js"><span id='Ext-chart-axis-Time'>/**
 </span> * @class Ext.chart.axis.Time
- * @extends Ext.chart.axis.Axis
+ * @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.
@@ -32,9 +32,7 @@
  *         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.
- * 
+ *
  */
 Ext.define('Ext.chart.axis.Time', {
 
     /* Begin Definitions */
 
-    extend: 'Ext.chart.axis.Category',
+    extend: 'Ext.chart.axis.Numeric',
 
     alternateClassName: 'Ext.chart.TimeAxis',
 
@@ -63,306 +61,124 @@ Ext.define('Ext.chart.axis.Time', {
 
     /* 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 &lt; 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 &lt; 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 &lt; l; index++) {
-                    rec = store.getAt(index);
-                    recDate = rec.get(field);
-                    if (+recDate &gt; +date) {
-                        return false;
-                    } else if (+recDate == +date) {
-                        return rec;
-                    }
-                }
-                return false;
-            };
-        })();
-        
-        if (!this.constrain) {
-            this.chart.filteredStore = this.chart.store;
-            return;
-        }
 
-        while(+fromDate &lt;= +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 &gt;&gt; 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 &lt; 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 &lt; 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 &lt; l; i++) {
+            excludes[i] = series[i].__excludes;
+        }
+        store.each(function(record) {
+            for (i = 0; i &lt; ln; i++) {
+                if (excludes[i]) {
+                    continue;
                 }
+                value = record.get(fields[i]);
+                if (+value &lt; +min) return;
+                if (+value &gt; +max) return;
             }
-        });
-        //perform aggregation operations on fields
-        for (key in aggStore) {
-            obj = aggStore[key];
-            for (i = 0; i &lt; 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>