Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Series.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-chart-series-Series'>/**
19 </span> * @class Ext.chart.series.Series
20  *
21  * Series is the abstract class containing the common logic to all chart series. Series includes
22  * methods from Labels, Highlights, Tips and Callouts mixins. This class implements the logic of handling
23  * mouse events, animating, hiding, showing all elements and returning the color of the series to be used as a legend item.
24  *
25  * ## Listeners
26  *
27  * The series class supports listeners via the Observable syntax. Some of these listeners are:
28  *
29  *  - `itemmouseup` When the user interacts with a marker.
30  *  - `itemmousedown` When the user interacts with a marker.
31  *  - `itemmousemove` When the user iteracts with a marker.
32  *  - `afterrender` Will be triggered when the animation ends or when the series has been rendered completely.
33  *
34  * For example:
35  *
36  *     series: [{
37  *             type: 'column',
38  *             axis: 'left',
39  *             listeners: {
40  *                     'afterrender': function() {
41  *                             console('afterrender');
42  *                     }
43  *             },
44  *             xField: 'category',
45  *             yField: 'data1'
46  *     }]
47  */
48 Ext.define('Ext.chart.series.Series', {
49
50     /* Begin Definitions */
51
52     mixins: {
53         observable: 'Ext.util.Observable',
54         labels: 'Ext.chart.Label',
55         highlights: 'Ext.chart.Highlight',
56         tips: 'Ext.chart.Tip',
57         callouts: 'Ext.chart.Callout'
58     },
59
60     /* End Definitions */
61
62 <span id='Ext-chart-series-Series-cfg-highlight'>    /**
63 </span>     * @cfg {Boolean/Object} highlight
64      * If set to `true` it will highlight the markers or the series when hovering
65      * with the mouse. This parameter can also be an object with the same style
66      * properties you would apply to a {@link Ext.draw.Sprite} to apply custom
67      * styles to markers and series.
68      */
69
70 <span id='Ext-chart-series-Series-cfg-tips'>    /**
71 </span>     * @cfg {Object} tips
72      * Add tooltips to the visualization's markers. The options for the tips are the
73      * same configuration used with {@link Ext.tip.ToolTip}. For example:
74      *
75      *     tips: {
76      *       trackMouse: true,
77      *       width: 140,
78      *       height: 28,
79      *       renderer: function(storeItem, item) {
80      *         this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data1') + ' views');
81      *       }
82      *     },
83      */
84
85 <span id='Ext-chart-series-Series-cfg-type'>    /**
86 </span>     * @cfg {String} type
87      * The type of series. Set in subclasses.
88      */
89     type: null,
90
91 <span id='Ext-chart-series-Series-cfg-title'>    /**
92 </span>     * @cfg {String} title
93      * The human-readable name of the series.
94      */
95     title: null,
96
97 <span id='Ext-chart-series-Series-cfg-showInLegend'>    /**
98 </span>     * @cfg {Boolean} showInLegend
99      * Whether to show this series in the legend.
100      */
101     showInLegend: true,
102
103 <span id='Ext-chart-series-Series-cfg-renderer'>    /**
104 </span>     * @cfg {Function} renderer
105      * A function that can be overridden to set custom styling properties to each rendered element.
106      * Passes in (sprite, record, attributes, index, store) to the function.
107      */
108     renderer: function(sprite, record, attributes, index, store) {
109         return attributes;
110     },
111
112 <span id='Ext-chart-series-Series-cfg-shadowAttributes'>    /**
113 </span>     * @cfg {Array} shadowAttributes
114      * An array with shadow attributes
115      */
116     shadowAttributes: null,
117
118     //@private triggerdrawlistener flag
119     triggerAfterDraw: false,
120
121 <span id='Ext-chart-series-Series-cfg-listeners'>    /**
122 </span>     * @cfg {Object} listeners
123      * An (optional) object with event callbacks. All event callbacks get the target *item* as first parameter. The callback functions are:
124      *
125      *  - itemmouseover
126      *  - itemmouseout
127      *  - itemmousedown
128      *  - itemmouseup
129      */
130
131     constructor: function(config) {
132         var me = this;
133         if (config) {
134             Ext.apply(me, config);
135         }
136
137         me.shadowGroups = [];
138
139         me.mixins.labels.constructor.call(me, config);
140         me.mixins.highlights.constructor.call(me, config);
141         me.mixins.tips.constructor.call(me, config);
142         me.mixins.callouts.constructor.call(me, config);
143
144         me.addEvents({
145             scope: me,
146             itemmouseover: true,
147             itemmouseout: true,
148             itemmousedown: true,
149             itemmouseup: true,
150             mouseleave: true,
151             afterdraw: true,
152
153 <span id='Ext-chart-series-Series-event-titlechange'>            /**
154 </span>             * @event titlechange
155              * Fires when the series title is changed via {@link #setTitle}.
156              * @param {String} title The new title value
157              * @param {Number} index The index in the collection of titles
158              */
159             titlechange: true
160         });
161
162         me.mixins.observable.constructor.call(me, config);
163
164         me.on({
165             scope: me,
166             itemmouseover: me.onItemMouseOver,
167             itemmouseout: me.onItemMouseOut,
168             mouseleave: me.onMouseLeave
169         });
170     },
171     
172 <span id='Ext-chart-series-Series-method-eachRecord'>    /**
173 </span>     * Iterate over each of the records for this series. The default implementation simply iterates
174      * through the entire data store, but individual series implementations can override this to
175      * provide custom handling, e.g. adding/removing records.
176      * @param {Function} fn The function to execute for each record.
177      * @param {Object} scope Scope for the fn.
178      */
179     eachRecord: function(fn, scope) {
180         var chart = this.chart;
181         (chart.substore || chart.store).each(fn, scope);
182     },
183
184 <span id='Ext-chart-series-Series-method-getRecordCount'>    /**
185 </span>     * Return the number of records being displayed in this series. Defaults to the number of
186      * records in the store; individual series implementations can override to provide custom handling.
187      */
188     getRecordCount: function() {
189         var chart = this.chart,
190             store = chart.substore || chart.store;
191         return store ? store.getCount() : 0;
192     },
193
194 <span id='Ext-chart-series-Series-method-isExcluded'>    /**
195 </span>     * Determines whether the series item at the given index has been excluded, i.e. toggled off in the legend.
196      * @param index
197      */
198     isExcluded: function(index) {
199         var excludes = this.__excludes;
200         return !!(excludes &amp;&amp; excludes[index]);
201     },
202
203     // @private set the bbox and clipBox for the series
204     setBBox: function(noGutter) {
205         var me = this,
206             chart = me.chart,
207             chartBBox = chart.chartBBox,
208             gutterX = noGutter ? 0 : chart.maxGutter[0],
209             gutterY = noGutter ? 0 : chart.maxGutter[1],
210             clipBox, bbox;
211
212         clipBox = {
213             x: chartBBox.x,
214             y: chartBBox.y,
215             width: chartBBox.width,
216             height: chartBBox.height
217         };
218         me.clipBox = clipBox;
219
220         bbox = {
221             x: (clipBox.x + gutterX) - (chart.zoom.x * chart.zoom.width),
222             y: (clipBox.y + gutterY) - (chart.zoom.y * chart.zoom.height),
223             width: (clipBox.width - (gutterX * 2)) * chart.zoom.width,
224             height: (clipBox.height - (gutterY * 2)) * chart.zoom.height
225         };
226         me.bbox = bbox;
227     },
228
229     // @private set the animation for the sprite
230     onAnimate: function(sprite, attr) {
231         var me = this;
232         sprite.stopAnimation();
233         if (me.triggerAfterDraw) {
234             return sprite.animate(Ext.applyIf(attr, me.chart.animate));
235         } else {
236             me.triggerAfterDraw = true;
237             return sprite.animate(Ext.apply(Ext.applyIf(attr, me.chart.animate), {
238                 listeners: {
239                     'afteranimate': function() {
240                         me.triggerAfterDraw = false;
241                         me.fireEvent('afterrender');
242                     }
243                 }
244             }));
245         }
246     },
247
248     // @private return the gutter.
249     getGutters: function() {
250         return [0, 0];
251     },
252
253     // @private wrapper for the itemmouseover event.
254     onItemMouseOver: function(item) {
255         var me = this;
256         if (item.series === me) {
257             if (me.highlight) {
258                 me.highlightItem(item);
259             }
260             if (me.tooltip) {
261                 me.showTip(item);
262             }
263         }
264     },
265
266     // @private wrapper for the itemmouseout event.
267     onItemMouseOut: function(item) {
268         var me = this;
269         if (item.series === me) {
270             me.unHighlightItem();
271             if (me.tooltip) {
272                 me.hideTip(item);
273             }
274         }
275     },
276
277     // @private wrapper for the mouseleave event.
278     onMouseLeave: function() {
279         var me = this;
280         me.unHighlightItem();
281         if (me.tooltip) {
282             me.hideTip();
283         }
284     },
285
286 <span id='Ext-chart-series-Series-method-getItemForPoint'>    /**
287 </span>     * For a given x/y point relative to the Surface, find a corresponding item from this
288      * series, if any.
289      * @param {Number} x
290      * @param {Number} y
291      * @return {Object} An object describing the item, or null if there is no matching item.
292      * The exact contents of this object will vary by series type, but should always contain the following:
293      * @return {Ext.chart.series.Series} return.series the Series object to which the item belongs
294      * @return {Object} return.value the value(s) of the item's data point
295      * @return {Array} return.point the x/y coordinates relative to the chart box of a single point
296      * for this data item, which can be used as e.g. a tooltip anchor point.
297      * @return {Ext.draw.Sprite} return.sprite the item's rendering Sprite.
298      */
299     getItemForPoint: function(x, y) {
300         //if there are no items to query just return null.
301         if (!this.items || !this.items.length || this.seriesIsHidden) {
302             return null;
303         }
304         var me = this,
305             items = me.items,
306             bbox = me.bbox,
307             item, i, ln;
308         // Check bounds
309         if (!Ext.draw.Draw.withinBox(x, y, bbox)) {
310             return null;
311         }
312         for (i = 0, ln = items.length; i &lt; ln; i++) {
313             if (items[i] &amp;&amp; this.isItemInPoint(x, y, items[i], i)) {
314                 return items[i];
315             }
316         }
317
318         return null;
319     },
320
321     isItemInPoint: function(x, y, item, i) {
322         return false;
323     },
324
325 <span id='Ext-chart-series-Series-method-hideAll'>    /**
326 </span>     * Hides all the elements in the series.
327      */
328     hideAll: function() {
329         var me = this,
330             items = me.items,
331             item, len, i, j, l, sprite, shadows;
332
333         me.seriesIsHidden = true;
334         me._prevShowMarkers = me.showMarkers;
335
336         me.showMarkers = false;
337         //hide all labels
338         me.hideLabels(0);
339         //hide all sprites
340         for (i = 0, len = items.length; i &lt; len; i++) {
341             item = items[i];
342             sprite = item.sprite;
343             if (sprite) {
344                 sprite.setAttributes({
345                     hidden: true
346                 }, true);
347             }
348
349             if (sprite &amp;&amp; sprite.shadows) {
350                 shadows = sprite.shadows;
351                 for (j = 0, l = shadows.length; j &lt; l; ++j) {
352                     shadows[j].setAttributes({
353                         hidden: true
354                     }, true);
355                 }
356             }
357         }
358     },
359
360 <span id='Ext-chart-series-Series-method-showAll'>    /**
361 </span>     * Shows all the elements in the series.
362      */
363     showAll: function() {
364         var me = this,
365             prevAnimate = me.chart.animate;
366         me.chart.animate = false;
367         me.seriesIsHidden = false;
368         me.showMarkers = me._prevShowMarkers;
369         me.drawSeries();
370         me.chart.animate = prevAnimate;
371     },
372
373 <span id='Ext-chart-series-Series-method-getLegendColor'>    /**
374 </span>     * Returns a string with the color to be used for the series legend item.
375      */
376     getLegendColor: function(index) {
377         var me = this, fill, stroke;
378         if (me.seriesStyle) {
379             fill = me.seriesStyle.fill;
380             stroke = me.seriesStyle.stroke;
381             if (fill &amp;&amp; fill != 'none') {
382                 return fill;
383             }
384             return stroke;
385         }
386         return '#000';
387     },
388
389 <span id='Ext-chart-series-Series-method-visibleInLegend'>    /**
390 </span>     * Checks whether the data field should be visible in the legend
391      * @private
392      * @param {Number} index The index of the current item
393      */
394     visibleInLegend: function(index){
395         var excludes = this.__excludes;
396         if (excludes) {
397             return !excludes[index];
398         }
399         return !this.seriesIsHidden;
400     },
401
402 <span id='Ext-chart-series-Series-method-setTitle'>    /**
403 </span>     * Changes the value of the {@link #title} for the series.
404      * Arguments can take two forms:
405      * &lt;ul&gt;
406      * &lt;li&gt;A single String value: this will be used as the new single title for the series (applies
407      * to series with only one yField)&lt;/li&gt;
408      * &lt;li&gt;A numeric index and a String value: this will set the title for a single indexed yField.&lt;/li&gt;
409      * &lt;/ul&gt;
410      * @param {Number} index
411      * @param {String} title
412      */
413     setTitle: function(index, title) {
414         var me = this,
415             oldTitle = me.title;
416
417         if (Ext.isString(index)) {
418             title = index;
419             index = 0;
420         }
421
422         if (Ext.isArray(oldTitle)) {
423             oldTitle[index] = title;
424         } else {
425             me.title = title;
426         }
427
428         me.fireEvent('titlechange', title, index);
429     }
430 });
431 </pre>
432 </body>
433 </html>