3 * Copyright(c) 2006-2009 Ext JS, LLC
5 * http://www.extjs.com/license
8 * @class Ext.chart.Chart
\r
9 * @extends Ext.FlashComponent
\r
10 * The Ext.chart package provides the capability to visualize data with flash based charting.
\r
11 * Each chart binds directly to an Ext.data.Store enabling automatic updates of the chart.
\r
12 * To change the look and feel of a chart, see the {@link #chartStyle} and {@link #extraStyle} config options.
\r
17 Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
\r
21 * @cfg {String} backgroundColor
\r
26 * @cfg {Object} chartStyle
\r
27 * Sets styles for this chart. This contains default styling, so modifying this property will <b>override</b>
\r
28 * the built in styles of the chart. Use {@link #extraStyle} to add customizations to the default styling.
\r
32 animationEnabled: true,
\r
59 * The url to load the chart from. This defaults to Ext.chart.Chart.CHART_URL, which should
\r
60 * be modified to point to the local charts resource.
\r
64 * @cfg {Object} extraStyle
\r
65 * Contains extra styles that will be added or overwritten to the default chartStyle. Defaults to <tt>null</tt>.
\r
66 * For a detailed list of the options available, visit the YUI Charts site
\r
67 * at <a href="http://developer.yahoo.com/yui/charts/#basicstyles">http://developer.yahoo.com/yui/charts/#basicstyles</a><br/>
\r
68 * Some of the options availabe:<br />
\r
69 * <ul style="padding:5px;padding-left:16px;list-style-type:inherit;">
\r
70 * <li><b>padding</b> - The space around the edge of the chart's contents. Padding does not increase the size of the chart.</li>
\r
71 * <li><b>animationEnabled</b> - A Boolean value that specifies whether marker animations are enabled or not. Enabled by default.</li>
\r
72 * <li><b>font</b> - An Object defining the font style to be used in the chart. Defaults to <tt>{ name: 'Tahoma', color: 0x444444, size: 11 }</tt><br/>
\r
73 * <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
\r
74 * <li><b>name</b> - font name</li>
\r
75 * <li><b>color</b> - font color (hex code, ie: "#ff0000", "ff0000" or 0xff0000)</li>
\r
76 * <li><b>size</b> - font size in points (numeric portion only, ie: 11)</li>
\r
77 * <li><b>bold</b> - boolean</li>
\r
78 * <li><b>italic</b> - boolean</li>
\r
79 * <li><b>underline</b> - boolean</li>
\r
82 * <li><b>border</b> - An object defining the border style around the chart. The chart itself will decrease in dimensions to accomodate the border.<br/>
\r
83 * <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
\r
84 * <li><b>color</b> - border color (hex code, ie: "#ff0000", "ff0000" or 0xff0000)</li>
\r
85 * <li><b>size</b> - border size in pixels (numeric portion only, ie: 1)</li>
\r
88 * <li><b>background</b> - An object defining the background style of the chart.<br/>
\r
89 * <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
\r
90 * <li><b>color</b> - border color (hex code, ie: "#ff0000", "ff0000" or 0xff0000)</li>
\r
91 * <li><b>image</b> - an image URL. May be relative to the current document or absolute.</li>
\r
94 * <li><b>legend</b> - An object defining the legend style<br/>
\r
95 * <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
\r
96 * <li><b>display</b> - location of the legend. Possible values are "none", "left", "right", "top", and "bottom".</li>
\r
97 * <li><b>spacing</b> - an image URL. May be relative to the current document or absolute.</li>
\r
98 * <li><b>padding, border, background, font</b> - same options as described above.</li>
\r
100 * <li><b>dataTip</b> - An object defining the style of the data tip (tooltip).<br/>
\r
101 * <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
\r
102 * <li><b>padding, border, background, font</b> - same options as described above.</li>
\r
104 * <li><b>xAxis and yAxis</b> - An object defining the style of the style of either axis.<br/>
\r
105 * <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
\r
106 * <li><b>color</b> - same option as described above.</li>
\r
107 * <li><b>size</b> - same option as described above.</li>
\r
108 * <li><b>showLabels</b> - boolean</li>
\r
109 * <li><b>labelRotation</b> - a value in degrees from -90 through 90. Default is zero.</li>
\r
111 * <li><b>majorGridLines and minorGridLines</b> - An object defining the style of the style of the grid lines.<br/>
\r
112 * <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
\r
113 * <li><b>color, size</b> - same options as described above.</li>
\r
115 * <li><b>zeroGridLine</b> - An object defining the style of the style of the zero grid line.<br/>
\r
116 * <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
\r
117 * <li><b>color, size</b> - same options as described above.</li>
\r
119 * <li><b>majorTicks and minorTicks</b> - An object defining the style of the style of ticks in the chart.<br/>
\r
120 * <ul style="padding:5px;padding-left:26px;list-style-type:circle;">
\r
121 * <li><b>color, size</b> - same options as described above.</li>
\r
122 * <li><b>length</b> - the length of each tick in pixels extending from the axis.</li>
\r
123 * <li><b>display</b> - how the ticks are drawn. Possible values are "none", "inside", "outside", and "cross".</li>
\r
130 * @cfg {Object} seriesStyles
\r
131 * Contains styles to apply to the series after a refresh. Defaults to <tt>null</tt>.
\r
133 seriesStyles: null,
\r
136 * @cfg {Boolean} disableCaching
\r
137 * True to add a "cache buster" to the end of the chart url. Defaults to true for Opera and IE.
\r
139 disableCaching: Ext.isIE || Ext.isOpera,
\r
140 disableCacheParam: '_dc',
\r
142 initComponent : function(){
\r
143 Ext.chart.Chart.superclass.initComponent.call(this);
\r
145 this.url = Ext.chart.Chart.CHART_URL;
\r
147 if(this.disableCaching){
\r
148 this.url = Ext.urlAppend(this.url, String.format('{0}={1}', this.disableCacheParam, new Date().getTime()));
\r
159 * @event beforerefresh
\r
160 * Fires before a refresh to the chart data is called. If the beforerefresh handler returns
\r
161 * <tt>false</tt> the {@link #refresh} action will be cancelled.
\r
162 * @param {Chart} this
\r
167 * Fires after the chart data has been refreshed.
\r
168 * @param {Chart} this
\r
172 this.store = Ext.StoreMgr.lookup(this.store);
\r
176 * Sets a single style value on the Chart instance.
\r
178 * @param name {String} Name of the Chart style value to change.
\r
179 * @param value {Object} New value to pass to the Chart style.
\r
181 setStyle: function(name, value){
\r
182 this.swf.setStyle(name, Ext.encode(value));
\r
186 * Resets all styles on the Chart instance.
\r
188 * @param styles {Object} Initializer for all Chart styles.
\r
190 setStyles: function(styles){
\r
191 this.swf.setStyles(Ext.encode(styles));
\r
195 * Sets the styles on all series in the Chart.
\r
197 * @param styles {Array} Initializer for all Chart series styles.
\r
199 setSeriesStyles: function(styles){
\r
200 this.seriesStyles = styles;
\r
202 Ext.each(styles, function(style){
\r
203 s.push(Ext.encode(style));
\r
205 this.swf.setSeriesStyles(s);
\r
208 setCategoryNames : function(names){
\r
209 this.swf.setCategoryNames(names);
\r
212 setTipRenderer : function(fn){
\r
214 this.tipFnName = this.createFnProxy(function(item, index, series){
\r
215 var record = chart.store.getAt(index);
\r
216 return fn(chart, record, index, series);
\r
217 }, this.tipFnName);
\r
218 this.swf.setDataTipFunction(this.tipFnName);
\r
221 setSeries : function(series){
\r
222 this.series = series;
\r
227 * Changes the data store bound to this chart and refreshes it.
\r
228 * @param {Store} store The store to bind to this chart
\r
230 bindStore : function(store, initial){
\r
231 if(!initial && this.store){
\r
232 if(store !== this.store && this.store.autoDestroy){
\r
233 this.store.destroy();
\r
235 this.store.un("datachanged", this.refresh, this);
\r
236 this.store.un("add", this.delayRefresh, this);
\r
237 this.store.un("remove", this.delayRefresh, this);
\r
238 this.store.un("update", this.delayRefresh, this);
\r
239 this.store.un("clear", this.refresh, this);
\r
243 store = Ext.StoreMgr.lookup(store);
\r
246 datachanged: this.refresh,
\r
247 add: this.delayRefresh,
\r
248 remove: this.delayRefresh,
\r
249 update: this.delayRefresh,
\r
250 clear: this.refresh
\r
253 this.store = store;
\r
254 if(store && !initial){
\r
259 onSwfReady : function(isReset){
\r
260 Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
\r
261 this.swf.setType(this.type);
\r
263 if(this.chartStyle){
\r
264 this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle));
\r
267 if(this.categoryNames){
\r
268 this.setCategoryNames(this.categoryNames);
\r
271 if(this.tipRenderer){
\r
272 this.setTipRenderer(this.tipRenderer);
\r
275 this.bindStore(this.store, true);
\r
277 this.refresh.defer(10, this);
\r
280 delayRefresh : function(){
\r
281 if(!this.refreshTask){
\r
282 this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
\r
284 this.refreshTask.delay(this.refreshBuffer);
\r
287 refresh : function(){
\r
288 if(this.fireEvent('beforerefresh', this) !== false){
\r
289 var styleChanged = false;
\r
290 // convert the store data into something YUI charts can understand
\r
291 var data = [], rs = this.store.data.items;
\r
292 for(var j = 0, len = rs.length; j < len; j++){
\r
293 data[j] = rs[j].data;
\r
295 //make a copy of the series definitions so that we aren't
\r
296 //editing them directly.
\r
297 var dataProvider = [];
\r
298 var seriesCount = 0;
\r
299 var currentSeries = null;
\r
302 seriesCount = this.series.length;
\r
303 for(i = 0; i < seriesCount; i++){
\r
304 currentSeries = this.series[i];
\r
305 var clonedSeries = {};
\r
306 for(var prop in currentSeries){
\r
307 if(prop == "style" && currentSeries.style !== null){
\r
308 clonedSeries.style = Ext.encode(currentSeries.style);
\r
309 styleChanged = true;
\r
310 //we don't want to modify the styles again next time
\r
311 //so null out the style property.
\r
312 // this causes issues
\r
313 // currentSeries.style = null;
\r
315 clonedSeries[prop] = currentSeries[prop];
\r
318 dataProvider.push(clonedSeries);
\r
322 if(seriesCount > 0){
\r
323 for(i = 0; i < seriesCount; i++){
\r
324 currentSeries = dataProvider[i];
\r
325 if(!currentSeries.type){
\r
326 currentSeries.type = this.type;
\r
328 currentSeries.dataProvider = data;
\r
331 dataProvider.push({type: this.type, dataProvider: data});
\r
333 this.swf.setDataProvider(dataProvider);
\r
334 if(this.seriesStyles){
\r
335 this.setSeriesStyles(this.seriesStyles);
\r
337 this.fireEvent('refresh', this);
\r
341 createFnProxy : function(fn, old){
\r
343 delete window[old];
\r
345 var fnName = "extFnProxy" + (++Ext.chart.Chart.PROXY_FN_ID);
\r
346 window[fnName] = fn;
\r
350 onDestroy: function(){
\r
351 Ext.chart.Chart.superclass.onDestroy.call(this);
\r
352 this.bindStore(null);
\r
353 var tip = this.tipFnName;
\r
354 if(!Ext.isEmpty(tip)){
\r
355 delete window[tip];
\r
359 Ext.reg('chart', Ext.chart.Chart);
\r
360 Ext.chart.Chart.PROXY_FN_ID = 0;
\r
363 * Sets the url to load the chart from. This should be set to a local resource.
\r
367 Ext.chart.Chart.CHART_URL = 'http:/' + '/yui.yahooapis.com/2.7.0/build/charts/assets/charts.swf';
\r
370 * @class Ext.chart.PieChart
\r
371 * @extends Ext.chart.Chart
\r
375 Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
\r
378 onSwfReady : function(isReset){
\r
379 Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);
\r
381 this.setDataField(this.dataField);
\r
382 this.setCategoryField(this.categoryField);
\r
385 setDataField : function(field){
\r
386 this.dataField = field;
\r
387 this.swf.setDataField(field);
\r
390 setCategoryField : function(field){
\r
391 this.categoryField = field;
\r
392 this.swf.setCategoryField(field);
\r
395 Ext.reg('piechart', Ext.chart.PieChart);
\r
398 * @class Ext.chart.CartesianChart
\r
399 * @extends Ext.chart.Chart
\r
401 * @xtype cartesianchart
\r
403 Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
\r
404 onSwfReady : function(isReset){
\r
405 Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
\r
408 this.setXField(this.xField);
\r
411 this.setYField(this.yField);
\r
414 this.setXAxis(this.xAxis);
\r
417 this.setYAxis(this.yAxis);
\r
421 setXField : function(value){
\r
422 this.xField = value;
\r
423 this.swf.setHorizontalField(value);
\r
426 setYField : function(value){
\r
427 this.yField = value;
\r
428 this.swf.setVerticalField(value);
\r
431 setXAxis : function(value){
\r
432 this.xAxis = this.createAxis('xAxis', value);
\r
433 this.swf.setHorizontalAxis(this.xAxis);
\r
436 setYAxis : function(value){
\r
437 this.yAxis = this.createAxis('yAxis', value);
\r
438 this.swf.setVerticalAxis(this.yAxis);
\r
441 createAxis : function(axis, value){
\r
442 var o = Ext.apply({}, value), oldFn = null;
\r
444 oldFn = this[axis].labelFunction;
\r
446 if(o.labelRenderer){
\r
447 var fn = o.labelRenderer;
\r
448 o.labelFunction = this.createFnProxy(function(v){
\r
451 delete o.labelRenderer;
\r
456 Ext.reg('cartesianchart', Ext.chart.CartesianChart);
\r
459 * @class Ext.chart.LineChart
\r
460 * @extends Ext.chart.CartesianChart
\r
464 Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
\r
467 Ext.reg('linechart', Ext.chart.LineChart);
\r
470 * @class Ext.chart.ColumnChart
\r
471 * @extends Ext.chart.CartesianChart
\r
473 * @xtype columnchart
\r
475 Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
\r
478 Ext.reg('columnchart', Ext.chart.ColumnChart);
\r
481 * @class Ext.chart.StackedColumnChart
\r
482 * @extends Ext.chart.CartesianChart
\r
484 * @xtype stackedcolumnchart
\r
486 Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
\r
487 type: 'stackcolumn'
\r
489 Ext.reg('stackedcolumnchart', Ext.chart.StackedColumnChart);
\r
492 * @class Ext.chart.BarChart
\r
493 * @extends Ext.chart.CartesianChart
\r
497 Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
\r
500 Ext.reg('barchart', Ext.chart.BarChart);
\r
503 * @class Ext.chart.StackedBarChart
\r
504 * @extends Ext.chart.CartesianChart
\r
506 * @xtype stackedbarchart
\r
508 Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
\r
511 Ext.reg('stackedbarchart', Ext.chart.StackedBarChart);
\r
516 * @class Ext.chart.Axis
\r
517 * Defines a CartesianChart's vertical or horizontal axis.
\r
520 Ext.chart.Axis = function(config){
\r
521 Ext.apply(this, config);
\r
524 Ext.chart.Axis.prototype =
\r
527 * The type of axis.
\r
535 * The direction in which the axis is drawn. May be "horizontal" or "vertical".
\r
537 * @property orientation
\r
540 orientation: "horizontal",
\r
543 * If true, the items on the axis will be drawn in opposite direction.
\r
545 * @property reverse
\r
551 * A string reference to the globally-accessible function that may be called to
\r
552 * determine each of the label values for this axis.
\r
554 * @property labelFunction
\r
557 labelFunction: null,
\r
560 * If true, labels that overlap previously drawn labels on the axis will be hidden.
\r
562 * @property hideOverlappingLabels
\r
565 hideOverlappingLabels: true
\r
569 * @class Ext.chart.NumericAxis
\r
570 * @extends Ext.chart.Axis
\r
571 * A type of axis whose units are measured in numeric values.
\r
574 Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
\r
578 * The minimum value drawn by the axis. If not set explicitly, the axis minimum
\r
579 * will be calculated automatically.
\r
581 * @property minimum
\r
587 * The maximum value drawn by the axis. If not set explicitly, the axis maximum
\r
588 * will be calculated automatically.
\r
590 * @property maximum
\r
596 * The spacing between major intervals on this axis.
\r
598 * @property majorUnit
\r
604 * The spacing between minor intervals on this axis.
\r
606 * @property minorUnit
\r
612 * If true, the labels, ticks, gridlines, and other objects will snap to
\r
613 * the nearest major or minor unit. If false, their position will be based
\r
614 * on the minimum value.
\r
616 * @property snapToUnits
\r
622 * If true, and the bounds are calculated automatically, either the minimum or
\r
623 * maximum will be set to zero.
\r
625 * @property alwaysShowZero
\r
628 alwaysShowZero: true,
\r
631 * The scaling algorithm to use on this axis. May be "linear" or "logarithmic".
\r
640 * @class Ext.chart.TimeAxis
\r
641 * @extends Ext.chart.Axis
\r
642 * A type of axis whose units are measured in time-based values.
\r
645 Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
\r
649 * The minimum value drawn by the axis. If not set explicitly, the axis minimum
\r
650 * will be calculated automatically.
\r
652 * @property minimum
\r
658 * The maximum value drawn by the axis. If not set explicitly, the axis maximum
\r
659 * will be calculated automatically.
\r
661 * @property maximum
\r
667 * The spacing between major intervals on this axis.
\r
669 * @property majorUnit
\r
675 * The time unit used by the majorUnit.
\r
677 * @property majorTimeUnit
\r
680 majorTimeUnit: null,
\r
683 * The spacing between minor intervals on this axis.
\r
685 * @property majorUnit
\r
691 * The time unit used by the minorUnit.
\r
693 * @property majorTimeUnit
\r
696 minorTimeUnit: null,
\r
699 * If true, the labels, ticks, gridlines, and other objects will snap to
\r
700 * the nearest major or minor unit. If false, their position will be based
\r
701 * on the minimum value.
\r
703 * @property snapToUnits
\r
710 * @class Ext.chart.CategoryAxis
\r
711 * @extends Ext.chart.Axis
\r
712 * A type of axis that displays items in categories.
\r
715 Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
\r
719 * A list of category names to display along this axis.
\r
721 * @property categoryNames
\r
724 categoryNames: null
\r
728 * @class Ext.chart.Series
\r
729 * Series class for the charts widget.
\r
732 Ext.chart.Series = function(config) { Ext.apply(this, config); };
\r
734 Ext.chart.Series.prototype =
\r
737 * The type of series.
\r
745 * The human-readable name of the series.
\r
747 * @property displayName
\r
754 * @class Ext.chart.CartesianSeries
\r
755 * @extends Ext.chart.Series
\r
756 * CartesianSeries class for the charts widget.
\r
759 Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {
\r
761 * The field used to access the x-axis value from the items from the data source.
\r
769 * The field used to access the y-axis value from the items from the data source.
\r
778 * @class Ext.chart.ColumnSeries
\r
779 * @extends Ext.chart.CartesianSeries
\r
780 * ColumnSeries class for the charts widget.
\r
783 Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
\r
788 * @class Ext.chart.LineSeries
\r
789 * @extends Ext.chart.CartesianSeries
\r
790 * LineSeries class for the charts widget.
\r
793 Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
\r
798 * @class Ext.chart.BarSeries
\r
799 * @extends Ext.chart.CartesianSeries
\r
800 * BarSeries class for the charts widget.
\r
803 Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
\r
809 * @class Ext.chart.PieSeries
\r
810 * @extends Ext.chart.Series
\r
811 * PieSeries class for the charts widget.
\r
814 Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
\r
817 categoryField: null
\r