API Docs for: 3.10.3
Show:

File: charts/js/PieChart.js

  1. /**
  2. * The PieChart class creates a pie chart
  3. *
  4. * @class PieChart
  5. * @extends ChartBase
  6. * @constructor
  7. * @submodule charts-base
  8. */
  9. Y.PieChart = Y.Base.create("pieChart", Y.Widget, [Y.ChartBase], {
  10. /**
  11. * Calculates and returns a `seriesCollection`.
  12. *
  13. * @method _getSeriesCollection
  14. * @return Array
  15. * @private
  16. */
  17. _getSeriesCollection: function()
  18. {
  19. if(this._seriesCollection)
  20. {
  21. return this._seriesCollection;
  22. }
  23. var axes = this.get("axes"),
  24. sc = [],
  25. seriesKeys,
  26. i = 0,
  27. l,
  28. type = this.get("type"),
  29. key,
  30. catAxis = "categoryAxis",
  31. catKey = "categoryKey",
  32. valAxis = "valueAxis",
  33. seriesKey = "valueKey";
  34. if(axes)
  35. {
  36. seriesKeys = axes.values.get("keyCollection");
  37. key = axes.category.get("keyCollection")[0];
  38. l = seriesKeys.length;
  39. for(; i < l; ++i)
  40. {
  41. sc[i] = {type:type};
  42. sc[i][catAxis] = "category";
  43. sc[i][valAxis] = "values";
  44. sc[i][catKey] = key;
  45. sc[i][seriesKey] = seriesKeys[i];
  46. }
  47. }
  48. this._seriesCollection = sc;
  49. return sc;
  50. },
  51.  
  52. /**
  53. * Creates `Axis` instances.
  54. *
  55. * @method _parseAxes
  56. * @param {Object} val Object containing `Axis` instances or objects in which to construct `Axis` instances.
  57. * @return Object
  58. * @private
  59. */
  60. _parseAxes: function(hash)
  61. {
  62. if(!this._axes)
  63. {
  64. this._axes = {};
  65. }
  66. var i, pos, axis, dh, config, AxisClass,
  67. type = this.get("type"),
  68. w = this.get("width"),
  69. h = this.get("height"),
  70. node = Y.Node.one(this._parentNode);
  71. if(!w)
  72. {
  73. this.set("width", node.get("offsetWidth"));
  74. w = this.get("width");
  75. }
  76. if(!h)
  77. {
  78. this.set("height", node.get("offsetHeight"));
  79. h = this.get("height");
  80. }
  81. for(i in hash)
  82. {
  83. if(hash.hasOwnProperty(i))
  84. {
  85. dh = hash[i];
  86. pos = type === "pie" ? "none" : dh.position;
  87. AxisClass = this._getAxisClass(dh.type);
  88. config = {dataProvider:this.get("dataProvider")};
  89. if(dh.hasOwnProperty("roundingUnit"))
  90. {
  91. config.roundingUnit = dh.roundingUnit;
  92. }
  93. config.keys = dh.keys;
  94. config.width = w;
  95. config.height = h;
  96. config.position = pos;
  97. config.styles = dh.styles;
  98. axis = new AxisClass(config);
  99. axis.on("axisRendered", Y.bind(this._itemRendered, this));
  100. this._axes[i] = axis;
  101. }
  102. }
  103. },
  104.  
  105. /**
  106. * Adds axes to the chart.
  107. *
  108. * @method _addAxes
  109. * @private
  110. */
  111. _addAxes: function()
  112. {
  113. var axes = this.get("axes"),
  114. i,
  115. axis,
  116. p;
  117. if(!axes)
  118. {
  119. this.set("axes", this._getDefaultAxes());
  120. axes = this.get("axes");
  121. }
  122. if(!this._axesCollection)
  123. {
  124. this._axesCollection = [];
  125. }
  126. for(i in axes)
  127. {
  128. if(axes.hasOwnProperty(i))
  129. {
  130. axis = axes[i];
  131. p = axis.get("position");
  132. if(!this.get(p + "AxesCollection"))
  133. {
  134. this.set(p + "AxesCollection", [axis]);
  135. }
  136. else
  137. {
  138. this.get(p + "AxesCollection").push(axis);
  139. }
  140. this._axesCollection.push(axis);
  141. }
  142. }
  143. },
  144.  
  145. /**
  146. * Renders the Graph.
  147. *
  148. * @method _addSeries
  149. * @private
  150. */
  151. _addSeries: function()
  152. {
  153. var graph = this.get("graph"),
  154. seriesCollection = this.get("seriesCollection");
  155. this._parseSeriesAxes(seriesCollection);
  156. graph.set("showBackground", false);
  157. graph.set("width", this.get("width"));
  158. graph.set("height", this.get("height"));
  159. graph.set("seriesCollection", seriesCollection);
  160. this._seriesCollection = graph.get("seriesCollection");
  161. graph.render(this.get("contentBox"));
  162. },
  163.  
  164. /**
  165. * Parse and sets the axes for the chart.
  166. *
  167. * @method _parseSeriesAxes
  168. * @param {Array} c A collection `PieSeries` instance.
  169. * @private
  170. */
  171. _parseSeriesAxes: function(c)
  172. {
  173. var i = 0,
  174. len = c.length,
  175. s,
  176. axes = this.get("axes"),
  177. axis;
  178. for(; i < len; ++i)
  179. {
  180. s = c[i];
  181. if(s)
  182. {
  183. //If series is an actual series instance,
  184. //replace axes attribute string ids with axes
  185. if(s instanceof Y.PieSeries)
  186. {
  187. axis = s.get("categoryAxis");
  188. if(axis && !(axis instanceof Y.Axis))
  189. {
  190. s.set("categoryAxis", axes[axis]);
  191. }
  192. axis = s.get("valueAxis");
  193. if(axis && !(axis instanceof Y.Axis))
  194. {
  195. s.set("valueAxis", axes[axis]);
  196. }
  197. continue;
  198. }
  199. s.categoryAxis = axes.category;
  200. s.valueAxis = axes.values;
  201. if(!s.type)
  202. {
  203. s.type = this.get("type");
  204. }
  205. }
  206. }
  207. },
  208.  
  209. /**
  210. * Generates and returns a key-indexed object containing `Axis` instances or objects used to create `Axis` instances.
  211. *
  212. * @method _getDefaultAxes
  213. * @return Object
  214. * @private
  215. */
  216. _getDefaultAxes: function()
  217. {
  218. var catKey = this.get("categoryKey"),
  219. seriesKeys = this.get("seriesKeys").concat(),
  220. seriesAxis = "numeric";
  221. return {
  222. values:{
  223. keys:seriesKeys,
  224. type:seriesAxis
  225. },
  226. category:{
  227. keys:[catKey],
  228. type:this.get("categoryType")
  229. }
  230. };
  231. },
  232.  
  233. /**
  234. * Returns an object literal containing a categoryItem and a valueItem for a given series index.
  235. *
  236. * @method getSeriesItem
  237. * @param series Reference to a series.
  238. * @param index Index of the specified item within a series.
  239. * @return Object
  240. */
  241. getSeriesItems: function(series, index)
  242. {
  243. var categoryItem = {
  244. axis: series.get("categoryAxis"),
  245. key: series.get("categoryKey"),
  246. displayName: series.get("categoryDisplayName")
  247. },
  248. valueItem = {
  249. axis: series.get("valueAxis"),
  250. key: series.get("valueKey"),
  251. displayName: series.get("valueDisplayName")
  252. };
  253. categoryItem.value = categoryItem.axis.getKeyValueAt(categoryItem.key, index);
  254. valueItem.value = valueItem.axis.getKeyValueAt(valueItem.key, index);
  255. return {category:categoryItem, value:valueItem};
  256. },
  257.  
  258. /**
  259. * Handler for sizeChanged event.
  260. *
  261. * @method _sizeChanged
  262. * @param {Object} e Event object.
  263. * @private
  264. */
  265. _sizeChanged: function()
  266. {
  267. this._redraw();
  268. },
  269.  
  270. /**
  271. * Redraws the chart instance.
  272. *
  273. * @method _redraw
  274. * @private
  275. */
  276. _redraw: function()
  277. {
  278. var graph = this.get("graph"),
  279. w = this.get("width"),
  280. h = this.get("height"),
  281. dimension;
  282. if(graph)
  283. {
  284. dimension = Math.min(w, h);
  285. graph.set("width", dimension);
  286. graph.set("height", dimension);
  287. }
  288. },
  289.  
  290. /**
  291. * Formats tooltip text for a pie chart.
  292. *
  293. * @method _tooltipLabelFunction
  294. * @param {Object} categoryItem An object containing the following:
  295. * <dl>
  296. * <dt>axis</dt><dd>The axis to which the category is bound.</dd>
  297. * <dt>displayName</dt><dd>The display name set to the category (defaults to key if not provided)</dd>
  298. * <dt>key</dt><dd>The key of the category.</dd>
  299. * <dt>value</dt><dd>The value of the category</dd>
  300. * </dl>
  301. * @param {Object} valueItem An object containing the following:
  302. * <dl>
  303. * <dt>axis</dt><dd>The axis to which the item's series is bound.</dd>
  304. * <dt>displayName</dt><dd>The display name of the series. (defaults to key if not provided)</dd>
  305. * <dt>key</dt><dd>The key for the series.</dd>
  306. * <dt>value</dt><dd>The value for the series item.</dd>
  307. * </dl>
  308. * @param {Number} itemIndex The index of the item within the series.
  309. * @param {CartesianSeries} series The `PieSeries` instance of the item.
  310. * @return {HTML}
  311. * @private
  312. */
  313. _tooltipLabelFunction: function(categoryItem, valueItem, itemIndex, series)
  314. {
  315. var msg = DOCUMENT.createElement("div"),
  316. total = series.getTotalValues(),
  317. pct = Math.round((valueItem.value / total) * 10000)/100;
  318. msg.appendChild(DOCUMENT.createTextNode(categoryItem.displayName +
  319. ": " + categoryItem.axis.get("labelFunction").apply(this, [categoryItem.value, categoryItem.axis.get("labelFormat")])));
  320. msg.appendChild(DOCUMENT.createElement("br"));
  321. msg.appendChild(DOCUMENT.createTextNode(valueItem.displayName +
  322. ": " + valueItem.axis.get("labelFunction").apply(this, [valueItem.value, valueItem.axis.get("labelFormat")])));
  323. msg.appendChild(DOCUMENT.createElement("br"));
  324. msg.appendChild(DOCUMENT.createTextNode(pct + "%"));
  325. return msg;
  326. },
  327.  
  328. /**
  329. * Returns the appropriate message based on the key press.
  330. *
  331. * @method _getAriaMessage
  332. * @param {Number} key The keycode that was pressed.
  333. * @return String
  334. */
  335. _getAriaMessage: function(key)
  336. {
  337. var msg = "",
  338. categoryItem,
  339. items,
  340. series,
  341. valueItem,
  342. seriesIndex = 0,
  343. itemIndex = this._itemIndex,
  344. len,
  345. total,
  346. pct,
  347. markers;
  348. series = this.getSeries(parseInt(seriesIndex, 10));
  349. markers = series.get("markers");
  350. len = markers && markers.length ? markers.length : 0;
  351. if(key === 37)
  352. {
  353. itemIndex = itemIndex > 0 ? itemIndex - 1 : len - 1;
  354. }
  355. else if(key === 39)
  356. {
  357. itemIndex = itemIndex >= len - 1 ? 0 : itemIndex + 1;
  358. }
  359. this._itemIndex = itemIndex;
  360. items = this.getSeriesItems(series, itemIndex);
  361. categoryItem = items.category;
  362. valueItem = items.value;
  363. total = series.getTotalValues();
  364. pct = Math.round((valueItem.value / total) * 10000)/100;
  365. if(categoryItem && valueItem)
  366. {
  367. msg += categoryItem.displayName +
  368. ": " +
  369. categoryItem.axis.formatLabel.apply(this, [categoryItem.value, categoryItem.axis.get("labelFormat")]) +
  370. ", ";
  371. msg += valueItem.displayName +
  372. ": " + valueItem.axis.formatLabel.apply(this, [valueItem.value, valueItem.axis.get("labelFormat")]) +
  373. ", ";
  374. msg += "Percent of total " + valueItem.displayName + ": " + pct + "%,";
  375. }
  376. else
  377. {
  378. msg += "No data available,";
  379. }
  380. msg += (itemIndex + 1) + " of " + len + ". ";
  381. return msg;
  382. }
  383. }, {
  384. ATTRS: {
  385. /**
  386. * Sets the aria description for the chart.
  387. *
  388. * @attribute ariaDescription
  389. * @type String
  390. */
  391. ariaDescription: {
  392. value: "Use the left and right keys to navigate through items.",
  393.  
  394. setter: function(val)
  395. {
  396. if(this._description)
  397. {
  398. this._description.setContent("");
  399. this._description.appendChild(DOCUMENT.createTextNode(val));
  400. }
  401. return val;
  402. }
  403. },
  404.  
  405. /**
  406. * Axes to appear in the chart.
  407. *
  408. * @attribute axes
  409. * @type Object
  410. */
  411. axes: {
  412. getter: function()
  413. {
  414. return this._axes;
  415. },
  416.  
  417. setter: function(val)
  418. {
  419. this._parseAxes(val);
  420. }
  421. },
  422.  
  423. /**
  424. * Collection of series to appear on the chart. This can be an array of Series instances or object literals
  425. * used to describe a Series instance.
  426. *
  427. * @attribute seriesCollection
  428. * @type Array
  429. */
  430. seriesCollection: {
  431. lazyAdd: false,
  432.  
  433. getter: function()
  434. {
  435. return this._getSeriesCollection();
  436. },
  437.  
  438. setter: function(val)
  439. {
  440. return this._setSeriesCollection(val);
  441. }
  442. },
  443.  
  444. /**
  445. * Type of chart when there is no series collection specified.
  446. *
  447. * @attribute type
  448. * @type String
  449. */
  450. type: {
  451. value: "pie"
  452. }
  453. }
  454. });
  455.