123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- <!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-Legend'>/**
- </span> * @class Ext.chart.Legend
- *
- * Defines a legend for a chart's series.
- * The 'chart' member must be set prior to rendering.
- * The legend class displays a list of legend items each of them related with a
- * series being rendered. In order to render the legend item of the proper series
- * the series configuration object must have `showInLegend` set to true.
- *
- * The legend configuration object accepts a `position` as parameter.
- * The `position` parameter can be `left`, `right`
- * `top` or `bottom`. For example:
- *
- * legend: {
- * position: 'right'
- * },
- *
- * ## Example
- *
- * @example
- * var store = Ext.create('Ext.data.JsonStore', {
- * fields: ['name', 'data1', 'data2', 'data3', 'data4', 'data5'],
- * data: [
- * { 'name': 'metric one', 'data1': 10, 'data2': 12, 'data3': 14, 'data4': 8, 'data5': 13 },
- * { 'name': 'metric two', 'data1': 7, 'data2': 8, 'data3': 16, 'data4': 10, 'data5': 3 },
- * { 'name': 'metric three', 'data1': 5, 'data2': 2, 'data3': 14, 'data4': 12, 'data5': 7 },
- * { 'name': 'metric four', 'data1': 2, 'data2': 14, 'data3': 6, 'data4': 1, 'data5': 23 },
- * { 'name': 'metric five', 'data1': 27, 'data2': 38, 'data3': 36, 'data4': 13, 'data5': 33 }
- * ]
- * });
- *
- * Ext.create('Ext.chart.Chart', {
- * renderTo: Ext.getBody(),
- * width: 500,
- * height: 300,
- * animate: true,
- * store: store,
- * shadow: true,
- * theme: 'Category1',
- * legend: {
- * position: 'top'
- * },
- * axes: [
- * {
- * type: 'Numeric',
- * grid: true,
- * position: 'left',
- * fields: ['data1', 'data2', 'data3', 'data4', 'data5'],
- * title: 'Sample Values',
- * grid: {
- * odd: {
- * opacity: 1,
- * fill: '#ddd',
- * stroke: '#bbb',
- * 'stroke-width': 1
- * }
- * },
- * minimum: 0,
- * adjustMinimumByMajorUnit: 0
- * },
- * {
- * type: 'Category',
- * position: 'bottom',
- * fields: ['name'],
- * title: 'Sample Metrics',
- * grid: true,
- * label: {
- * rotate: {
- * degrees: 315
- * }
- * }
- * }
- * ],
- * series: [{
- * type: 'area',
- * highlight: false,
- * axis: 'left',
- * xField: 'name',
- * yField: ['data1', 'data2', 'data3', 'data4', 'data5'],
- * style: {
- * opacity: 0.93
- * }
- * }]
- * });
- */
- Ext.define('Ext.chart.Legend', {
- /* Begin Definitions */
- requires: ['Ext.chart.LegendItem'],
- /* End Definitions */
- <span id='Ext-chart-Legend-cfg-visible'> /**
- </span> * @cfg {Boolean} visible
- * Whether or not the legend should be displayed.
- */
- visible: true,
-
- <span id='Ext-chart-Legend-cfg-update'> /**
- </span> * @cfg {Boolean} update
- * If set to true the legend will be refreshed when the chart is.
- * This is useful to update the legend items if series are
- * added/removed/updated from the chart. Default is true.
- */
- update: true,
- <span id='Ext-chart-Legend-cfg-position'> /**
- </span> * @cfg {String} position
- * The position of the legend in relation to the chart. One of: "top",
- * "bottom", "left", "right", or "float". If set to "float", then the legend
- * box will be positioned at the point denoted by the x and y parameters.
- */
- position: 'bottom',
- <span id='Ext-chart-Legend-cfg-x'> /**
- </span> * @cfg {Number} x
- * X-position of the legend box. Used directly if position is set to "float", otherwise
- * it will be calculated dynamically.
- */
- x: 0,
- <span id='Ext-chart-Legend-cfg-y'> /**
- </span> * @cfg {Number} y
- * Y-position of the legend box. Used directly if position is set to "float", otherwise
- * it will be calculated dynamically.
- */
- y: 0,
- <span id='Ext-chart-Legend-cfg-labelColor'> /**
- </span> * @cfg {String} labelColor
- * Color to be used for the legend labels, eg '#000'
- */
- labelColor: '#000',
- <span id='Ext-chart-Legend-cfg-labelFont'> /**
- </span> * @cfg {String} labelFont
- * Font to be used for the legend labels, eg '12px Helvetica'
- */
- labelFont: '12px Helvetica, sans-serif',
- <span id='Ext-chart-Legend-cfg-boxStroke'> /**
- </span> * @cfg {String} boxStroke
- * Style of the stroke for the legend box
- */
- boxStroke: '#000',
- <span id='Ext-chart-Legend-cfg-boxStrokeWidth'> /**
- </span> * @cfg {String} boxStrokeWidth
- * Width of the stroke for the legend box
- */
- boxStrokeWidth: 1,
- <span id='Ext-chart-Legend-cfg-boxFill'> /**
- </span> * @cfg {String} boxFill
- * Fill style for the legend box
- */
- boxFill: '#FFF',
- <span id='Ext-chart-Legend-cfg-itemSpacing'> /**
- </span> * @cfg {Number} itemSpacing
- * Amount of space between legend items
- */
- itemSpacing: 10,
- <span id='Ext-chart-Legend-cfg-padding'> /**
- </span> * @cfg {Number} padding
- * Amount of padding between the legend box's border and its items
- */
- padding: 5,
- // @private
- width: 0,
- // @private
- height: 0,
- <span id='Ext-chart-Legend-cfg-boxZIndex'> /**
- </span> * @cfg {Number} boxZIndex
- * Sets the z-index for the legend. Defaults to 100.
- */
- boxZIndex: 100,
- <span id='Ext-chart-Legend-method-constructor'> /**
- </span> * Creates new Legend.
- * @param {Object} config (optional) Config object.
- */
- constructor: function(config) {
- var me = this;
- if (config) {
- Ext.apply(me, config);
- }
- me.items = [];
- <span id='Ext-chart-Legend-property-isVertical'> /**
- </span> * Whether the legend box is oriented vertically, i.e. if it is on the left or right side or floating.
- * @type {Boolean}
- */
- me.isVertical = ("left|right|float".indexOf(me.position) !== -1);
- // cache these here since they may get modified later on
- me.origX = me.x;
- me.origY = me.y;
- },
- <span id='Ext-chart-Legend-method-create'> /**
- </span> * @private Create all the sprites for the legend
- */
- create: function() {
- var me = this,
- seriesItems = me.chart.series.items,
- i, ln, series;
- me.createBox();
-
- if (me.rebuild !== false) {
- me.createItems();
- }
-
- if (!me.created && me.isDisplayed()) {
- me.created = true;
- // Listen for changes to series titles to trigger regeneration of the legend
- for (i = 0, ln = seriesItems.length; i < ln; i++) {
- series = seriesItems[i];
- series.on('titlechange', function() {
- me.create();
- me.updatePosition();
- });
- }
- }
- },
- <span id='Ext-chart-Legend-method-isDisplayed'> /**
- </span> * @private Determine whether the legend should be displayed. Looks at the legend's 'visible' config,
- * and also the 'showInLegend' config for each of the series.
- */
- isDisplayed: function() {
- return this.visible && this.chart.series.findIndex('showInLegend', true) !== -1;
- },
- <span id='Ext-chart-Legend-method-createItems'> /**
- </span> * @private Create the series markers and labels
- */
- createItems: function() {
- var me = this,
- chart = me.chart,
- seriesItems = chart.series.items,
- ln, series,
- surface = chart.surface,
- items = me.items,
- padding = me.padding,
- itemSpacing = me.itemSpacing,
- spacingOffset = 2,
- maxWidth = 0,
- maxHeight = 0,
- totalWidth = 0,
- totalHeight = 0,
- vertical = me.isVertical,
- math = Math,
- mfloor = math.floor,
- mmax = math.max,
- index = 0,
- i = 0,
- len = items ? items.length : 0,
- x, y, spacing, item, bbox, height, width,
- fields, field, nFields, j;
- //remove all legend items
- if (len) {
- for (; i < len; i++) {
- items[i].destroy();
- }
- }
- //empty array
- items.length = [];
- // Create all the item labels, collecting their dimensions and positioning each one
- // properly in relation to the previous item
- for (i = 0, ln = seriesItems.length; i < ln; i++) {
- series = seriesItems[i];
- if (series.showInLegend) {
- fields = [].concat(series.yField);
- for (j = 0, nFields = fields.length; j < nFields; j++) {
- field = fields[j];
- item = new Ext.chart.LegendItem({
- legend: this,
- series: series,
- surface: chart.surface,
- yFieldIndex: j
- });
- bbox = item.getBBox();
- //always measure from x=0, since not all markers go all the way to the left
- width = bbox.width;
- height = bbox.height;
- if (i + j === 0) {
- spacing = vertical ? padding + height / 2 : padding;
- }
- else {
- spacing = itemSpacing / (vertical ? 2 : 1);
- }
- // Set the item's position relative to the legend box
- item.x = mfloor(vertical ? padding : totalWidth + spacing);
- item.y = mfloor(vertical ? totalHeight + spacing : padding + height / 2);
- // Collect cumulative dimensions
- totalWidth += width + spacing;
- totalHeight += height + spacing;
- maxWidth = mmax(maxWidth, width);
- maxHeight = mmax(maxHeight, height);
- items.push(item);
- }
- }
- }
- // Store the collected dimensions for later
- me.width = mfloor((vertical ? maxWidth : totalWidth) + padding * 2);
- if (vertical && items.length === 1) {
- spacingOffset = 1;
- }
- me.height = mfloor((vertical ? totalHeight - spacingOffset * spacing : maxHeight) + (padding * 2));
- me.itemHeight = maxHeight;
- },
- <span id='Ext-chart-Legend-method-getBBox'> /**
- </span> * @private Get the bounds for the legend's outer box
- */
- getBBox: function() {
- var me = this;
- return {
- x: Math.round(me.x) - me.boxStrokeWidth / 2,
- y: Math.round(me.y) - me.boxStrokeWidth / 2,
- width: me.width,
- height: me.height
- };
- },
- <span id='Ext-chart-Legend-method-createBox'> /**
- </span> * @private Create the box around the legend items
- */
- createBox: function() {
- var me = this,
- box, bbox;
- if (me.boxSprite) {
- me.boxSprite.destroy();
- }
- bbox = me.getBBox();
- //if some of the dimensions are NaN this means that we
- //cannot set a specific width/height for the legend
- //container. One possibility for this is that there are
- //actually no items to show in the legend, and the legend
- //should be hidden.
- if (isNaN(bbox.width) || isNaN(bbox.height)) {
- me.boxSprite = false;
- return;
- }
-
- box = me.boxSprite = me.chart.surface.add(Ext.apply({
- type: 'rect',
- stroke: me.boxStroke,
- "stroke-width": me.boxStrokeWidth,
- fill: me.boxFill,
- zIndex: me.boxZIndex
- }, bbox));
- box.redraw();
- },
- <span id='Ext-chart-Legend-method-updatePosition'> /**
- </span> * @private Update the position of all the legend's sprites to match its current x/y values
- */
- updatePosition: function() {
- var me = this,
- items = me.items,
- i, ln,
- x, y,
- legendWidth = me.width || 0,
- legendHeight = me.height || 0,
- padding = me.padding,
- chart = me.chart,
- chartBBox = chart.chartBBox,
- insets = chart.insetPadding,
- chartWidth = chartBBox.width - (insets * 2),
- chartHeight = chartBBox.height - (insets * 2),
- chartX = chartBBox.x + insets,
- chartY = chartBBox.y + insets,
- surface = chart.surface,
- mfloor = Math.floor,
- bbox;
- if (me.isDisplayed()) {
- // Find the position based on the dimensions
- switch(me.position) {
- case "left":
- x = insets;
- y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
- break;
- case "right":
- x = mfloor(surface.width - legendWidth) - insets;
- y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
- break;
- case "top":
- x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
- y = insets;
- break;
- case "bottom":
- x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
- y = mfloor(surface.height - legendHeight) - insets;
- break;
- default:
- x = mfloor(me.origX) + insets;
- y = mfloor(me.origY) + insets;
- }
- me.x = x;
- me.y = y;
- // Update the position of each item
- for (i = 0, ln = items.length; i < ln; i++) {
- items[i].updatePosition();
- }
- bbox = me.getBBox();
- //if some of the dimensions are NaN this means that we
- //cannot set a specific width/height for the legend
- //container. One possibility for this is that there are
- //actually no items to show in the legend, and the legend
- //should be hidden.
- if (isNaN(bbox.width) || isNaN(bbox.height)) {
- if (me.boxSprite) {
- me.boxSprite.hide(true);
- }
- } else {
- if (!me.boxSprite) {
- me.createBox();
- }
- // Update the position of the outer box
- me.boxSprite.setAttributes(bbox, true);
- me.boxSprite.show(true);
- }
- }
- },
-
- <span id='Ext-chart-Legend-method-toggle'> /** toggle
- </span> * @param {Boolean} Whether to show or hide the legend.
- *
- */
- toggle: function(show) {
- var me = this,
- i = 0,
- items = me.items,
- len = items.length;
- if (me.boxSprite) {
- if (show) {
- me.boxSprite.show(true);
- } else {
- me.boxSprite.hide(true);
- }
- }
- for (; i < len; ++i) {
- if (show) {
- items[i].show(true);
- } else {
- items[i].hide(true);
- }
- }
- me.visible = show;
- }
- });
- </pre>
- </body>
- </html>
|