API Docs for: 3.17.2
Show:

File: charts/js/AxisBase.js

  1. /**
  2. * The axis-base submodule contains functionality for the handling of axis data in a chart.
  3. *
  4. * @module charts
  5. * @submodule axis-base
  6. */
  7. /**
  8. * An abstract class that provides the core functionality used by the following classes:
  9. * <ul>
  10. * <li>{{#crossLink "CategoryAxisBase"}}{{/crossLink}}</li>
  11. * <li>{{#crossLink "NumericAxisBase"}}{{/crossLink}}</li>
  12. * <li>{{#crossLink "StackedAxisBase"}}{{/crossLink}}</li>
  13. * <li>{{#crossLink "TimeAxisBase"}}{{/crossLink}}</li>
  14. * <li>{{#crossLink "CategoryAxis"}}{{/crossLink}}</li>
  15. * <li>{{#crossLink "NumericAxis"}}{{/crossLink}}</li>
  16. * <li>{{#crossLink "StackedAxis"}}{{/crossLink}}</li>
  17. * <li>{{#crossLink "TimeAxis"}}{{/crossLink}}</li>
  18. * </ul>
  19. *
  20. * @class AxisBase
  21. * @constructor
  22. * @extends Base
  23. * @uses Renderer
  24. * @param {Object} config (optional) Configuration parameters.
  25. * @submodule axis-base
  26. */
  27. Y.AxisBase = Y.Base.create("axisBase", Y.Base, [Y.Renderer], {
  28. /**
  29. * @method initializer
  30. * @private
  31. */
  32. initializer: function()
  33. {
  34. this.after("minimumChange", Y.bind(this._keyChangeHandler, this));
  35. this.after("maximumChange", Y.bind(this._keyChangeHandler, this));
  36. this.after("keysChange", this._keyChangeHandler);
  37. this.after("dataProviderChange", this._dataProviderChangeHandler);
  38. },
  39.  
  40. /**
  41. * Returns the value corresponding to the origin on the axis.
  42. *
  43. * @method getOrigin
  44. * @return Number
  45. */
  46. getOrigin: function() {
  47. return this.get("minimum");
  48. },
  49.  
  50. /**
  51. * Handles changes to `dataProvider`.
  52. *
  53. * @method _dataProviderChangeHandler
  54. * @param {Object} e Event object.
  55. * @private
  56. */
  57. _dataProviderChangeHandler: function()
  58. {
  59. var keyCollection = this.get("keyCollection").concat(),
  60. keys = this.get("keys"),
  61. i;
  62. if(keys)
  63. {
  64. for(i in keys)
  65. {
  66. if(keys.hasOwnProperty(i))
  67. {
  68. delete keys[i];
  69. }
  70. }
  71. }
  72. if(keyCollection && keyCollection.length)
  73. {
  74. this.set("keys", keyCollection);
  75. }
  76. },
  77.  
  78. /**
  79. * Calculates the maximum and minimum values for the `Data`.
  80. *
  81. * @method _updateMinAndMax
  82. * @private
  83. */
  84. _updateMinAndMax: function() {
  85. },
  86.  
  87. /**
  88. * Constant used to generate unique id.
  89. *
  90. * @property GUID
  91. * @type String
  92. * @private
  93. */
  94. GUID: "yuibaseaxis",
  95.  
  96. /**
  97. * Type of data used in `Axis`.
  98. *
  99. * @property _type
  100. * @type String
  101. * @readOnly
  102. * @private
  103. */
  104. _type: null,
  105.  
  106. /**
  107. * Storage for `setMaximum` attribute.
  108. *
  109. * @property _setMaximum
  110. * @type Object
  111. * @private
  112. */
  113. _setMaximum: null,
  114.  
  115. /**
  116. * Storage for `setMinimum` attribute.
  117. *
  118. * @property _setMinimum
  119. * @type Object
  120. * @private
  121. */
  122. _setMinimum: null,
  123.  
  124. /**
  125. * Reference to data array.
  126. *
  127. * @property _data
  128. * @type Array
  129. * @private
  130. */
  131. _data: null,
  132.  
  133. /**
  134. * Indicates whether the all data is up to date.
  135. *
  136. * @property _updateTotalDataFlag
  137. * @type Boolean
  138. * @private
  139. */
  140. _updateTotalDataFlag: true,
  141.  
  142. /**
  143. * Storage for `dataReady` attribute.
  144. *
  145. * @property _dataReady
  146. * @type Boolean
  147. * @readOnly
  148. * @private
  149. */
  150. _dataReady: false,
  151.  
  152. /**
  153. * Adds an array to the key hash.
  154. *
  155. * @method addKey
  156. * @param value Indicates what key to use in retrieving
  157. * the array.
  158. */
  159. addKey: function (value)
  160. {
  161. this.set("keys", value);
  162. },
  163.  
  164. /**
  165. * Gets an array of values based on a key.
  166. *
  167. * @method _getKeyArray
  168. * @param {String} key Value key associated with the data array.
  169. * @param {Array} data Array in which the data resides.
  170. * @return Array
  171. * @private
  172. */
  173. _getKeyArray: function(key, data)
  174. {
  175. var i = 0,
  176. obj,
  177. keyArray = [],
  178. len = data.length;
  179. for(; i < len; ++i)
  180. {
  181. obj = data[i];
  182. keyArray[i] = obj[key];
  183. }
  184. return keyArray;
  185. },
  186.  
  187. /**
  188. * Updates the total data array.
  189. *
  190. * @method _updateTotalData
  191. * @private
  192. */
  193. _updateTotalData: function()
  194. {
  195. var keys = this.get("keys"),
  196. i;
  197. this._data = [];
  198. for(i in keys)
  199. {
  200. if(keys.hasOwnProperty(i))
  201. {
  202. this._data = this._data.concat(keys[i]);
  203. }
  204. }
  205. this._updateTotalDataFlag = false;
  206. },
  207.  
  208. /**
  209. * Removes an array from the key hash.
  210. *
  211. * @method removeKey
  212. * @param {String} value Indicates what key to use in removing from
  213. * the hash.
  214. */
  215. removeKey: function(value)
  216. {
  217. var keys = this.get("keys");
  218. if(keys.hasOwnProperty(value))
  219. {
  220. delete keys[value];
  221. this._keyChangeHandler();
  222. }
  223. },
  224.  
  225. /**
  226. * Returns a value based of a key value and an index.
  227. *
  228. * @method getKeyValueAt
  229. * @param {String} key value used to look up the correct array
  230. * @param {Number} index within the array
  231. * @return Number
  232. */
  233. getKeyValueAt: function(key, index)
  234. {
  235. var value = NaN,
  236. keys = this.get("keys");
  237. if(keys[key] && Y_Lang.isNumber(parseFloat(keys[key][index])))
  238. {
  239. value = keys[key][index];
  240. }
  241. return parseFloat(value);
  242. },
  243.  
  244. /**
  245. * Returns values based on key identifiers. When a string is passed as an argument, an array of values is returned.
  246. * When an array of keys is passed as an argument, an object literal with an array of values mapped to each key is
  247. * returned.
  248. *
  249. * @method getDataByKey
  250. * @param {String|Array} value value used to identify the array
  251. * @return Array|Object
  252. */
  253. getDataByKey: function (value)
  254. {
  255. var obj,
  256. i,
  257. len,
  258. key,
  259. keys = this.get("keys");
  260. if(Y_Lang.isArray(value))
  261. {
  262. obj = {};
  263. len = value.length;
  264. for(i = 0; i < len; i = i + 1)
  265. {
  266. key = value[i];
  267. if(keys[key])
  268. {
  269. obj[key] = this.getDataByKey(key);
  270. }
  271. }
  272. }
  273. else if(keys[value])
  274. {
  275. obj = keys[value];
  276. }
  277. else
  278. {
  279. obj = null;
  280. }
  281. return obj;
  282. },
  283.  
  284. /**
  285. * Returns the total number of majorUnits that will appear on an axis.
  286. *
  287. * @method getTotalMajorUnits
  288. * @return Number
  289. */
  290. getTotalMajorUnits: function()
  291. {
  292. var units,
  293. majorUnit = this.get("styles").majorUnit;
  294. units = majorUnit.count;
  295. return units;
  296. },
  297.  
  298. /**
  299. * Gets the distance that the first and last ticks are offset from there respective
  300. * edges.
  301. *
  302. * @method getEdgeOffset
  303. * @param {Number} ct Number of ticks on the axis.
  304. * @param {Number} l Length (in pixels) of the axis.
  305. * @return Number
  306. */
  307. getEdgeOffset: function(ct, l)
  308. {
  309. var edgeOffset;
  310. if(this.get("calculateEdgeOffset")) {
  311. edgeOffset = (l/ct)/2;
  312. } else {
  313. edgeOffset = 0;
  314. }
  315. return edgeOffset;
  316. },
  317.  
  318. /**
  319. * Updates the `Axis` after a change in keys.
  320. *
  321. * @method _keyChangeHandler
  322. * @param {Object} e Event object.
  323. * @private
  324. */
  325. _keyChangeHandler: function()
  326. {
  327. this._updateMinAndMax();
  328. this._updateTotalDataFlag = true;
  329. this.fire("dataUpdate");
  330. },
  331.  
  332. /**
  333. * Gets the default value for the `styles` attribute. Overrides
  334. * base implementation.
  335. *
  336. * @method _getDefaultStyles
  337. * @return Object
  338. * @protected
  339. */
  340. _getDefaultStyles: function()
  341. {
  342. var axisstyles = {
  343. majorUnit: {
  344. determinant:"count",
  345. count:11,
  346. distance:75
  347. }
  348. };
  349. return axisstyles;
  350. },
  351.  
  352. /**
  353. * Getter method for maximum attribute.
  354. *
  355. * @method _maximumGetter
  356. * @return Number
  357. * @private
  358. */
  359. _maximumGetter: function ()
  360. {
  361. var max = this.get("dataMaximum"),
  362. min = this.get("minimum");
  363. //If all values are zero, force a range so that the Axis and related series
  364. //will still render.
  365. if(min === 0 && max === 0)
  366. {
  367. max = 10;
  368. }
  369. if(Y_Lang.isNumber(this._setMaximum))
  370. {
  371. max = this._setMaximum;
  372. }
  373. return parseFloat(max);
  374. },
  375.  
  376. /**
  377. * Setter method for maximum attribute.
  378. *
  379. * @method _maximumSetter
  380. * @param {Object} value
  381. * @private
  382. */
  383. _maximumSetter: function (value)
  384. {
  385. this._setMaximum = parseFloat(value);
  386. return value;
  387. },
  388.  
  389. /**
  390. * Getter method for minimum attribute.
  391. *
  392. * @method _minimumGetter
  393. * @return Number
  394. * @private
  395. */
  396. _minimumGetter: function ()
  397. {
  398. var min = this.get("dataMinimum");
  399. if(Y_Lang.isNumber(this._setMinimum))
  400. {
  401. min = this._setMinimum;
  402. }
  403. return parseFloat(min);
  404. },
  405.  
  406. /**
  407. * Setter method for minimum attribute.
  408. *
  409. * @method _minimumSetter
  410. * @param {Object} value
  411. * @private
  412. */
  413. _minimumSetter: function(val)
  414. {
  415. this._setMinimum = parseFloat(val);
  416. return val;
  417. },
  418.  
  419. /**
  420. * Indicates whether or not the maximum attribute has been explicitly set.
  421. *
  422. * @method _getSetMax
  423. * @return Boolean
  424. * @private
  425. */
  426. _getSetMax: function()
  427. {
  428. return Y_Lang.isNumber(this._setMaximum);
  429. },
  430.  
  431.  
  432. /**
  433. * Returns and array of coordinates corresponding to an array of data values.
  434. *
  435. * @method _getCoordsFromValues
  436. * @param {Number} min The minimum for the axis.
  437. * @param {Number} max The maximum for the axis.
  438. * @param {Number} length The distance that the axis spans.
  439. * @param {Array} dataValues An array of values.
  440. * @param {Number} offset Value in which to offset the coordinates.
  441. * @param {Boolean} reverse Indicates whether the coordinates should start from
  442. * the end of an axis. Only used in the numeric implementation.
  443. * @return Array
  444. * @private
  445. */
  446. _getCoordsFromValues: function(min, max, length, dataValues, offset, reverse)
  447. {
  448. var i,
  449. valuecoords = [],
  450. len = dataValues.length;
  451. for(i = 0; i < len; i = i + 1)
  452. {
  453. valuecoords.push(this._getCoordFromValue.apply(this, [min, max, length, dataValues[i], offset, reverse]));
  454. }
  455. return valuecoords;
  456. },
  457.  
  458. /**
  459. * Returns and array of data values based on the axis' range and number of values.
  460. *
  461. * @method _getDataValuesByCount
  462. * @param {Number} count The number of values to be used.
  463. * @param {Number} min The minimum value of the axis.
  464. * @param {Number} max The maximum value of the axis.
  465. * @return Array
  466. * @private
  467. */
  468. _getDataValuesByCount: function(count, min, max)
  469. {
  470. var dataValues = [],
  471. dataValue = min,
  472. len = count - 1,
  473. range = max - min,
  474. increm = range/len,
  475. i;
  476. for(i = 0; i < len; i = i + 1)
  477. {
  478. dataValues.push(dataValue);
  479. dataValue = dataValue + increm;
  480. }
  481. dataValues.push(max);
  482. return dataValues;
  483. },
  484.  
  485. /**
  486. * Indicates whether or not the minimum attribute has been explicitly set.
  487. *
  488. * @method _getSetMin
  489. * @return Boolean
  490. * @private
  491. */
  492. _getSetMin: function()
  493. {
  494. return Y_Lang.isNumber(this._setMinimum);
  495. }
  496. }, {
  497. ATTRS: {
  498. /**
  499. * Determines whether and offset is automatically calculated for the edges of the axis.
  500. *
  501. * @attribute calculateEdgeOffset
  502. * @type Boolean
  503. */
  504. calculateEdgeOffset: {
  505. value: false
  506. },
  507.  
  508. labelFunction: {
  509. valueFn: function() {
  510. return this.formatLabel;
  511. }
  512. },
  513.  
  514. /**
  515. * Hash of array identifed by a string value.
  516. *
  517. * @attribute keys
  518. * @type Object
  519. */
  520. keys: {
  521. value: {},
  522.  
  523. setter: function(val)
  524. {
  525. var keys = {},
  526. i,
  527. len,
  528. data = this.get("dataProvider");
  529. if(Y_Lang.isArray(val))
  530. {
  531. len = val.length;
  532. for(i = 0; i < len; ++i)
  533. {
  534. keys[val[i]] = this._getKeyArray(val[i], data);
  535. }
  536.  
  537. }
  538. else if(Y_Lang.isString(val))
  539. {
  540. keys = this.get("keys");
  541. keys[val] = this._getKeyArray(val, data);
  542. }
  543. else
  544. {
  545. for(i in val)
  546. {
  547. if(val.hasOwnProperty(i))
  548. {
  549. keys[i] = this._getKeyArray(i, data);
  550. }
  551. }
  552. }
  553. this._updateTotalDataFlag = true;
  554. return keys;
  555. }
  556. },
  557.  
  558. /**
  559. *Returns the type of axis data
  560. * <dl>
  561. * <dt>time</dt><dd>Manages time data</dd>
  562. * <dt>stacked</dt><dd>Manages stacked numeric data</dd>
  563. * <dt>numeric</dt><dd>Manages numeric data</dd>
  564. * <dt>category</dt><dd>Manages categorical data</dd>
  565. * </dl>
  566. *
  567. * @attribute type
  568. * @type String
  569. */
  570. type:
  571. {
  572. readOnly: true,
  573.  
  574. getter: function ()
  575. {
  576. return this._type;
  577. }
  578. },
  579.  
  580. /**
  581. * Instance of `ChartDataProvider` that the class uses
  582. * to build its own data.
  583. *
  584. * @attribute dataProvider
  585. * @type Array
  586. */
  587. dataProvider:{
  588. setter: function (value)
  589. {
  590. return value;
  591. }
  592. },
  593.  
  594. /**
  595. * The maximum value contained in the `data` array. Used for
  596. * `maximum` when `autoMax` is true.
  597. *
  598. * @attribute dataMaximum
  599. * @type Number
  600. */
  601. dataMaximum: {
  602. getter: function ()
  603. {
  604. if(!Y_Lang.isNumber(this._dataMaximum))
  605. {
  606. this._updateMinAndMax();
  607. }
  608. return this._dataMaximum;
  609. }
  610. },
  611.  
  612. /**
  613. * The maximum value that will appear on an axis.
  614. *
  615. * @attribute maximum
  616. * @type Number
  617. */
  618. maximum: {
  619. lazyAdd: false,
  620.  
  621. getter: "_maximumGetter",
  622.  
  623. setter: "_maximumSetter"
  624. },
  625.  
  626. /**
  627. * The minimum value contained in the `data` array. Used for
  628. * `minimum` when `autoMin` is true.
  629. *
  630. * @attribute dataMinimum
  631. * @type Number
  632. */
  633. dataMinimum: {
  634. getter: function ()
  635. {
  636. if(!Y_Lang.isNumber(this._dataMinimum))
  637. {
  638. this._updateMinAndMax();
  639. }
  640. return this._dataMinimum;
  641. }
  642. },
  643.  
  644. /**
  645. * The minimum value that will appear on an axis.
  646. *
  647. * @attribute minimum
  648. * @type Number
  649. */
  650. minimum: {
  651. lazyAdd: false,
  652.  
  653. getter: "_minimumGetter",
  654.  
  655. setter: "_minimumSetter"
  656. },
  657.  
  658. /**
  659. * Determines whether the maximum is calculated or explicitly
  660. * set by the user.
  661. *
  662. * @attribute setMax
  663. * @type Boolean
  664. */
  665. setMax: {
  666. readOnly: true,
  667.  
  668. getter: "_getSetMax"
  669. },
  670.  
  671. /**
  672. * Determines whether the minimum is calculated or explicitly
  673. * set by the user.
  674. *
  675. * @attribute setMin
  676. * @type Boolean
  677. */
  678. setMin: {
  679. readOnly: true,
  680.  
  681. getter: "_getSetMin"
  682. },
  683.  
  684. /**
  685. * Array of axis data
  686. *
  687. * @attribute data
  688. * @type Array
  689. */
  690. data: {
  691. getter: function ()
  692. {
  693. if(!this._data || this._updateTotalDataFlag)
  694. {
  695. this._updateTotalData();
  696. }
  697. return this._data;
  698. }
  699. },
  700.  
  701. /**
  702. * Array containing all the keys in the axis.
  703.  
  704. * @attribute keyCollection
  705. * @type Array
  706. */
  707. keyCollection: {
  708. getter: function()
  709. {
  710. var keys = this.get("keys"),
  711. i,
  712. col = [];
  713. for(i in keys)
  714. {
  715. if(keys.hasOwnProperty(i))
  716. {
  717. col.push(i);
  718. }
  719. }
  720. return col;
  721. },
  722. readOnly: true
  723. },
  724.  
  725. /**
  726. * Object which should have by the labelFunction
  727. *
  728. * @attribute labelFunctionScope
  729. * @type Object
  730. */
  731. labelFunctionScope: {}
  732. }
  733. });
  734.