Series.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-chart-series-Series'>/**
  19. </span> * @class Ext.chart.series.Series
  20. *
  21. * Series is the abstract class containing the common logic to all chart series. Series includes
  22. * methods from Labels, Highlights, Tips and Callouts mixins. This class implements the logic of handling
  23. * mouse events, animating, hiding, showing all elements and returning the color of the series to be used as a legend item.
  24. *
  25. * ## Listeners
  26. *
  27. * The series class supports listeners via the Observable syntax. Some of these listeners are:
  28. *
  29. * - `itemmouseup` When the user interacts with a marker.
  30. * - `itemmousedown` When the user interacts with a marker.
  31. * - `itemmousemove` When the user iteracts with a marker.
  32. * - `afterrender` Will be triggered when the animation ends or when the series has been rendered completely.
  33. *
  34. * For example:
  35. *
  36. * series: [{
  37. * type: 'column',
  38. * axis: 'left',
  39. * listeners: {
  40. * 'afterrender': function() {
  41. * console('afterrender');
  42. * }
  43. * },
  44. * xField: 'category',
  45. * yField: 'data1'
  46. * }]
  47. */
  48. Ext.define('Ext.chart.series.Series', {
  49. /* Begin Definitions */
  50. mixins: {
  51. observable: 'Ext.util.Observable',
  52. labels: 'Ext.chart.Label',
  53. highlights: 'Ext.chart.Highlight',
  54. tips: 'Ext.chart.Tip',
  55. callouts: 'Ext.chart.Callout'
  56. },
  57. /* End Definitions */
  58. <span id='Ext-chart-series-Series-cfg-highlight'> /**
  59. </span> * @cfg {Boolean/Object} highlight
  60. * If set to `true` it will highlight the markers or the series when hovering
  61. * with the mouse. This parameter can also be an object with the same style
  62. * properties you would apply to a {@link Ext.draw.Sprite} to apply custom
  63. * styles to markers and series.
  64. */
  65. <span id='Ext-chart-series-Series-cfg-tips'> /**
  66. </span> * @cfg {Object} tips
  67. * Add tooltips to the visualization's markers. The options for the tips are the
  68. * same configuration used with {@link Ext.tip.ToolTip}. For example:
  69. *
  70. * tips: {
  71. * trackMouse: true,
  72. * width: 140,
  73. * height: 28,
  74. * renderer: function(storeItem, item) {
  75. * this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data1') + ' views');
  76. * }
  77. * },
  78. */
  79. <span id='Ext-chart-series-Series-cfg-type'> /**
  80. </span> * @cfg {String} type
  81. * The type of series. Set in subclasses.
  82. */
  83. type: null,
  84. <span id='Ext-chart-series-Series-cfg-title'> /**
  85. </span> * @cfg {String} title
  86. * The human-readable name of the series.
  87. */
  88. title: null,
  89. <span id='Ext-chart-series-Series-cfg-showInLegend'> /**
  90. </span> * @cfg {Boolean} showInLegend
  91. * Whether to show this series in the legend.
  92. */
  93. showInLegend: true,
  94. <span id='Ext-chart-series-Series-cfg-renderer'> /**
  95. </span> * @cfg {Function} renderer
  96. * A function that can be overridden to set custom styling properties to each rendered element.
  97. * Passes in (sprite, record, attributes, index, store) to the function.
  98. */
  99. renderer: function(sprite, record, attributes, index, store) {
  100. return attributes;
  101. },
  102. <span id='Ext-chart-series-Series-cfg-shadowAttributes'> /**
  103. </span> * @cfg {Array} shadowAttributes
  104. * An array with shadow attributes
  105. */
  106. shadowAttributes: null,
  107. // @private animating flag
  108. animating: false,
  109. <span id='Ext-chart-series-Series-cfg-listeners'> /**
  110. </span> * @cfg {Object} listeners
  111. * An (optional) object with event callbacks. All event callbacks get the target *item* as first parameter. The callback functions are:
  112. *
  113. * - itemmouseover
  114. * - itemmouseout
  115. * - itemmousedown
  116. * - itemmouseup
  117. */
  118. constructor: function(config) {
  119. var me = this;
  120. if (config) {
  121. Ext.apply(me, config);
  122. }
  123. me.shadowGroups = [];
  124. me.mixins.labels.constructor.call(me, config);
  125. me.mixins.highlights.constructor.call(me, config);
  126. me.mixins.tips.constructor.call(me, config);
  127. me.mixins.callouts.constructor.call(me, config);
  128. me.addEvents({
  129. scope: me,
  130. itemmouseover: true,
  131. itemmouseout: true,
  132. itemmousedown: true,
  133. itemmouseup: true,
  134. mouseleave: true,
  135. afterdraw: true,
  136. <span id='Ext-chart-series-Series-event-titlechange'> /**
  137. </span> * @event titlechange
  138. * Fires when the series title is changed via {@link #setTitle}.
  139. * @param {String} title The new title value
  140. * @param {Number} index The index in the collection of titles
  141. */
  142. titlechange: true
  143. });
  144. me.mixins.observable.constructor.call(me, config);
  145. me.on({
  146. scope: me,
  147. itemmouseover: me.onItemMouseOver,
  148. itemmouseout: me.onItemMouseOut,
  149. mouseleave: me.onMouseLeave
  150. });
  151. if (me.style) {
  152. Ext.apply(me.seriesStyle, me.style);
  153. }
  154. },
  155. <span id='Ext-chart-series-Series-method-eachRecord'> /**
  156. </span> * Iterate over each of the records for this series. The default implementation simply iterates
  157. * through the entire data store, but individual series implementations can override this to
  158. * provide custom handling, e.g. adding/removing records.
  159. * @param {Function} fn The function to execute for each record.
  160. * @param {Object} scope Scope for the fn.
  161. */
  162. eachRecord: function(fn, scope) {
  163. var chart = this.chart;
  164. (chart.substore || chart.store).each(fn, scope);
  165. },
  166. <span id='Ext-chart-series-Series-method-getRecordCount'> /**
  167. </span> * Return the number of records being displayed in this series. Defaults to the number of
  168. * records in the store; individual series implementations can override to provide custom handling.
  169. */
  170. getRecordCount: function() {
  171. var chart = this.chart,
  172. store = chart.substore || chart.store;
  173. return store ? store.getCount() : 0;
  174. },
  175. <span id='Ext-chart-series-Series-method-isExcluded'> /**
  176. </span> * Determines whether the series item at the given index has been excluded, i.e. toggled off in the legend.
  177. * @param index
  178. */
  179. isExcluded: function(index) {
  180. var excludes = this.__excludes;
  181. return !!(excludes &amp;&amp; excludes[index]);
  182. },
  183. // @private set the bbox and clipBox for the series
  184. setBBox: function(noGutter) {
  185. var me = this,
  186. chart = me.chart,
  187. chartBBox = chart.chartBBox,
  188. gutterX = noGutter ? 0 : chart.maxGutter[0],
  189. gutterY = noGutter ? 0 : chart.maxGutter[1],
  190. clipBox, bbox;
  191. clipBox = {
  192. x: chartBBox.x,
  193. y: chartBBox.y,
  194. width: chartBBox.width,
  195. height: chartBBox.height
  196. };
  197. me.clipBox = clipBox;
  198. bbox = {
  199. x: (clipBox.x + gutterX) - (chart.zoom.x * chart.zoom.width),
  200. y: (clipBox.y + gutterY) - (chart.zoom.y * chart.zoom.height),
  201. width: (clipBox.width - (gutterX * 2)) * chart.zoom.width,
  202. height: (clipBox.height - (gutterY * 2)) * chart.zoom.height
  203. };
  204. me.bbox = bbox;
  205. },
  206. // @private set the animation for the sprite
  207. onAnimate: function(sprite, attr) {
  208. var me = this;
  209. sprite.stopAnimation();
  210. if (me.animating) {
  211. return sprite.animate(Ext.applyIf(attr, me.chart.animate));
  212. } else {
  213. me.animating = true;
  214. return sprite.animate(Ext.apply(Ext.applyIf(attr, me.chart.animate), {
  215. listeners: {
  216. 'afteranimate': function() {
  217. me.animating = false;
  218. me.fireEvent('afterrender');
  219. }
  220. }
  221. }));
  222. }
  223. },
  224. // @private return the gutter.
  225. getGutters: function() {
  226. return [0, 0];
  227. },
  228. // @private wrapper for the itemmouseover event.
  229. onItemMouseOver: function(item) {
  230. var me = this;
  231. if (item.series === me) {
  232. if (me.highlight) {
  233. me.highlightItem(item);
  234. }
  235. if (me.tooltip) {
  236. me.showTip(item);
  237. }
  238. }
  239. },
  240. // @private wrapper for the itemmouseout event.
  241. onItemMouseOut: function(item) {
  242. var me = this;
  243. if (item.series === me) {
  244. me.unHighlightItem();
  245. if (me.tooltip) {
  246. me.hideTip(item);
  247. }
  248. }
  249. },
  250. // @private wrapper for the mouseleave event.
  251. onMouseLeave: function() {
  252. var me = this;
  253. me.unHighlightItem();
  254. if (me.tooltip) {
  255. me.hideTip();
  256. }
  257. },
  258. <span id='Ext-chart-series-Series-method-getItemForPoint'> /**
  259. </span> * For a given x/y point relative to the Surface, find a corresponding item from this
  260. * series, if any.
  261. * @param {Number} x
  262. * @param {Number} y
  263. * @return {Object} An object describing the item, or null if there is no matching item.
  264. * The exact contents of this object will vary by series type, but should always contain the following:
  265. * @return {Ext.chart.series.Series} return.series the Series object to which the item belongs
  266. * @return {Object} return.value the value(s) of the item's data point
  267. * @return {Array} return.point the x/y coordinates relative to the chart box of a single point
  268. * for this data item, which can be used as e.g. a tooltip anchor point.
  269. * @return {Ext.draw.Sprite} return.sprite the item's rendering Sprite.
  270. */
  271. getItemForPoint: function(x, y) {
  272. //if there are no items to query just return null.
  273. if (!this.items || !this.items.length || this.seriesIsHidden) {
  274. return null;
  275. }
  276. var me = this,
  277. items = me.items,
  278. bbox = me.bbox,
  279. item, i, ln;
  280. // Check bounds
  281. if (!Ext.draw.Draw.withinBox(x, y, bbox)) {
  282. return null;
  283. }
  284. for (i = 0, ln = items.length; i &lt; ln; i++) {
  285. if (items[i] &amp;&amp; this.isItemInPoint(x, y, items[i], i)) {
  286. return items[i];
  287. }
  288. }
  289. return null;
  290. },
  291. isItemInPoint: function(x, y, item, i) {
  292. return false;
  293. },
  294. <span id='Ext-chart-series-Series-method-hideAll'> /**
  295. </span> * Hides all the elements in the series.
  296. */
  297. hideAll: function() {
  298. var me = this,
  299. items = me.items,
  300. item, len, i, j, l, sprite, shadows;
  301. me.seriesIsHidden = true;
  302. me._prevShowMarkers = me.showMarkers;
  303. me.showMarkers = false;
  304. //hide all labels
  305. me.hideLabels(0);
  306. //hide all sprites
  307. for (i = 0, len = items.length; i &lt; len; i++) {
  308. item = items[i];
  309. sprite = item.sprite;
  310. if (sprite) {
  311. sprite.setAttributes({
  312. hidden: true
  313. }, true);
  314. }
  315. if (sprite &amp;&amp; sprite.shadows) {
  316. shadows = sprite.shadows;
  317. for (j = 0, l = shadows.length; j &lt; l; ++j) {
  318. shadows[j].setAttributes({
  319. hidden: true
  320. }, true);
  321. }
  322. }
  323. }
  324. },
  325. <span id='Ext-chart-series-Series-method-showAll'> /**
  326. </span> * Shows all the elements in the series.
  327. */
  328. showAll: function() {
  329. var me = this,
  330. prevAnimate = me.chart.animate;
  331. me.chart.animate = false;
  332. me.seriesIsHidden = false;
  333. me.showMarkers = me._prevShowMarkers;
  334. me.drawSeries();
  335. me.chart.animate = prevAnimate;
  336. },
  337. hide: function() {
  338. if (this.items) {
  339. var me = this,
  340. items = me.items,
  341. i, j, lsh, ln, shadows;
  342. if (items &amp;&amp; items.length) {
  343. for (i = 0, ln = items.length; i &lt; ln; ++i) {
  344. if (items[i].sprite) {
  345. items[i].sprite.hide(true);
  346. shadows = items[i].shadows || items[i].sprite.shadows;
  347. if (shadows) {
  348. for (j = 0, lsh = shadows.length; j &lt; lsh; ++j) {
  349. shadows[j].hide(true);
  350. }
  351. }
  352. }
  353. }
  354. me.hideLabels();
  355. }
  356. }
  357. },
  358. <span id='Ext-chart-series-Series-method-getLegendColor'> /**
  359. </span> * Returns a string with the color to be used for the series legend item.
  360. */
  361. getLegendColor: function(index) {
  362. var me = this, fill, stroke;
  363. if (me.seriesStyle) {
  364. fill = me.seriesStyle.fill;
  365. stroke = me.seriesStyle.stroke;
  366. if (fill &amp;&amp; fill != 'none') {
  367. return fill;
  368. }
  369. if(stroke){
  370. return stroke;
  371. }
  372. }
  373. return (me.colorArrayStyle)?me.colorArrayStyle[me.seriesIdx % me.colorArrayStyle.length]:'#000';
  374. },
  375. <span id='Ext-chart-series-Series-method-visibleInLegend'> /**
  376. </span> * Checks whether the data field should be visible in the legend
  377. * @private
  378. * @param {Number} index The index of the current item
  379. */
  380. visibleInLegend: function(index){
  381. var excludes = this.__excludes;
  382. if (excludes) {
  383. return !excludes[index];
  384. }
  385. return !this.seriesIsHidden;
  386. },
  387. <span id='Ext-chart-series-Series-method-setTitle'> /**
  388. </span> * Changes the value of the {@link #title} for the series.
  389. * Arguments can take two forms:
  390. * &lt;ul&gt;
  391. * &lt;li&gt;A single String value: this will be used as the new single title for the series (applies
  392. * to series with only one yField)&lt;/li&gt;
  393. * &lt;li&gt;A numeric index and a String value: this will set the title for a single indexed yField.&lt;/li&gt;
  394. * &lt;/ul&gt;
  395. * @param {Number} index
  396. * @param {String} title
  397. */
  398. setTitle: function(index, title) {
  399. var me = this,
  400. oldTitle = me.title;
  401. if (Ext.isString(index)) {
  402. title = index;
  403. index = 0;
  404. }
  405. if (Ext.isArray(oldTitle)) {
  406. oldTitle[index] = title;
  407. } else {
  408. me.title = title;
  409. }
  410. me.fireEvent('titlechange', title, index);
  411. }
  412. });
  413. </pre>
  414. </body>
  415. </html>