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; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-chart-series-Line'>/**
19 </span> * @class Ext.chart.series.Line
20 * @extends Ext.chart.series.Cartesian
22 * Creates a Line Chart. A Line Chart is a useful visualization technique to display quantitative information for different
23 * categories or other real values (as opposed to the bar chart), that can show some progression (or regression) in the dataset.
24 * As with all other series, the Line Series must be appended in the *series* Chart array configuration. See the Chart
25 * documentation for more information. A typical configuration object for the line series could be:
27 * {@img Ext.chart.series.Line/Ext.chart.series.Line.png Ext.chart.series.Line chart series}
29 * var store = Ext.create('Ext.data.JsonStore', {
30 * fields: ['name', 'data1', 'data2', 'data3', 'data4', 'data5'],
32 * {'name':'metric one', 'data1':10, 'data2':12, 'data3':14, 'data4':8, 'data5':13},
33 * {'name':'metric two', 'data1':7, 'data2':8, 'data3':16, 'data4':10, 'data5':3},
34 * {'name':'metric three', 'data1':5, 'data2':2, 'data3':14, 'data4':12, 'data5':7},
35 * {'name':'metric four', 'data1':2, 'data2':14, 'data3':6, 'data4':1, 'data5':23},
36 * {'name':'metric five', 'data1':27, 'data2':38, 'data3':36, 'data4':13, 'data5':33}
40 * Ext.create('Ext.chart.Chart', {
41 * renderTo: Ext.getBody(),
51 * renderer: Ext.util.Format.numberRenderer('0,0')
53 * title: 'Sample Values',
60 * title: 'Sample Metrics'
96 * In this configuration we're adding two series (or lines), one bound to the `data1`
97 * property of the store and the other to `data3`. The type for both configurations is
98 * `line`. The `xField` for both series is the same, the name propert of the store.
99 * Both line series share the same axis, the left axis. You can set particular marker
100 * configuration by adding properties onto the markerConfig object. Both series have
101 * an object as highlight so that markers animate smoothly to the properties in highlight
102 * when hovered. The second series has `fill=true` which means that the line will also
103 * have an area below it of the same color.
105 * **Note:** In the series definition remember to explicitly set the axis to bind the
106 * values of the line series to. This can be done by using the `axis` configuration property.
108 Ext.define('Ext.chart.series.Line', {
110 /* Begin Definitions */
112 extend: 'Ext.chart.series.Cartesian',
114 alternateClassName: ['Ext.chart.LineSeries', 'Ext.chart.LineChart'],
116 requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.draw.Draw', 'Ext.fx.Anim'],
118 /* End Definitions */
122 alias: 'series.line',
124 <span id='Ext-chart-series-Line-cfg-axis'> /**
125 </span> * @cfg {String} axis
126 * The position of the axis to bind the values to. Possible values are 'left', 'bottom', 'top' and 'right'.
127 * You must explicitly set this value to bind the values of the line series to the ones in the axis, otherwise a
128 * relative scale will be used.
131 <span id='Ext-chart-series-Line-cfg-selectionTolerance'> /**
132 </span> * @cfg {Number} selectionTolerance
133 * The offset distance from the cursor position to the line series to trigger events (then used for highlighting series, etc).
135 selectionTolerance: 20,
137 <span id='Ext-chart-series-Line-cfg-showMarkers'> /**
138 </span> * @cfg {Boolean} showMarkers
139 * Whether markers should be displayed at the data points along the line. If true,
140 * then the {@link #markerConfig} config item will determine the markers' styling.
144 <span id='Ext-chart-series-Line-cfg-markerConfig'> /**
145 </span> * @cfg {Object} markerConfig
146 * The display style for the markers. Only used if {@link #showMarkers} is true.
147 * The markerConfig is a configuration object containing the same set of properties defined in
148 * the Sprite class. For example, if we were to set red circles as markers to the line series we could
151 <pre><code>
157 </code></pre>
162 <span id='Ext-chart-series-Line-cfg-style'> /**
163 </span> * @cfg {Object} style
164 * An object containing styles for the visualization lines. These styles will override the theme styles.
165 * Some options contained within the style object will are described next.
169 <span id='Ext-chart-series-Line-cfg-smooth'> /**
170 </span> * @cfg {Boolean} smooth
171 * If true, the line will be smoothed/rounded around its points, otherwise straight line
172 * segments will be drawn. Defaults to false.
176 <span id='Ext-chart-series-Line-cfg-fill'> /**
177 </span> * @cfg {Boolean} fill
178 * If true, the area below the line will be filled in using the {@link #style.eefill} and
179 * {@link #style.opacity} config properties. Defaults to false.
183 constructor: function(config) {
184 this.callParent(arguments);
186 surface = me.chart.surface,
187 shadow = me.chart.shadow,
189 Ext.apply(me, config, {
194 "stroke-width": 6,
195 "stroke-opacity": 0.05,
196 stroke: 'rgb(0, 0, 0)',
202 "stroke-width": 4,
203 "stroke-opacity": 0.1,
204 stroke: 'rgb(0, 0, 0)',
210 "stroke-width": 2,
211 "stroke-opacity": 0.15,
212 stroke: 'rgb(0, 0, 0)',
219 me.group = surface.getGroup(me.seriesId);
220 if (me.showMarkers) {
221 me.markerGroup = surface.getGroup(me.seriesId + '-markers');
224 for (i = 0, l = this.shadowAttributes.length; i < l; i++) {
225 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
230 // @private makes an average of points when there are more data points than pixels to be rendered.
231 shrink: function(xValues, yValues, size) {
232 // Start at the 2nd point...
233 var len = xValues.length,
234 ratio = Math.floor(len / size),
241 for (; i < len; ++i) {
242 xSum += xValues[i] || 0;
243 ySum += yValues[i] || 0;
244 if (i % ratio == 0) {
245 xRes.push(xSum/ratio);
246 yRes.push(ySum/ratio);
257 <span id='Ext-chart-series-Line-method-drawSeries'> /**
258 </span> * Draws the series for the current chart.
260 drawSeries: function() {
263 store = chart.substore || chart.store,
264 surface = chart.surface,
265 chartBBox = chart.chartBBox,
268 gutterX = chart.maxGutter[0],
269 gutterY = chart.maxGutter[1],
270 showMarkers = me.showMarkers,
271 markerGroup = me.markerGroup,
272 enableShadows = chart.shadow,
273 shadowGroups = me.shadowGroups,
274 shadowAttributes = this.shadowAttributes,
275 lnsh = shadowGroups.length,
276 dummyPath = ["M"],
277 path = ["M"],
278 markerIndex = chart.markerIndex,
279 axes = [].concat(me.axis),
287 markerStyle = me.markerStyle,
288 seriesStyle = me.seriesStyle,
289 seriesLabelStyle = me.seriesLabelStyle,
290 colorArrayStyle = me.colorArrayStyle,
291 colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
298 seriesIdx = me.seriesIdx, shadows, shadow, shindex, fromPath, fill, fillPath, rendererAttributes,
299 x, y, prevX, prevY, firstY, markerCount, i, j, ln, axis, ends, marker, markerAux, item, xValue,
300 yValue, coords, xScale, yScale, minX, maxX, minY, maxY, line, animation, endMarkerStyle,
301 endLineStyle, type, props, firstMarker, count;
303 //if store is empty then there's nothing to draw.
304 if (!store || !store.getCount()) {
308 //prepare style objects for line and markers
309 endMarkerStyle = Ext.apply(markerStyle, me.markerConfig);
310 type = endMarkerStyle.type;
311 delete endMarkerStyle.type;
312 endLineStyle = Ext.apply(seriesStyle, me.style);
313 //if no stroke with is specified force it to 0.5 because this is
314 //about making *lines*
315 if (!endLineStyle['stroke-width']) {
316 endLineStyle['stroke-width'] = 0.5;
318 //If we're using a time axis and we need to translate the points,
319 //then reuse the first markers as the last markers.
320 if (markerIndex && markerGroup && markerGroup.getCount()) {
321 for (i = 0; i < markerIndex; i++) {
322 marker = markerGroup.getAt(i);
323 markerGroup.remove(marker);
324 markerGroup.add(marker);
325 markerAux = markerGroup.getAt(markerGroup.getCount() - 2);
326 marker.setAttributes({
330 x: markerAux.attr.translation.x,
331 y: markerAux.attr.translation.y
337 me.unHighlightItem();
338 me.cleanHighlights();
343 me.clipRect = [bbox.x, bbox.y, bbox.width, bbox.height];
345 chart.axes.each(function(axis) {
346 //only apply position calculations to axes that affect this series
347 //this means the axis in the position referred by this series and also
348 //the axis in the other coordinate for this series. For example: (left, top|bottom),
349 //or (top, left|right), etc.
350 if (axis.position == me.axis || axis.position != posHash[me.axis]) {
352 if (axis.type != 'Numeric') {
356 numericAxis = (numericAxis && axis.type == 'Numeric');
358 ends = axis.calcEnds();
359 if (axis.position == 'top' || axis.position == 'bottom') {
371 //If there's only one axis specified for a series, then we set the default type of the other
372 //axis to a category axis. So in this case numericAxis, which would be true if both axes affecting
373 //the series are numeric should be false.
374 if (numericAxis && axisCount == 1) {
378 // If a field was specified without a corresponding axis, create one to get bounds
379 //only do this for the axis where real values are bound (that's why we check for
381 if (me.xField && !Ext.isNumber(minX)) {
382 if (me.axis == 'bottom' || me.axis == 'top') {
383 axis = Ext.create('Ext.chart.axis.Axis', {
385 fields: [].concat(me.xField)
389 } else if (numericAxis) {
390 axis = Ext.create('Ext.chart.axis.Axis', {
392 fields: [].concat(me.xField),
400 if (me.yField && !Ext.isNumber(minY)) {
401 if (me.axis == 'right' || me.axis == 'left') {
402 axis = Ext.create('Ext.chart.axis.Axis', {
404 fields: [].concat(me.yField)
408 } else if (numericAxis) {
409 axis = Ext.create('Ext.chart.axis.Axis', {
411 fields: [].concat(me.yField),
421 xScale = bbox.width / (store.getCount() - 1);
424 xScale = bbox.width / (maxX - minX);
429 yScale = bbox.height / (store.getCount() - 1);
432 yScale = bbox.height / (maxY - minY);
435 store.each(function(record, i) {
436 xValue = record.get(me.xField);
437 yValue = record.get(me.yField);
438 //skip undefined values
439 if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
441 if (Ext.isDefined(Ext.global.console)) {
442 Ext.global.console.warn("[Ext.chart.series.Line] Skipping a store element with an undefined value at ", record, xValue, yValue);
448 if (typeof xValue == 'string' || typeof xValue == 'object'
449 //set as uniform distribution if the axis is a category axis.
450 || (me.axis != 'top' && me.axis != 'bottom' && !numericAxis)) {
453 if (typeof yValue == 'string' || typeof yValue == 'object'
454 //set as uniform distribution if the axis is a category axis.
455 || (me.axis != 'left' && me.axis != 'right' && !numericAxis)) {
458 xValues.push(xValue);
459 yValues.push(yValue);
463 if (ln > bbox.width) {
464 coords = me.shrink(xValues, yValues, bbox.width);
473 for (i = 0; i < ln; i++) {
476 if (yValue === false) {
477 if (path.length == 1) {
481 me.items.push(false);
484 x = (bbox.x + (xValue - minX) * xScale).toFixed(2);
485 y = ((bbox.y + bbox.height) - (yValue - minY) * yScale).toFixed(2);
490 path = path.concat([x, y]);
492 if ((typeof firstY == 'undefined') && (typeof y != 'undefined')) {
495 // If this is the first line, create a dummypath to animate in from.
496 if (!me.line || chart.resizing) {
497 dummyPath = dummyPath.concat([x, bbox.y + bbox.height / 2]);
500 // When resizing, reset before animating
501 if (chart.animate && chart.resizing && me.line) {
502 me.line.setAttributes({
506 me.fillPath.setAttributes({
511 if (me.line.shadows) {
512 shadows = me.line.shadows;
513 for (j = 0, lnsh = shadows.length; j < lnsh; j++) {
515 shadow.setAttributes({
522 marker = markerGroup.getAt(count++);
524 marker = Ext.chart.Shape[type](surface, Ext.apply({
525 group: [group, markerGroup],
529 y: prevY || (bbox.y + bbox.height / 2)
531 value: '"' + xValue + ', ' + yValue + '"'
540 marker.setAttributes({
541 value: '"' + xValue + ', ' + yValue + '"',
554 value: [xValue, yValue],
557 storeItem: store.getAt(i)
563 if (path.length <= 1) {
564 //nothing to be rendered
569 path = Ext.draw.Draw.smooth(path, 6);
572 //Correct path if we're animating timeAxis intervals
573 if (chart.markerIndex && me.previousPath) {
574 fromPath = me.previousPath;
575 fromPath.splice(1, 2);
580 // Only create a line if one doesn't exist.
582 me.line = surface.add(Ext.apply({
586 stroke: endLineStyle.stroke || endLineStyle.fill
587 }, endLineStyle || {}));
588 //unset fill here (there's always a default fill withing the themes).
589 me.line.setAttributes({
592 if (!endLineStyle.stroke && colorArrayLength) {
593 me.line.setAttributes({
594 stroke: colorArrayStyle[seriesIdx % colorArrayLength]
599 shadows = me.line.shadows = [];
600 for (shindex = 0; shindex < lnsh; shindex++) {
601 shadowBarAttr = shadowAttributes[shindex];
602 shadowBarAttr = Ext.apply({}, shadowBarAttr, { path: dummyPath });
603 shadow = chart.surface.add(Ext.apply({}, {
605 group: shadowGroups[shindex]
607 shadows.push(shadow);
612 fillPath = path.concat([
613 ["L", x, bbox.y + bbox.height],
614 ["L", bbox.x, bbox.y + bbox.height],
615 ["L", bbox.x, firstY]
618 me.fillPath = surface.add({
621 opacity: endLineStyle.opacity || 0.3,
622 fill: colorArrayStyle[seriesIdx % colorArrayLength] || endLineStyle.fill,
627 markerCount = showMarkers && markerGroup.getCount();
631 //Add renderer to line. There is not unique record associated with this.
632 rendererAttributes = me.renderer(line, false, { path: path }, i, store);
633 Ext.apply(rendererAttributes, endLineStyle || {}, {
634 stroke: endLineStyle.stroke || endLineStyle.fill
636 //fill should not be used here but when drawing the special fill path object
637 delete rendererAttributes.fill;
638 if (chart.markerIndex && me.previousPath) {
639 me.animation = animation = me.onAnimate(line, {
640 to: rendererAttributes,
646 me.animation = animation = me.onAnimate(line, {
647 to: rendererAttributes
652 shadows = line.shadows;
653 for(j = 0; j < lnsh; j++) {
654 if (chart.markerIndex && me.previousPath) {
655 me.onAnimate(shadows[j], {
657 from: { path: fromPath }
660 me.onAnimate(shadows[j], {
668 me.onAnimate(me.fillPath, {
671 fill: colorArrayStyle[seriesIdx % colorArrayLength] || endLineStyle.fill
672 }, endLineStyle || {})
678 for(i = 0; i < ln; i++) {
680 item = markerGroup.getAt(count++);
682 rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
684 to: Ext.apply(rendererAttributes, endMarkerStyle || {})
689 for(; count < markerCount; count++) {
690 item = markerGroup.getAt(count);
695 rendererAttributes = me.renderer(me.line, false, { path: path, hidden: false }, i, store);
696 Ext.apply(rendererAttributes, endLineStyle || {}, {
697 stroke: endLineStyle.stroke || endLineStyle.fill
699 //fill should not be used here but when drawing the special fill path object
700 delete rendererAttributes.fill;
701 me.line.setAttributes(rendererAttributes, true);
702 //set path for shadows
704 shadows = me.line.shadows;
705 for(j = 0; j < lnsh; j++) {
706 shadows[j].setAttributes({
712 me.fillPath.setAttributes({
718 for(i = 0; i < ln; i++) {
720 item = markerGroup.getAt(count++);
722 rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
723 item.setAttributes(Ext.apply(endMarkerStyle || {}, rendererAttributes || {}), true);
727 for(; count < markerCount; count++) {
728 item = markerGroup.getAt(count);
734 if (chart.markerIndex) {
735 path.splice(1, 0, path[1], path[2]);
736 me.previousPath = path;
742 // @private called when a label is to be created.
743 onCreateLabel: function(storeItem, item, i, display) {
745 group = me.labelsGroup,
748 endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
750 return me.chart.surface.add(Ext.apply({
752 'text-anchor': 'middle',
755 'y': bbox.y + bbox.height / 2
756 }, endLabelStyle || {}));
759 // @private called when a label is to be created.
760 onPlaceLabel: function(label, storeItem, item, i, display, animate) {
763 resizing = chart.resizing,
765 format = config.renderer,
766 field = config.field,
770 radius = item.sprite.attr.radius,
773 label.setAttributes({
774 text: format(storeItem.get(field)),
778 if (display == 'rotate') {
779 label.setAttributes({
780 'text-anchor': 'start',
787 //correct label position to fit into the box
788 bb = label.getBBox();
791 x = x < bbox.x? bbox.x : x;
792 x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
793 y = (y - height < bbox.y)? bbox.y + height : y;
795 } else if (display == 'under' || display == 'over') {
796 //TODO(nicolas): find out why width/height values in circle bounding boxes are undefined.
797 bb = item.sprite.getBBox();
798 bb.width = bb.width || (radius * 2);
799 bb.height = bb.height || (radius * 2);
800 y = y + (display == 'over'? -bb.height : bb.height);
801 //correct label position to fit into the box
802 bb = label.getBBox();
804 height = bb.height/2;
805 x = x - width < bbox.x? bbox.x + width : x;
806 x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
807 y = y - height < bbox.y? bbox.y + height : y;
808 y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
811 if (me.chart.animate && !me.chart.resizing) {
813 me.onAnimate(label, {
820 label.setAttributes({
825 me.animation.on('afteranimate', function() {
834 //@private Overriding highlights.js highlightItem method.
835 highlightItem: function() {
837 me.callParent(arguments);
838 if (this.line && !this.highlighted) {
839 if (!('__strokeWidth' in this.line)) {
840 this.line.__strokeWidth = this.line.attr['stroke-width'] || 0;
842 if (this.line.__anim) {
843 this.line.__anim.paused = true;
845 this.line.__anim = Ext.create('Ext.fx.Anim', {
848 'stroke-width': this.line.__strokeWidth + 3
851 this.highlighted = true;
855 //@private Overriding highlights.js unHighlightItem method.
856 unHighlightItem: function() {
858 me.callParent(arguments);
859 if (this.line && this.highlighted) {
860 this.line.__anim = Ext.create('Ext.fx.Anim', {
863 'stroke-width': this.line.__strokeWidth
866 this.highlighted = false;
870 //@private called when a callout needs to be placed.
871 onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
878 surface = chart.surface,
879 resizing = chart.resizing,
880 config = me.callouts,
882 prev = i == 0? false : items[i -1].point,
883 next = (i == items.length -1)? false : items[i +1].point,
884 cur = [+item.point[0], +item.point[1]],
885 dir, norm, normal, a, aprev, anext,
886 offsetFromViz = config.offsetFromViz || 30,
887 offsetToSide = config.offsetToSide || 10,
888 offsetBox = config.offsetBox || 3,
889 boxx, boxy, boxw, boxh,
890 p, clipRect = me.clipRect,
892 width: config.styles.width || 10,
893 height: config.styles.height || 10
897 //get the right two points
904 a = (next[1] - prev[1]) / (next[0] - prev[0]);
905 aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
906 anext = (next[1] - cur[1]) / (next[0] - cur[0]);
908 norm = Math.sqrt(1 + a * a);
909 dir = [1 / norm, a / norm];
910 normal = [-dir[1], dir[0]];
912 //keep the label always on the outer part of the "elbow"
913 if (aprev > 0 && anext < 0 && normal[1] < 0
914 || aprev < 0 && anext > 0 && normal[1] > 0) {
917 } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0
918 || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
923 x = cur[0] + normal[0] * offsetFromViz;
924 y = cur[1] + normal[1] * offsetFromViz;
926 //box position and dimensions
927 boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
928 boxy = y - bbox.height /2 - offsetBox;
929 boxw = bbox.width + 2 * offsetBox;
930 boxh = bbox.height + 2 * offsetBox;
932 //now check if we're out of bounds and invert the normal vector correspondingly
933 //this may add new overlaps between labels (but labels won't be out of bounds).
934 if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
937 if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
942 x = cur[0] + normal[0] * offsetFromViz;
943 y = cur[1] + normal[1] * offsetFromViz;
945 //update box position and dimensions
946 boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
947 boxy = y - bbox.height /2 - offsetBox;
948 boxw = bbox.width + 2 * offsetBox;
949 boxh = bbox.height + 2 * offsetBox;
952 //set the line from the middle of the pie to the box.
953 me.onAnimate(callout.lines, {
955 path: ["M", cur[0], cur[1], "L", x, y, "Z"]
958 //set component position
960 callout.panel.setPosition(boxx, boxy, true);
964 //set the line from the middle of the pie to the box.
965 callout.lines.setAttributes({
966 path: ["M", cur[0], cur[1], "L", x, y, "Z"]
968 //set component position
970 callout.panel.setPosition(boxx, boxy);
974 callout[p].show(true);
978 isItemInPoint: function(x, y, item, i) {
981 tolerance = me.selectionTolerance,
994 dist1, dist2, dist, midx, midy,
995 sqrt = Math.sqrt, abs = Math.abs;
998 prevItem = i && items[i - 1];
1001 prevItem = items[ln - 1];
1003 prevPoint = prevItem && prevItem.point;
1004 nextPoint = nextItem && nextItem.point;
1005 x1 = prevItem ? prevPoint[0] : nextPoint[0] - tolerance;
1006 y1 = prevItem ? prevPoint[1] : nextPoint[1];
1007 x2 = nextItem ? nextPoint[0] : prevPoint[0] + tolerance;
1008 y2 = nextItem ? nextPoint[1] : prevPoint[1];
1009 dist1 = sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
1010 dist2 = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
1011 dist = Math.min(dist1, dist2);
1013 if (dist <= tolerance) {
1014 return dist == dist1? prevItem : nextItem;
1019 // @private toggle visibility of all series elements (markers, sprites).
1020 toggleAll: function(show) {
1022 i, ln, shadow, shadows;
1024 Ext.chart.series.Line.superclass.hideAll.call(me);
1027 Ext.chart.series.Line.superclass.showAll.call(me);
1030 me.line.setAttributes({
1034 if (me.line.shadows) {
1035 for (i = 0, shadows = me.line.shadows, ln = shadows.length; i < ln; i++) {
1036 shadow = shadows[i];
1037 shadow.setAttributes({
1044 me.fillPath.setAttributes({
1050 // @private hide all series elements (markers, sprites).
1051 hideAll: function() {
1052 this.toggleAll(false);
1055 // @private hide all series elements (markers, sprites).
1056 showAll: function() {
1057 this.toggleAll(true);