3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.chart.series.Series
18 * Series is the abstract class containing the common logic to all chart series. Series includes
19 * methods from Labels, Highlights, Tips and Callouts mixins. This class implements the logic of handling
20 * mouse events, animating, hiding, showing all elements and returning the color of the series to be used as a legend item.
24 * The series class supports listeners via the Observable syntax. Some of these listeners are:
26 * - `itemmouseup` When the user interacts with a marker.
27 * - `itemmousedown` When the user interacts with a marker.
28 * - `itemmousemove` When the user iteracts with a marker.
29 * - `afterrender` Will be triggered when the animation ends or when the series has been rendered completely.
37 * 'afterrender': function() {
38 * console('afterrender');
46 Ext.define('Ext.chart.series.Series', {
48 /* Begin Definitions */
51 observable: 'Ext.util.Observable',
52 labels: 'Ext.chart.Label',
53 highlights: 'Ext.chart.Highlight',
54 tips: 'Ext.chart.Tip',
55 callouts: 'Ext.chart.Callout'
61 * @cfg {Boolean|Object} highlight
62 * If set to `true` it will highlight the markers or the series when hovering
63 * with the mouse. This parameter can also be an object with the same style
64 * properties you would apply to a {@link Ext.draw.Sprite} to apply custom
65 * styles to markers and series.
70 * Add tooltips to the visualization's markers. The options for the tips are the
71 * same configuration used with {@link Ext.tip.ToolTip}. For example:
77 * renderer: function(storeItem, item) {
78 * this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data1') + ' views');
85 * The type of series. Set in subclasses.
91 * The human-readable name of the series.
96 * @cfg {Boolean} showInLegend
97 * Whether to show this series in the legend.
102 * @cfg {Function} renderer
103 * A function that can be overridden to set custom styling properties to each rendered element.
104 * Passes in (sprite, record, attributes, index, store) to the function.
106 renderer: function(sprite, record, attributes, index, store) {
111 * @cfg {Array} shadowAttributes
112 * An array with shadow attributes
114 shadowAttributes: null,
116 //@private triggerdrawlistener flag
117 triggerAfterDraw: false,
120 * @cfg {Object} listeners
121 * An (optional) object with event callbacks. All event callbacks get the target *item* as first parameter. The callback functions are:
124 * <li>itemmouseover</li>
125 * <li>itemmouseout</li>
126 * <li>itemmousedown</li>
127 * <li>itemmouseup</li>
131 constructor: function(config) {
134 Ext.apply(me, config);
137 me.shadowGroups = [];
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);
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
162 me.mixins.observable.constructor.call(me, config);
166 itemmouseover: me.onItemMouseOver,
167 itemmouseout: me.onItemMouseOut,
168 mouseleave: me.onMouseLeave
172 // @private set the bbox and clipBox for the series
173 setBBox: function(noGutter) {
176 chartBBox = chart.chartBBox,
177 gutterX = noGutter ? 0 : chart.maxGutter[0],
178 gutterY = noGutter ? 0 : chart.maxGutter[1],
184 width: chartBBox.width,
185 height: chartBBox.height
187 me.clipBox = clipBox;
190 x: (clipBox.x + gutterX) - (chart.zoom.x * chart.zoom.width),
191 y: (clipBox.y + gutterY) - (chart.zoom.y * chart.zoom.height),
192 width: (clipBox.width - (gutterX * 2)) * chart.zoom.width,
193 height: (clipBox.height - (gutterY * 2)) * chart.zoom.height
198 // @private set the animation for the sprite
199 onAnimate: function(sprite, attr) {
201 sprite.stopAnimation();
202 if (me.triggerAfterDraw) {
203 return sprite.animate(Ext.applyIf(attr, me.chart.animate));
205 me.triggerAfterDraw = true;
206 return sprite.animate(Ext.apply(Ext.applyIf(attr, me.chart.animate), {
208 'afteranimate': function() {
209 me.triggerAfterDraw = false;
210 me.fireEvent('afterrender');
217 // @private return the gutter.
218 getGutters: function() {
222 // @private wrapper for the itemmouseover event.
223 onItemMouseOver: function(item) {
225 if (item.series === me) {
227 me.highlightItem(item);
235 // @private wrapper for the itemmouseout event.
236 onItemMouseOut: function(item) {
238 if (item.series === me) {
239 me.unHighlightItem();
246 // @private wrapper for the mouseleave event.
247 onMouseLeave: function() {
249 me.unHighlightItem();
256 * For a given x/y point relative to the Surface, find a corresponding item from this
260 * @return {Object} An object describing the item, or null if there is no matching item. The exact contents of
261 * this object will vary by series type, but should always contain at least the following:
263 * <li>{Ext.chart.series.Series} series - the Series object to which the item belongs</li>
264 * <li>{Object} value - the value(s) of the item's data point</li>
265 * <li>{Array} point - the x/y coordinates relative to the chart box of a single point
266 * for this data item, which can be used as e.g. a tooltip anchor point.</li>
267 * <li>{Ext.draw.Sprite} sprite - the item's rendering Sprite.
270 getItemForPoint: function(x, y) {
271 //if there are no items to query just return null.
272 if (!this.items || !this.items.length || this.seriesIsHidden) {
280 if (!Ext.draw.Draw.withinBox(x, y, bbox)) {
283 for (i = 0, ln = items.length; i < ln; i++) {
284 if (items[i] && this.isItemInPoint(x, y, items[i], i)) {
292 isItemInPoint: function(x, y, item, i) {
297 * Hides all the elements in the series.
299 hideAll: function() {
302 item, len, i, sprite;
304 me.seriesIsHidden = true;
305 me._prevShowMarkers = me.showMarkers;
307 me.showMarkers = false;
311 for (i = 0, len = items.length; i < len; i++) {
313 sprite = item.sprite;
315 sprite.setAttributes({
323 * Shows all the elements in the series.
325 showAll: function() {
327 prevAnimate = me.chart.animate;
328 me.chart.animate = false;
329 me.seriesIsHidden = false;
330 me.showMarkers = me._prevShowMarkers;
332 me.chart.animate = prevAnimate;
336 * Returns a string with the color to be used for the series legend item.
338 getLegendColor: function(index) {
339 var me = this, fill, stroke;
340 if (me.seriesStyle) {
341 fill = me.seriesStyle.fill;
342 stroke = me.seriesStyle.stroke;
343 if (fill && fill != 'none') {
352 * Checks whether the data field should be visible in the legend
354 * @param {Number} index The index of the current item
356 visibleInLegend: function(index){
357 var excludes = this.__excludes;
359 return !excludes[index];
361 return !this.seriesIsHidden;
365 * Changes the value of the {@link #title} for the series.
366 * Arguments can take two forms:
368 * <li>A single String value: this will be used as the new single title for the series (applies
369 * to series with only one yField)</li>
370 * <li>A numeric index and a String value: this will set the title for a single indexed yField.</li>
372 * @param {Number} index
373 * @param {String} title
375 setTitle: function(index, title) {
379 if (Ext.isString(index)) {
384 if (Ext.isArray(oldTitle)) {
385 oldTitle[index] = title;
390 me.fireEvent('titlechange', title, index);