Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / Legend.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="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../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-Legend'>/**
19 </span> * @class Ext.chart.Legend
20  *
21  * Defines a legend for a chart's series.
22  * The 'chart' member must be set prior to rendering.
23  * The legend class displays a list of legend items each of them related with a
24  * series being rendered. In order to render the legend item of the proper series
25  * the series configuration object must have `showInSeries` set to true.
26  *
27  * The legend configuration object accepts a `position` as parameter.
28  * The `position` parameter can be `left`, `right`
29  * `top` or `bottom`. For example:
30  *
31  *     legend: {
32  *         position: 'right'
33  *     },
34  * 
35  * Full example:
36     &lt;pre&gt;&lt;code&gt;
37     var store = Ext.create('Ext.data.JsonStore', {
38         fields: ['name', 'data1', 'data2', 'data3', 'data4', 'data5'],
39         data: [
40             {'name':'metric one', 'data1':10, 'data2':12, 'data3':14, 'data4':8, 'data5':13},
41             {'name':'metric two', 'data1':7, 'data2':8, 'data3':16, 'data4':10, 'data5':3},
42             {'name':'metric three', 'data1':5, 'data2':2, 'data3':14, 'data4':12, 'data5':7},
43             {'name':'metric four', 'data1':2, 'data2':14, 'data3':6, 'data4':1, 'data5':23},
44             {'name':'metric five', 'data1':27, 'data2':38, 'data3':36, 'data4':13, 'data5':33}                                                
45         ]
46     });
47     
48     Ext.create('Ext.chart.Chart', {
49         renderTo: Ext.getBody(),
50         width: 500,
51         height: 300,
52         animate: true,
53         store: store,
54         shadow: true,
55         theme: 'Category1',
56         legend: {
57             position: 'top'
58         },
59          axes: [{
60                 type: 'Numeric',
61                 grid: true,
62                 position: 'left',
63                 fields: ['data1', 'data2', 'data3', 'data4', 'data5'],
64                 title: 'Sample Values',
65                 grid: {
66                     odd: {
67                         opacity: 1,
68                         fill: '#ddd',
69                         stroke: '#bbb',
70                         'stroke-width': 1
71                     }
72                 },
73                 minimum: 0,
74                 adjustMinimumByMajorUnit: 0
75             }, {
76                 type: 'Category',
77                 position: 'bottom',
78                 fields: ['name'],
79                 title: 'Sample Metrics',
80                 grid: true,
81                 label: {
82                     rotate: {
83                         degrees: 315
84                     }
85                 }
86         }],
87         series: [{
88             type: 'area',
89             highlight: false,
90             axis: 'left',
91             xField: 'name',
92             yField: ['data1', 'data2', 'data3', 'data4', 'data5'],
93             style: {
94                 opacity: 0.93
95             }
96         }]
97     });    
98     &lt;/code&gt;&lt;/pre&gt;    
99  *
100  */
101 Ext.define('Ext.chart.Legend', {
102
103     /* Begin Definitions */
104
105     requires: ['Ext.chart.LegendItem'],
106
107     /* End Definitions */
108
109 <span id='Ext-chart-Legend-cfg-visible'>    /**
110 </span>     * @cfg {Boolean} visible
111      * Whether or not the legend should be displayed.
112      */
113     visible: true,
114
115 <span id='Ext-chart-Legend-cfg-position'>    /**
116 </span>     * @cfg {String} position
117      * The position of the legend in relation to the chart. One of: &quot;top&quot;,
118      * &quot;bottom&quot;, &quot;left&quot;, &quot;right&quot;, or &quot;float&quot;. If set to &quot;float&quot;, then the legend
119      * box will be positioned at the point denoted by the x and y parameters.
120      */
121     position: 'bottom',
122
123 <span id='Ext-chart-Legend-cfg-x'>    /**
124 </span>     * @cfg {Number} x
125      * X-position of the legend box. Used directly if position is set to &quot;float&quot;, otherwise 
126      * it will be calculated dynamically.
127      */
128     x: 0,
129
130 <span id='Ext-chart-Legend-cfg-y'>    /**
131 </span>     * @cfg {Number} y
132      * Y-position of the legend box. Used directly if position is set to &quot;float&quot;, otherwise
133      * it will be calculated dynamically.
134      */
135     y: 0,
136
137 <span id='Ext-chart-Legend-cfg-labelFont'>    /**
138 </span>     * @cfg {String} labelFont
139      * Font to be used for the legend labels, eg '12px Helvetica'
140      */
141     labelFont: '12px Helvetica, sans-serif',
142
143 <span id='Ext-chart-Legend-cfg-boxStroke'>    /**
144 </span>     * @cfg {String} boxStroke
145      * Style of the stroke for the legend box
146      */
147     boxStroke: '#000',
148
149 <span id='Ext-chart-Legend-cfg-boxStrokeWidth'>    /**
150 </span>     * @cfg {String} boxStrokeWidth
151      * Width of the stroke for the legend box
152      */
153     boxStrokeWidth: 1,
154
155 <span id='Ext-chart-Legend-cfg-boxFill'>    /**
156 </span>     * @cfg {String} boxFill
157      * Fill style for the legend box
158      */
159     boxFill: '#FFF',
160
161 <span id='Ext-chart-Legend-cfg-itemSpacing'>    /**
162 </span>     * @cfg {Number} itemSpacing
163      * Amount of space between legend items
164      */
165     itemSpacing: 10,
166
167 <span id='Ext-chart-Legend-cfg-padding'>    /**
168 </span>     * @cfg {Number} padding
169      * Amount of padding between the legend box's border and its items
170      */
171     padding: 5,
172
173     // @private
174     width: 0,
175     // @private
176     height: 0,
177
178 <span id='Ext-chart-Legend-cfg-boxZIndex'>    /**
179 </span>     * @cfg {Number} boxZIndex
180      * Sets the z-index for the legend. Defaults to 100.
181      */
182     boxZIndex: 100,
183
184 <span id='Ext-chart-Legend-method-constructor'>    /**
185 </span>     * Creates new Legend.
186      * @param {Object} config  (optional) Config object.
187      */
188     constructor: function(config) {
189         var me = this;
190         if (config) {
191             Ext.apply(me, config);
192         }
193         me.items = [];
194 <span id='Ext-chart-Legend-property-isVertical'>        /**
195 </span>         * Whether the legend box is oriented vertically, i.e. if it is on the left or right side or floating.
196          * @type {Boolean}
197          */
198         me.isVertical = (&quot;left|right|float&quot;.indexOf(me.position) !== -1);
199         
200         // cache these here since they may get modified later on
201         me.origX = me.x;
202         me.origY = me.y;
203     },
204
205 <span id='Ext-chart-Legend-method-create'>    /**
206 </span>     * @private Create all the sprites for the legend
207      */
208     create: function() {
209         var me = this;
210         me.createItems();
211         if (!me.created &amp;&amp; me.isDisplayed()) {
212             me.createBox();
213             me.created = true;
214
215             // Listen for changes to series titles to trigger regeneration of the legend
216             me.chart.series.each(function(series) {
217                 series.on('titlechange', function() {
218                     me.create();
219                     me.updatePosition();
220                 });
221             });
222         }
223     },
224
225 <span id='Ext-chart-Legend-method-isDisplayed'>    /**
226 </span>     * @private Determine whether the legend should be displayed. Looks at the legend's 'visible' config,
227      * and also the 'showInLegend' config for each of the series.
228      */
229     isDisplayed: function() {
230         return this.visible &amp;&amp; this.chart.series.findIndex('showInLegend', true) !== -1;
231     },
232
233 <span id='Ext-chart-Legend-method-createItems'>    /**
234 </span>     * @private Create the series markers and labels
235      */
236     createItems: function() {
237         var me = this,
238             chart = me.chart,
239             surface = chart.surface,
240             items = me.items,
241             padding = me.padding,
242             itemSpacing = me.itemSpacing,
243             spacingOffset = 2,
244             maxWidth = 0,
245             maxHeight = 0,
246             totalWidth = 0,
247             totalHeight = 0,
248             vertical = me.isVertical,
249             math = Math,
250             mfloor = math.floor,
251             mmax = math.max,
252             index = 0, 
253             i = 0, 
254             len = items ? items.length : 0,
255             x, y, spacing, item, bbox, height, width;
256
257         //remove all legend items
258         if (len) {
259             for (; i &lt; len; i++) {
260                 items[i].destroy();
261             }
262         }
263         //empty array
264         items.length = [];
265         // Create all the item labels, collecting their dimensions and positioning each one
266         // properly in relation to the previous item
267         chart.series.each(function(series, i) {
268             if (series.showInLegend) {
269                 Ext.each([].concat(series.yField), function(field, j) {
270                     item = Ext.create('Ext.chart.LegendItem', {
271                         legend: this,
272                         series: series,
273                         surface: chart.surface,
274                         yFieldIndex: j
275                     });
276                     bbox = item.getBBox();
277
278                     //always measure from x=0, since not all markers go all the way to the left
279                     width = bbox.width; 
280                     height = bbox.height;
281
282                     if (i + j === 0) {
283                         spacing = vertical ? padding + height / 2 : padding;
284                     }
285                     else {
286                         spacing = itemSpacing / (vertical ? 2 : 1);
287                     }
288                     // Set the item's position relative to the legend box
289                     item.x = mfloor(vertical ? padding : totalWidth + spacing);
290                     item.y = mfloor(vertical ? totalHeight + spacing : padding + height / 2);
291
292                     // Collect cumulative dimensions
293                     totalWidth += width + spacing;
294                     totalHeight += height + spacing;
295                     maxWidth = mmax(maxWidth, width);
296                     maxHeight = mmax(maxHeight, height);
297
298                     items.push(item);
299                 }, this);
300             }
301         }, me);
302
303         // Store the collected dimensions for later
304         me.width = mfloor((vertical ? maxWidth : totalWidth) + padding * 2);
305         if (vertical &amp;&amp; items.length === 1) {
306             spacingOffset = 1;
307         }
308         me.height = mfloor((vertical ? totalHeight - spacingOffset * spacing : maxHeight) + (padding * 2));
309         me.itemHeight = maxHeight;
310     },
311
312 <span id='Ext-chart-Legend-method-getBBox'>    /**
313 </span>     * @private Get the bounds for the legend's outer box
314      */
315     getBBox: function() {
316         var me = this;
317         return {
318             x: Math.round(me.x) - me.boxStrokeWidth / 2,
319             y: Math.round(me.y) - me.boxStrokeWidth / 2,
320             width: me.width,
321             height: me.height
322         };
323     },
324
325 <span id='Ext-chart-Legend-method-createBox'>    /**
326 </span>     * @private Create the box around the legend items
327      */
328     createBox: function() {
329         var me = this,
330             box = me.boxSprite = me.chart.surface.add(Ext.apply({
331                 type: 'rect',
332                 stroke: me.boxStroke,
333                 &quot;stroke-width&quot;: me.boxStrokeWidth,
334                 fill: me.boxFill,
335                 zIndex: me.boxZIndex
336             }, me.getBBox()));
337         box.redraw();
338     },
339
340 <span id='Ext-chart-Legend-method-updatePosition'>    /**
341 </span>     * @private Update the position of all the legend's sprites to match its current x/y values
342      */
343     updatePosition: function() {
344         var me = this,
345             x, y,
346             legendWidth = me.width,
347             legendHeight = me.height,
348             padding = me.padding,
349             chart = me.chart,
350             chartBBox = chart.chartBBox,
351             insets = chart.insetPadding,
352             chartWidth = chartBBox.width - (insets * 2),
353             chartHeight = chartBBox.height - (insets * 2),
354             chartX = chartBBox.x + insets,
355             chartY = chartBBox.y + insets,
356             surface = chart.surface,
357             mfloor = Math.floor;
358         
359         if (me.isDisplayed()) {
360             // Find the position based on the dimensions
361             switch(me.position) {
362                 case &quot;left&quot;:
363                     x = insets;
364                     y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
365                     break;
366                 case &quot;right&quot;:
367                     x = mfloor(surface.width - legendWidth) - insets;
368                     y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
369                     break;
370                 case &quot;top&quot;:
371                     x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
372                     y = insets;
373                     break;
374                 case &quot;bottom&quot;:
375                     x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
376                     y = mfloor(surface.height - legendHeight) - insets;
377                     break;
378                 default:
379                     x = mfloor(me.origX) + insets;
380                     y = mfloor(me.origY) + insets;
381             }
382             me.x = x;
383             me.y = y;
384
385             // Update the position of each item
386             Ext.each(me.items, function(item) {
387                 item.updatePosition();
388             });
389             // Update the position of the outer box
390             me.boxSprite.setAttributes(me.getBBox(), true);
391         }
392     }
393 });</pre>
394 </body>
395 </html>