123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>The source code</title>
- <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>
- <script type="text/javascript">
- function highlight() {
- document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
- }
- </script>
- </head>
- <body onload="prettyPrint(); highlight();">
- <pre class="prettyprint lang-js"><span id='Ext-chart-Chart'>/**
- </span> * Charts provide a flexible way to achieve a wide range of data visualization capablitities.
- * Each Chart gets its data directly from a {@link Ext.data.Store Store}, and automatically
- * updates its display whenever data in the Store changes. In addition, the look and feel
- * of a Chart can be customized using {@link Ext.chart.theme.Theme Theme}s.
- *
- * ## Creating a Simple Chart
- *
- * Every Chart has three key parts - a {@link Ext.data.Store Store} that contains the data,
- * an array of {@link Ext.chart.axis.Axis Axes} which define the boundaries of the Chart,
- * and one or more {@link Ext.chart.series.Series Series} to handle the visual rendering of the data points.
- *
- * ### 1. Creating a Store
- *
- * The first step is to create a {@link Ext.data.Model Model} that represents the type of
- * data that will be displayed in the Chart. For example the data for a chart that displays
- * a weather forecast could be represented as a series of "WeatherPoint" data points with
- * two fields - "temperature", and "date":
- *
- * Ext.define('WeatherPoint', {
- * extend: 'Ext.data.Model',
- * fields: ['temperature', 'date']
- * });
- *
- * Next a {@link Ext.data.Store Store} must be created. The store contains a collection of "WeatherPoint" Model instances.
- * The data could be loaded dynamically, but for sake of ease this example uses inline data:
- *
- * var store = Ext.create('Ext.data.Store', {
- * model: 'WeatherPoint',
- * data: [
- * { temperature: 58, date: new Date(2011, 1, 1, 8) },
- * { temperature: 63, date: new Date(2011, 1, 1, 9) },
- * { temperature: 73, date: new Date(2011, 1, 1, 10) },
- * { temperature: 78, date: new Date(2011, 1, 1, 11) },
- * { temperature: 81, date: new Date(2011, 1, 1, 12) }
- * ]
- * });
- *
- * For additional information on Models and Stores please refer to the [Data Guide](#/guide/data).
- *
- * ### 2. Creating the Chart object
- *
- * Now that a Store has been created it can be used in a Chart:
- *
- * Ext.create('Ext.chart.Chart', {
- * renderTo: Ext.getBody(),
- * width: 400,
- * height: 300,
- * store: store
- * });
- *
- * That's all it takes to create a Chart instance that is backed by a Store.
- * However, if the above code is run in a browser, a blank screen will be displayed.
- * This is because the two pieces that are responsible for the visual display,
- * the Chart's {@link #cfg-axes axes} and {@link #cfg-series series}, have not yet been defined.
- *
- * ### 3. Configuring the Axes
- *
- * {@link Ext.chart.axis.Axis Axes} are the lines that define the boundaries of the data points that a Chart can display.
- * This example uses one of the most common Axes configurations - a horizontal "x" axis, and a vertical "y" axis:
- *
- * Ext.create('Ext.chart.Chart', {
- * ...
- * axes: [
- * {
- * title: 'Temperature',
- * type: 'Numeric',
- * position: 'left',
- * fields: ['temperature'],
- * minimum: 0,
- * maximum: 100
- * },
- * {
- * title: 'Time',
- * type: 'Time',
- * position: 'bottom',
- * fields: ['date'],
- * dateFormat: 'ga'
- * }
- * ]
- * });
- *
- * The "Temperature" axis is a vertical {@link Ext.chart.axis.Numeric Numeric Axis} and is positioned on the left edge of the Chart.
- * It represents the bounds of the data contained in the "WeatherPoint" Model's "temperature" field that was
- * defined above. The minimum value for this axis is "0", and the maximum is "100".
- *
- * The horizontal axis is a {@link Ext.chart.axis.Time Time Axis} and is positioned on the bottom edge of the Chart.
- * It represents the bounds of the data contained in the "WeatherPoint" Model's "date" field.
- * The {@link Ext.chart.axis.Time#cfg-dateFormat dateFormat}
- * configuration tells the Time Axis how to format it's labels.
- *
- * Here's what the Chart looks like now that it has its Axes configured:
- *
- * {@img Ext.chart.Chart/Ext.chart.Chart1.png Chart Axes}
- *
- * ### 4. Configuring the Series
- *
- * The final step in creating a simple Chart is to configure one or more {@link Ext.chart.series.Series Series}.
- * Series are responsible for the visual representation of the data points contained in the Store.
- * This example only has one Series:
- *
- * Ext.create('Ext.chart.Chart', {
- * ...
- * axes: [
- * ...
- * ],
- * series: [
- * {
- * type: 'line',
- * xField: 'date',
- * yField: 'temperature'
- * }
- * ]
- * });
- *
- * This Series is a {@link Ext.chart.series.Line Line Series}, and it uses the "date" and "temperature" fields
- * from the "WeatherPoint" Models in the Store to plot its data points:
- *
- * {@img Ext.chart.Chart/Ext.chart.Chart2.png Line Series}
- *
- * See the [Line Charts Example](#!/example/charts/Charts.html) for a live demo.
- *
- * ## Themes
- *
- * The color scheme for a Chart can be easily changed using the {@link #cfg-theme theme} configuration option:
- *
- * Ext.create('Ext.chart.Chart', {
- * ...
- * theme: 'Green',
- * ...
- * });
- *
- * {@img Ext.chart.Chart/Ext.chart.Chart3.png Green Theme}
- *
- * For more information on Charts please refer to the [Drawing and Charting Guide](#/guide/drawing_and_charting).
- *
- */
- Ext.define('Ext.chart.Chart', {
- /* Begin Definitions */
- alias: 'widget.chart',
- extend: 'Ext.draw.Component',
-
- mixins: {
- themeManager: 'Ext.chart.theme.Theme',
- mask: 'Ext.chart.Mask',
- navigation: 'Ext.chart.Navigation',
- bindable: 'Ext.util.Bindable',
- observable: 'Ext.util.Observable'
- },
- uses: [
- 'Ext.chart.series.Series'
- ],
-
- requires: [
- 'Ext.util.MixedCollection',
- 'Ext.data.StoreManager',
- 'Ext.chart.Legend',
- 'Ext.chart.theme.Base',
- 'Ext.chart.theme.Theme',
- 'Ext.util.DelayedTask'
- ],
- /* End Definitions */
- // @private
- viewBox: false,
- <span id='Ext-chart-Chart-cfg-theme'> /**
- </span> * @cfg {String} theme
- * The name of the theme to be used. A theme defines the colors and other visual displays of tick marks
- * on axis, text, title text, line colors, marker colors and styles, etc. Possible theme values are 'Base', 'Green',
- * 'Sky', 'Red', 'Purple', 'Blue', 'Yellow' and also six category themes 'Category1' to 'Category6'. Default value
- * is 'Base'.
- */
- <span id='Ext-chart-Chart-cfg-animate'> /**
- </span> * @cfg {Boolean/Object} animate
- * True for the default animation (easing: 'ease' and duration: 500) or a standard animation config
- * object to be used for default chart animations. Defaults to false.
- */
- animate: false,
- <span id='Ext-chart-Chart-cfg-legend'> /**
- </span> * @cfg {Boolean/Object} legend
- * True for the default legend display or a legend config object. Defaults to false.
- */
- legend: false,
- <span id='Ext-chart-Chart-cfg-insetPadding'> /**
- </span> * @cfg {Number} insetPadding
- * The amount of inset padding in pixels for the chart. Defaults to 10.
- */
- insetPadding: 10,
- <span id='Ext-chart-Chart-cfg-enginePriority'> /**
- </span> * @cfg {String[]} enginePriority
- * Defines the priority order for which Surface implementation to use. The first one supported by the current
- * environment will be used. Defaults to `['Svg', 'Vml']`.
- */
- enginePriority: ['Svg', 'Vml'],
- <span id='Ext-chart-Chart-cfg-background'> /**
- </span> * @cfg {Object/Boolean} background
- * The chart background. This can be a gradient object, image, or color. Defaults to false for no
- * background. For example, if `background` were to be a color we could set the object as
- *
- * background: {
- * //color string
- * fill: '#ccc'
- * }
- *
- * You can specify an image by using:
- *
- * background: {
- * image: 'http://path.to.image/'
- * }
- *
- * Also you can specify a gradient by using the gradient object syntax:
- *
- * background: {
- * gradient: {
- * id: 'gradientId',
- * angle: 45,
- * stops: {
- * 0: {
- * color: '#555'
- * }
- * 100: {
- * color: '#ddd'
- * }
- * }
- * }
- * }
- */
- background: false,
- <span id='Ext-chart-Chart-cfg-gradients'> /**
- </span> * @cfg {Object[]} gradients
- * Define a set of gradients that can be used as `fill` property in sprites. The gradients array is an
- * array of objects with the following properties:
- *
- * - **id** - string - The unique name of the gradient.
- * - **angle** - number, optional - The angle of the gradient in degrees.
- * - **stops** - object - An object with numbers as keys (from 0 to 100) and style objects as values
- *
- * For example:
- *
- * gradients: [{
- * id: 'gradientId',
- * angle: 45,
- * stops: {
- * 0: {
- * color: '#555'
- * },
- * 100: {
- * color: '#ddd'
- * }
- * }
- * }, {
- * id: 'gradientId2',
- * angle: 0,
- * stops: {
- * 0: {
- * color: '#590'
- * },
- * 20: {
- * color: '#599'
- * },
- * 100: {
- * color: '#ddd'
- * }
- * }
- * }]
- *
- * Then the sprites can use `gradientId` and `gradientId2` by setting the fill attributes to those ids, for example:
- *
- * sprite.setAttributes({
- * fill: 'url(#gradientId)'
- * }, true);
- */
- <span id='Ext-chart-Chart-cfg-store'> /**
- </span> * @cfg {Ext.data.Store} store
- * The store that supplies data to this chart.
- */
- <span id='Ext-chart-Chart-cfg-series'> /**
- </span> * @cfg {Ext.chart.series.Series[]} series
- * Array of {@link Ext.chart.series.Series Series} instances or config objects. For example:
- *
- * series: [{
- * type: 'column',
- * axis: 'left',
- * listeners: {
- * 'afterrender': function() {
- * console('afterrender');
- * }
- * },
- * xField: 'category',
- * yField: 'data1'
- * }]
- */
- <span id='Ext-chart-Chart-cfg-axes'> /**
- </span> * @cfg {Ext.chart.axis.Axis[]} axes
- * Array of {@link Ext.chart.axis.Axis Axis} instances or config objects. For example:
- *
- * axes: [{
- * type: 'Numeric',
- * position: 'left',
- * fields: ['data1'],
- * title: 'Number of Hits',
- * minimum: 0,
- * //one minor tick between two major ticks
- * minorTickSteps: 1
- * }, {
- * type: 'Category',
- * position: 'bottom',
- * fields: ['name'],
- * title: 'Month of the Year'
- * }]
- */
- constructor: function(config) {
- var me = this,
- defaultAnim;
- config = Ext.apply({}, config);
- me.initTheme(config.theme || me.theme);
- if (me.gradients) {
- Ext.apply(config, { gradients: me.gradients });
- }
- if (me.background) {
- Ext.apply(config, { background: me.background });
- }
- if (config.animate) {
- defaultAnim = {
- easing: 'ease',
- duration: 500
- };
- if (Ext.isObject(config.animate)) {
- config.animate = Ext.applyIf(config.animate, defaultAnim);
- }
- else {
- config.animate = defaultAnim;
- }
- }
- me.mixins.observable.constructor.call(me, config);
- if (config.enableMask) {
- me.mixins.mask.constructor.call(me);
- }
- me.mixins.navigation.constructor.call(me);
- me.callParent([config]);
- },
-
- getChartStore: function(){
- return this.substore || this.store;
- },
- initComponent: function() {
- var me = this,
- axes,
- series;
- me.callParent();
- me.addEvents(
- 'itemmousedown',
- 'itemmouseup',
- 'itemmouseover',
- 'itemmouseout',
- 'itemclick',
- 'itemdblclick',
- 'itemdragstart',
- 'itemdrag',
- 'itemdragend',
- <span id='Ext-chart-Chart-event-beforerefresh'> /**
- </span> * @event beforerefresh
- * Fires before a refresh to the chart data is called. If the beforerefresh handler returns false the
- * {@link #event-refresh} action will be cancelled.
- * @param {Ext.chart.Chart} this
- */
- 'beforerefresh',
- <span id='Ext-chart-Chart-event-refresh'> /**
- </span> * @event refresh
- * Fires after the chart data has been refreshed.
- * @param {Ext.chart.Chart} this
- */
- 'refresh'
- );
- Ext.applyIf(me, {
- zoom: {
- width: 1,
- height: 1,
- x: 0,
- y: 0
- }
- });
- me.maxGutter = [0, 0];
- me.store = Ext.data.StoreManager.lookup(me.store);
- axes = me.axes;
- me.axes = new Ext.util.MixedCollection(false, function(a) { return a.position; });
- if (axes) {
- me.axes.addAll(axes);
- }
- series = me.series;
- me.series = new Ext.util.MixedCollection(false, function(a) { return a.seriesId || (a.seriesId = Ext.id(null, 'ext-chart-series-')); });
- if (series) {
- me.series.addAll(series);
- }
- if (me.legend !== false) {
- me.legend = new Ext.chart.Legend(Ext.applyIf({chart:me}, me.legend));
- }
- me.on({
- mousemove: me.onMouseMove,
- mouseleave: me.onMouseLeave,
- mousedown: me.onMouseDown,
- mouseup: me.onMouseUp,
- click: me.onClick,
- dblclick: me.onDblClick,
- scope: me
- });
- },
- // @private overrides the component method to set the correct dimensions to the chart.
- afterComponentLayout: function(width, height) {
- var me = this;
- if (Ext.isNumber(width) && Ext.isNumber(height)) {
- if (width !== me.curWidth || height !== me.curHeight) {
- me.curWidth = width;
- me.curHeight = height;
- me.redraw(true);
- } else if (me.needsRedraw) {
- delete me.needsRedraw;
- me.redraw();
- }
- }
- this.callParent(arguments);
- },
- <span id='Ext-chart-Chart-method-redraw'> /**
- </span> * Redraws the chart. If animations are set this will animate the chart too.
- * @param {Boolean} resize (optional) flag which changes the default origin points of the chart for animations.
- */
- redraw: function(resize) {
- var me = this,
- seriesItems = me.series.items,
- seriesLen = seriesItems.length,
- axesItems = me.axes.items,
- axesLen = axesItems.length,
- i,
- chartBBox = me.chartBBox = {
- x: 0,
- y: 0,
- height: me.curHeight,
- width: me.curWidth
- },
- legend = me.legend;
- me.surface.setSize(chartBBox.width, chartBBox.height);
- // Instantiate Series and Axes
- for (i = 0; i < seriesLen; i++) {
- me.initializeSeries(seriesItems[i],i);
- }
- for (i = 0; i < axesLen; i++) {
- me.initializeAxis(axesItems[i]);
- }
- //process all views (aggregated data etc) on stores
- //before rendering.
- for (i = 0; i < axesLen; i++) {
- axesItems[i].processView();
- }
- for (i = 0; i < axesLen; i++) {
- axesItems[i].drawAxis(true);
- }
- // Create legend if not already created
- if (legend !== false && legend.visible) {
- if (legend.update || !legend.created) {
- legend.create();
- }
- }
- // Place axes properly, including influence from each other
- me.alignAxes();
- // Reposition legend based on new axis alignment
- if (legend !== false && legend.visible) {
- legend.updatePosition();
- }
- // Find the max gutter
- me.getMaxGutter();
- // Draw axes and series
- me.resizing = !!resize;
- for (i = 0; i < axesLen; i++) {
- axesItems[i].drawAxis();
- }
- for (i = 0; i < seriesLen; i++) {
- me.drawCharts(seriesItems[i]);
- }
- me.resizing = false;
- },
- // @private set the store after rendering the chart.
- afterRender: function() {
- var ref,
- me = this;
- this.callParent();
- if (me.categoryNames) {
- me.setCategoryNames(me.categoryNames);
- }
- if (me.tipRenderer) {
- ref = me.getFunctionRef(me.tipRenderer);
- me.setTipRenderer(ref.fn, ref.scope);
- }
- me.bindStore(me.store, true);
- me.refresh();
- if (me.surface.engine === 'Vml') {
- me.on('added', me.onAddedVml, me);
- me.mon(Ext.container.Container.hierarchyEventSource, 'added', me.onContainerAddedVml, me);
- }
- },
- // When using a vml surface we need to redraw when this chart or one of its ancestors
- // is moved to a new container after render, because moving the vml chart causes the
- // vml elements to go haywire, some displaing incorrectly or not displaying at all.
- // This appears to be caused by the component being moved to the detached body element
- // before being added to the new container.
- onAddedVml: function() {
- this.needsRedraw = true; // redraw after component layout
- },
- onContainerAddedVml: function(container) {
- if (this.isDescendantOf(container)) {
- this.needsRedraw = true; // redraw after component layout
- }
- },
- // @private get x and y position of the mouse cursor.
- getEventXY: function(e) {
- var me = this,
- box = this.surface.getRegion(),
- pageXY = e.getXY(),
- x = pageXY[0] - box.left,
- y = pageXY[1] - box.top;
- return [x, y];
- },
-
- onClick: function(e) {
- this.handleClick('itemclick', e);
- },
-
- onDblClick: function(e) {
- this.handleClick('itemdblclick', e);
- },
- // @private wrap the mouse down position to delegate the event to the series.
- handleClick: function(name, e) {
- var me = this,
- position = me.getEventXY(e),
- seriesItems = me.series.items,
- i, ln, series,
- item;
- // Ask each series if it has an item corresponding to (not necessarily exactly
- // on top of) the current mouse coords. Fire itemclick event.
- for (i = 0, ln = seriesItems.length; i < ln; i++) {
- series = seriesItems[i];
- if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
- if (series.getItemForPoint) {
- item = series.getItemForPoint(position[0], position[1]);
- if (item) {
- series.fireEvent(name, item);
- }
- }
- }
- }
- },
- // @private wrap the mouse down position to delegate the event to the series.
- onMouseDown: function(e) {
- var me = this,
- position = me.getEventXY(e),
- seriesItems = me.series.items,
- i, ln, series,
- item;
- if (me.enableMask) {
- me.mixins.mask.onMouseDown.call(me, e);
- }
- // Ask each series if it has an item corresponding to (not necessarily exactly
- // on top of) the current mouse coords. Fire itemmousedown event.
- for (i = 0, ln = seriesItems.length; i < ln; i++) {
- series = seriesItems[i];
- if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
- if (series.getItemForPoint) {
- item = series.getItemForPoint(position[0], position[1]);
- if (item) {
- series.fireEvent('itemmousedown', item);
- }
- }
- }
- }
- },
- // @private wrap the mouse up event to delegate it to the series.
- onMouseUp: function(e) {
- var me = this,
- position = me.getEventXY(e),
- seriesItems = me.series.items,
- i, ln, series,
- item;
- if (me.enableMask) {
- me.mixins.mask.onMouseUp.call(me, e);
- }
- // Ask each series if it has an item corresponding to (not necessarily exactly
- // on top of) the current mouse coords. Fire itemmouseup event.
- for (i = 0, ln = seriesItems.length; i < ln; i++) {
- series = seriesItems[i];
- if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
- if (series.getItemForPoint) {
- item = series.getItemForPoint(position[0], position[1]);
- if (item) {
- series.fireEvent('itemmouseup', item);
- }
- }
- }
- }
- },
- // @private wrap the mouse move event so it can be delegated to the series.
- onMouseMove: function(e) {
- var me = this,
- position = me.getEventXY(e),
- seriesItems = me.series.items,
- i, ln, series,
- item, last, storeItem, storeField;
-
- if (me.enableMask) {
- me.mixins.mask.onMouseMove.call(me, e);
- }
- // Ask each series if it has an item corresponding to (not necessarily exactly
- // on top of) the current mouse coords. Fire itemmouseover/out events.
- for (i = 0, ln = seriesItems.length; i < ln; i++) {
- series = seriesItems[i];
- if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
- if (series.getItemForPoint) {
- item = series.getItemForPoint(position[0], position[1]);
- last = series._lastItemForPoint;
- storeItem = series._lastStoreItem;
- storeField = series._lastStoreField;
- if (item !== last || item && (item.storeItem != storeItem || item.storeField != storeField)) {
- if (last) {
- series.fireEvent('itemmouseout', last);
- delete series._lastItemForPoint;
- delete series._lastStoreField;
- delete series._lastStoreItem;
- }
- if (item) {
- series.fireEvent('itemmouseover', item);
- series._lastItemForPoint = item;
- series._lastStoreItem = item.storeItem;
- series._lastStoreField = item.storeField;
- }
- }
- }
- } else {
- last = series._lastItemForPoint;
- if (last) {
- series.fireEvent('itemmouseout', last);
- delete series._lastItemForPoint;
- delete series._lastStoreField;
- delete series._lastStoreItem;
- }
- }
- }
- },
- // @private handle mouse leave event.
- onMouseLeave: function(e) {
- var me = this,
- seriesItems = me.series.items,
- i, ln, series;
- if (me.enableMask) {
- me.mixins.mask.onMouseLeave.call(me, e);
- }
- for (i = 0, ln = seriesItems.length; i < ln; i++) {
- series = seriesItems[i];
- delete series._lastItemForPoint;
- }
- },
- // @private buffered refresh for when we update the store
- delayRefresh: function() {
- var me = this;
- if (!me.refreshTask) {
- me.refreshTask = new Ext.util.DelayedTask(me.refresh, me);
- }
- me.refreshTask.delay(me.refreshBuffer);
- },
- // @private
- refresh: function() {
- var me = this;
-
- if (me.rendered && me.curWidth !== undefined && me.curHeight !== undefined) {
- if (!me.isVisible(true) && !me.refreshPending) {
- me.setShowListeners('mon');
- me.refreshPending = true;
- return;
- }
- if (me.fireEvent('beforerefresh', me) !== false) {
- me.redraw();
- me.fireEvent('refresh', me);
- }
- }
- },
-
- onShow: function(){
- var me = this;
- me.callParent(arguments);
- if (me.refreshPending) {
- me.delayRefresh();
- me.setShowListeners('mun');
- }
- delete me.refreshPending;
- },
-
- setShowListeners: function(method){
- var me = this;
- me[method](Ext.container.Container.hierarchyEventSource, {
- scope: me,
- single: true,
- show: me.forceRefresh,
- expand: me.forceRefresh
- });
- },
-
- forceRefresh: function(container) {
- var me = this;
- if (me.isDescendantOf(container) && me.refreshPending) {
- // Add unbind here, because either expand/show could be fired,
- // so be sure to unbind the listener that didn't
- me.setShowListeners('mun');
- me.delayRefresh();
- }
- delete me.refreshPending;
- },
- bindStore: function(store, initial) {
- var me = this;
- me.mixins.bindable.bindStore.apply(me, arguments);
- if (me.store && !initial) {
- me.refresh();
- }
- },
-
- getStoreListeners: function() {
- var refresh = this.refresh,
- delayRefresh = this.delayRefresh;
-
- return {
- refresh: refresh,
- add: delayRefresh,
- remove: delayRefresh,
- update: delayRefresh,
- clear: refresh
- };
- },
- // @private Create Axis
- initializeAxis: function(axis) {
- var me = this,
- chartBBox = me.chartBBox,
- w = chartBBox.width,
- h = chartBBox.height,
- x = chartBBox.x,
- y = chartBBox.y,
- themeAttrs = me.themeAttrs,
- config = {
- chart: me
- };
- if (themeAttrs) {
- config.axisStyle = Ext.apply({}, themeAttrs.axis);
- config.axisLabelLeftStyle = Ext.apply({}, themeAttrs.axisLabelLeft);
- config.axisLabelRightStyle = Ext.apply({}, themeAttrs.axisLabelRight);
- config.axisLabelTopStyle = Ext.apply({}, themeAttrs.axisLabelTop);
- config.axisLabelBottomStyle = Ext.apply({}, themeAttrs.axisLabelBottom);
- config.axisTitleLeftStyle = Ext.apply({}, themeAttrs.axisTitleLeft);
- config.axisTitleRightStyle = Ext.apply({}, themeAttrs.axisTitleRight);
- config.axisTitleTopStyle = Ext.apply({}, themeAttrs.axisTitleTop);
- config.axisTitleBottomStyle = Ext.apply({}, themeAttrs.axisTitleBottom);
- }
- switch (axis.position) {
- case 'top':
- Ext.apply(config, {
- length: w,
- width: h,
- x: x,
- y: y
- });
- break;
- case 'bottom':
- Ext.apply(config, {
- length: w,
- width: h,
- x: x,
- y: h
- });
- break;
- case 'left':
- Ext.apply(config, {
- length: h,
- width: w,
- x: x,
- y: h
- });
- break;
- case 'right':
- Ext.apply(config, {
- length: h,
- width: w,
- x: w,
- y: h
- });
- break;
- }
- if (!axis.chart) {
- Ext.apply(config, axis);
- axis = me.axes.replace(Ext.createByAlias('axis.' + axis.type.toLowerCase(), config));
- }
- else {
- Ext.apply(axis, config);
- }
- },
- <span id='Ext-chart-Chart-method-alignAxes'> /**
- </span> * @private Adjust the dimensions and positions of each axis and the chart body area after accounting
- * for the space taken up on each side by the axes and legend.
- */
- alignAxes: function() {
- var me = this,
- axes = me.axes,
- axesItems = axes.items,
- axis,
- legend = me.legend,
- edges = ['top', 'right', 'bottom', 'left'],
- edge,
- i, ln,
- chartBBox,
- insetPadding = me.insetPadding,
- insets = {
- top: insetPadding,
- right: insetPadding,
- bottom: insetPadding,
- left: insetPadding
- },
- isVertical, bbox, pos;
- function getAxis(edge) {
- var i = axes.findIndex('position', edge);
- return (i < 0) ? null : axes.getAt(i);
- }
- // Find the space needed by axes and legend as a positive inset from each edge
- for (i = 0, ln = edges.length; i < ln; i++) {
- edge = edges[i];
- isVertical = (edge === 'left' || edge === 'right');
- axis = getAxis(edge);
- // Add legend size if it's on this edge
- if (legend !== false) {
- if (legend.position === edge) {
- bbox = legend.getBBox();
- insets[edge] += (isVertical ? bbox.width : bbox.height) + insets[edge];
- }
- }
- // Add axis size if there's one on this edge only if it has been
- //drawn before.
- if (axis && axis.bbox) {
- bbox = axis.bbox;
- insets[edge] += (isVertical ? bbox.width : bbox.height);
- }
- }
- // Build the chart bbox based on the collected inset values
- chartBBox = {
- x: insets.left,
- y: insets.top,
- width: me.curWidth - insets.left - insets.right,
- height: me.curHeight - insets.top - insets.bottom
- };
- me.chartBBox = chartBBox;
- // Go back through each axis and set its length and position based on the
- // corresponding edge of the chartBBox
- for (i = 0, ln = axesItems.length; i < ln; i++) {
- axis = axesItems[i];
- pos = axis.position;
- isVertical = (pos === 'left' || pos === 'right');
- axis.x = (pos === 'right' ? chartBBox.x + chartBBox.width : chartBBox.x);
- axis.y = (pos === 'top' ? chartBBox.y : chartBBox.y + chartBBox.height);
- axis.width = (isVertical ? chartBBox.width : chartBBox.height);
- axis.length = (isVertical ? chartBBox.height : chartBBox.width);
- }
- },
- // @private initialize the series.
- initializeSeries: function(series, idx) {
- var me = this,
- themeAttrs = me.themeAttrs,
- seriesObj, markerObj, seriesThemes, st,
- markerThemes, colorArrayStyle = [],
- i = 0, l,
- config = {
- chart: me,
- seriesId: series.seriesId
- };
- if (themeAttrs) {
- seriesThemes = themeAttrs.seriesThemes;
- markerThemes = themeAttrs.markerThemes;
- seriesObj = Ext.apply({}, themeAttrs.series);
- markerObj = Ext.apply({}, themeAttrs.marker);
- config.seriesStyle = Ext.apply(seriesObj, seriesThemes[idx % seriesThemes.length]);
- config.seriesLabelStyle = Ext.apply({}, themeAttrs.seriesLabel);
- config.markerStyle = Ext.apply(markerObj, markerThemes[idx % markerThemes.length]);
- if (themeAttrs.colors) {
- config.colorArrayStyle = themeAttrs.colors;
- } else {
- colorArrayStyle = [];
- for (l = seriesThemes.length; i < l; i++) {
- st = seriesThemes[i];
- if (st.fill || st.stroke) {
- colorArrayStyle.push(st.fill || st.stroke);
- }
- }
- if (colorArrayStyle.length) {
- config.colorArrayStyle = colorArrayStyle;
- }
- }
- config.seriesIdx = idx;
- }
- if (series instanceof Ext.chart.series.Series) {
- Ext.apply(series, config);
- } else {
- Ext.applyIf(config, series);
- series = me.series.replace(Ext.createByAlias('series.' + series.type.toLowerCase(), config));
- }
- if (series.initialize) {
- series.initialize();
- }
- },
- // @private
- getMaxGutter: function() {
- var me = this,
- seriesItems = me.series.items,
- i, ln, series,
- maxGutter = [0, 0],
- gutter;
- for (i = 0, ln = seriesItems.length; i < ln; i++) {
- series = seriesItems[i];
- gutter = series.getGutters && series.getGutters() || [0, 0];
- maxGutter[0] = Math.max(maxGutter[0], gutter[0]);
- maxGutter[1] = Math.max(maxGutter[1], gutter[1]);
- }
- me.maxGutter = maxGutter;
- },
- // @private draw axis.
- drawAxis: function(axis) {
- axis.drawAxis();
- },
- // @private draw series.
- drawCharts: function(series) {
- series.triggerafterrender = false;
- series.drawSeries();
- if (!this.animate) {
- series.fireEvent('afterrender');
- }
- },
- <span id='Ext-chart-Chart-method-save'> /**
- </span> * Saves the chart by either triggering a download or returning a string containing the chart data
- * as SVG. The action depends on the export type specified in the passed configuration. The chart
- * will be exported using either the {@link Ext.draw.engine.SvgExporter} or the {@link Ext.draw.engine.ImageExporter}
- * classes.
- *
- * Possible export types:
- *
- * - 'image/png'
- * - 'image/jpeg',
- * - 'image/svg+xml'
- *
- * If 'image/svg+xml' is specified, the SvgExporter will be used.
- * If 'image/png' or 'image/jpeg' are specified, the ImageExporter will be used. This exporter
- * must post the SVG data to a remote server to have the data processed, see the {@link Ext.draw.engine.ImageExporter}
- * for more details.
- *
- * Example usage:
- *
- * chart.save({
- * type: 'image/png'
- * });
- *
- * @param {Object} [config] The configuration to be passed to the exporter.
- * See the export method for the appropriate exporter for the relevant
- * configuration options
- * @return {Object} See the return types for the appropriate exporter
- */
- save: function(config){
- return Ext.draw.Surface.save(this.surface, config);
- },
- // @private remove gently.
- destroy: function() {
- Ext.destroy(this.surface);
- this.bindStore(null);
- this.callParent(arguments);
- }
- });
- </pre>
- </body>
- </html>
|