|
1 /* |
|
2 YUI 3.10.3 (build 2fb5187) |
|
3 Copyright 2013 Yahoo! Inc. All rights reserved. |
|
4 Licensed under the BSD License. |
|
5 http://yuilibrary.com/license/ |
|
6 */ |
|
7 |
|
8 YUI.add('series-bar-stacked', function (Y, NAME) { |
|
9 |
|
10 /** |
|
11 * Provides functionality for creating a stacked bar series. |
|
12 * |
|
13 * @module charts |
|
14 * @submodule series-bar-stacked |
|
15 */ |
|
16 var Y_Lang = Y.Lang; |
|
17 |
|
18 /** |
|
19 * The StackedBarSeries renders bar chart in which series are stacked horizontally to show |
|
20 * their contribution to the cumulative total. |
|
21 * |
|
22 * @class StackedBarSeries |
|
23 * @extends BarSeries |
|
24 * @uses StackingUtil |
|
25 * @constructor |
|
26 * @param {Object} config (optional) Configuration parameters. |
|
27 * @submodule series-bar-stacked |
|
28 */ |
|
29 Y.StackedBarSeries = Y.Base.create("stackedBarSeries", Y.BarSeries, [Y.StackingUtil], { |
|
30 /** |
|
31 * @protected |
|
32 * |
|
33 * Draws the series. |
|
34 * |
|
35 * @method drawSeries |
|
36 */ |
|
37 drawSeries: function() |
|
38 { |
|
39 if(this.get("xcoords").length < 1) |
|
40 { |
|
41 return; |
|
42 } |
|
43 |
|
44 var isNumber = Y_Lang.isNumber, |
|
45 style = Y.clone(this.get("styles").marker), |
|
46 w = style.width, |
|
47 h = style.height, |
|
48 xcoords = this.get("xcoords"), |
|
49 ycoords = this.get("ycoords"), |
|
50 i = 0, |
|
51 len = xcoords.length, |
|
52 top = ycoords[0], |
|
53 seriesCollection = this.get("seriesTypeCollection"), |
|
54 ratio, |
|
55 order = this.get("order"), |
|
56 graphOrder = this.get("graphOrder"), |
|
57 left, |
|
58 marker, |
|
59 lastCollection, |
|
60 negativeBaseValues, |
|
61 positiveBaseValues, |
|
62 fillColors, |
|
63 borderColors, |
|
64 useOrigin = order === 0, |
|
65 totalHeight = len * h, |
|
66 dimensions = { |
|
67 width: [], |
|
68 height: [] |
|
69 }, |
|
70 xvalues = [], |
|
71 yvalues = [], |
|
72 groupMarkers = this.get("groupMarkers"); |
|
73 if(Y_Lang.isArray(style.fill.color)) |
|
74 { |
|
75 fillColors = style.fill.color.concat(); |
|
76 } |
|
77 if(Y_Lang.isArray(style.border.color)) |
|
78 { |
|
79 borderColors = style.border.color.concat(); |
|
80 } |
|
81 this._createMarkerCache(); |
|
82 if(totalHeight > this.get("height")) |
|
83 { |
|
84 ratio = this.get("height")/totalHeight; |
|
85 h *= ratio; |
|
86 h = Math.max(h, 1); |
|
87 } |
|
88 if(!useOrigin) |
|
89 { |
|
90 lastCollection = seriesCollection[order - 1]; |
|
91 negativeBaseValues = lastCollection.get("negativeBaseValues"); |
|
92 positiveBaseValues = lastCollection.get("positiveBaseValues"); |
|
93 if(!negativeBaseValues || !positiveBaseValues) |
|
94 { |
|
95 useOrigin = true; |
|
96 positiveBaseValues = []; |
|
97 negativeBaseValues = []; |
|
98 } |
|
99 } |
|
100 else |
|
101 { |
|
102 negativeBaseValues = []; |
|
103 positiveBaseValues = []; |
|
104 } |
|
105 this.set("negativeBaseValues", negativeBaseValues); |
|
106 this.set("positiveBaseValues", positiveBaseValues); |
|
107 for(i = 0; i < len; ++i) |
|
108 { |
|
109 top = ycoords[i]; |
|
110 left = xcoords[i]; |
|
111 if(!isNumber(top) || !isNumber(left)) |
|
112 { |
|
113 if(useOrigin) |
|
114 { |
|
115 positiveBaseValues[i] = this._leftOrigin; |
|
116 negativeBaseValues[i] = this._leftOrigin; |
|
117 } |
|
118 this._markers.push(null); |
|
119 continue; |
|
120 } |
|
121 if(useOrigin) |
|
122 { |
|
123 w = Math.abs(left - this._leftOrigin); |
|
124 if(left > this._leftOrigin) |
|
125 { |
|
126 positiveBaseValues[i] = left; |
|
127 negativeBaseValues[i] = this._leftOrigin; |
|
128 left -= w; |
|
129 } |
|
130 else if(left < this._leftOrigin) |
|
131 { |
|
132 positiveBaseValues[i] = this._leftOrigin; |
|
133 negativeBaseValues[i] = left; |
|
134 } |
|
135 else |
|
136 { |
|
137 positiveBaseValues[i] = left; |
|
138 negativeBaseValues[i] = this._leftOrigin; |
|
139 } |
|
140 } |
|
141 else |
|
142 { |
|
143 if(left < this._leftOrigin) |
|
144 { |
|
145 left = negativeBaseValues[i] - (this._leftOrigin - xcoords[i]); |
|
146 w = negativeBaseValues[i] - left; |
|
147 negativeBaseValues[i] = left; |
|
148 } |
|
149 else if(left >= this._leftOrigin) |
|
150 { |
|
151 left += (positiveBaseValues[i] - this._leftOrigin); |
|
152 w = left - positiveBaseValues[i]; |
|
153 positiveBaseValues[i] = left; |
|
154 left -= w; |
|
155 } |
|
156 } |
|
157 if(!isNaN(w) && w > 0) |
|
158 { |
|
159 top -= h/2; |
|
160 if(groupMarkers) |
|
161 { |
|
162 dimensions.width[i] = w; |
|
163 dimensions.height[i] = h; |
|
164 xvalues.push(left); |
|
165 yvalues.push(top); |
|
166 } |
|
167 else |
|
168 { |
|
169 style.width = w; |
|
170 style.height = h; |
|
171 style.x = left; |
|
172 style.y = top; |
|
173 if(fillColors) |
|
174 { |
|
175 style.fill.color = fillColors[i % fillColors.length]; |
|
176 } |
|
177 if(borderColors) |
|
178 { |
|
179 style.border.color = borderColors[i % borderColors.length]; |
|
180 } |
|
181 marker = this.getMarker(style, graphOrder, i); |
|
182 } |
|
183 } |
|
184 else if(!groupMarkers) |
|
185 { |
|
186 this._markers.push(null); |
|
187 } |
|
188 } |
|
189 if(groupMarkers) |
|
190 { |
|
191 this._createGroupMarker({ |
|
192 fill: style.fill, |
|
193 border: style.border, |
|
194 dimensions: dimensions, |
|
195 xvalues: xvalues, |
|
196 yvalues: yvalues, |
|
197 shape: style.shape |
|
198 }); |
|
199 } |
|
200 else |
|
201 { |
|
202 this._clearMarkerCache(); |
|
203 } |
|
204 }, |
|
205 |
|
206 /** |
|
207 * @protected |
|
208 * |
|
209 * Resizes and positions markers based on a mouse interaction. |
|
210 * |
|
211 * @method updateMarkerState |
|
212 * @param {String} type state of the marker |
|
213 * @param {Number} i index of the marker |
|
214 */ |
|
215 updateMarkerState: function(type, i) |
|
216 { |
|
217 if(this._markers[i]) |
|
218 { |
|
219 var state = this._getState(type), |
|
220 ycoords = this.get("ycoords"), |
|
221 marker = this._markers[i], |
|
222 styles = this.get("styles").marker, |
|
223 h = styles.height, |
|
224 markerStyles = state === "off" || !styles[state] ? Y.clone(styles) : Y.clone(styles[state]), |
|
225 fillColor, |
|
226 borderColor; |
|
227 markerStyles.y = (ycoords[i] - h/2); |
|
228 markerStyles.x = marker.get("x"); |
|
229 markerStyles.width = marker.get("width"); |
|
230 markerStyles.id = marker.get("id"); |
|
231 fillColor = markerStyles.fill.color; |
|
232 borderColor = markerStyles.border.color; |
|
233 if(Y_Lang.isArray(fillColor)) |
|
234 { |
|
235 markerStyles.fill.color = fillColor[i % fillColor.length]; |
|
236 } |
|
237 else |
|
238 { |
|
239 markerStyles.fill.color = this._getItemColor(markerStyles.fill.color, i); |
|
240 } |
|
241 if(Y_Lang.isArray(borderColor)) |
|
242 { |
|
243 markerStyles.border.color = borderColor[i % borderColor.length]; |
|
244 } |
|
245 else |
|
246 { |
|
247 markerStyles.border.color = this._getItemColor(markerStyles.border.color, i); |
|
248 } |
|
249 marker.set(markerStyles); |
|
250 } |
|
251 }, |
|
252 |
|
253 /** |
|
254 * @protected |
|
255 * |
|
256 * Returns default values for the `styles` attribute. |
|
257 * |
|
258 * @method _getPlotDefaults |
|
259 * @return Object |
|
260 */ |
|
261 _getPlotDefaults: function() |
|
262 { |
|
263 var defs = { |
|
264 fill:{ |
|
265 type: "solid", |
|
266 alpha: 1, |
|
267 colors:null, |
|
268 alphas: null, |
|
269 ratios: null |
|
270 }, |
|
271 border:{ |
|
272 weight: 0, |
|
273 alpha: 1 |
|
274 }, |
|
275 width: 24, |
|
276 height: 24, |
|
277 shape: "rect", |
|
278 |
|
279 padding:{ |
|
280 top: 0, |
|
281 left: 0, |
|
282 right: 0, |
|
283 bottom: 0 |
|
284 } |
|
285 }; |
|
286 defs.fill.color = this._getDefaultColor(this.get("graphOrder"), "fill"); |
|
287 defs.border.color = this._getDefaultColor(this.get("graphOrder"), "border"); |
|
288 return defs; |
|
289 } |
|
290 }, { |
|
291 ATTRS: { |
|
292 /** |
|
293 * Read-only attribute indicating the type of series. |
|
294 * |
|
295 * @attribute type |
|
296 * @type String |
|
297 * @default stackedBar |
|
298 */ |
|
299 type: { |
|
300 value: "stackedBar" |
|
301 }, |
|
302 |
|
303 /** |
|
304 * Direction of the series |
|
305 * |
|
306 * @attribute direction |
|
307 * @type String |
|
308 * @default vertical |
|
309 */ |
|
310 direction: { |
|
311 value: "vertical" |
|
312 }, |
|
313 |
|
314 /** |
|
315 * @private |
|
316 * |
|
317 * @attribute negativeBaseValues |
|
318 * @type Array |
|
319 * @default null |
|
320 */ |
|
321 negativeBaseValues: { |
|
322 value: null |
|
323 }, |
|
324 |
|
325 /** |
|
326 * @private |
|
327 * |
|
328 * @attribute positiveBaseValues |
|
329 * @type Array |
|
330 * @default null |
|
331 */ |
|
332 positiveBaseValues: { |
|
333 value: null |
|
334 } |
|
335 |
|
336 /** |
|
337 * Style properties used for drawing markers. This attribute is inherited from `BarSeries`. Below are the default values: |
|
338 * <dl> |
|
339 * <dt>fill</dt><dd>A hash containing the following values: |
|
340 * <dl> |
|
341 * <dt>color</dt><dd>Color of the fill. The default value is determined by the order of the series on the graph. The color |
|
342 * will be retrieved from the below array:<br/> |
|
343 * `["#66007f", "#a86f41", "#295454", "#996ab2", "#e8cdb7", "#90bdbd","#000000","#c3b8ca", "#968373", "#678585"]` |
|
344 * </dd> |
|
345 * <dt>alpha</dt><dd>Number from 0 to 1 indicating the opacity of the marker fill. The default value is 1.</dd> |
|
346 * </dl> |
|
347 * </dd> |
|
348 * <dt>border</dt><dd>A hash containing the following values: |
|
349 * <dl> |
|
350 * <dt>color</dt><dd>Color of the border. The default value is determined by the order of the series on the graph. The color |
|
351 * will be retrieved from the below array:<br/> |
|
352 * `["#205096", "#b38206", "#000000", "#94001e", "#9d6fa0", "#e55b00", "#5e85c9", "#adab9e", "#6ac291", "#006457"]` |
|
353 * <dt>alpha</dt><dd>Number from 0 to 1 indicating the opacity of the marker border. The default value is 1.</dd> |
|
354 * <dt>weight</dt><dd>Number indicating the width of the border. The default value is 1.</dd> |
|
355 * </dl> |
|
356 * </dd> |
|
357 * <dt>height</dt><dd>indicates the width of the marker. The default value is 24.</dd> |
|
358 * <dt>over</dt><dd>hash containing styles for markers when highlighted by a `mouseover` event. The default |
|
359 * values for each style is null. When an over style is not set, the non-over value will be used. For example, |
|
360 * the default value for `marker.over.fill.color` is equivalent to `marker.fill.color`.</dd> |
|
361 * </dl> |
|
362 * |
|
363 * @attribute styles |
|
364 * @type Object |
|
365 */ |
|
366 } |
|
367 }); |
|
368 |
|
369 |
|
370 |
|
371 }, '3.10.3', {"requires": ["series-stacked", "series-bar"]}); |