Point.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. /* *
  2. *
  3. * (c) 2010-2019 Torstein Honsi
  4. *
  5. * License: www.highcharts.com/license
  6. *
  7. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  8. *
  9. * */
  10. 'use strict';
  11. import Highcharts from './Globals.js';
  12. /**
  13. * Function callback when a series point is clicked. Return false to cancel the
  14. * action.
  15. *
  16. * @callback Highcharts.PointClickCallbackFunction
  17. *
  18. * @param {Highcharts.Point} this
  19. * The point where the event occured.
  20. *
  21. * @param {Highcharts.PointClickEventObject} event
  22. * Event arguments.
  23. */
  24. /**
  25. * Common information for a click event on a series point.
  26. *
  27. * @interface Highcharts.PointClickEventObject
  28. * @extends Highcharts.PointerEventObject
  29. */ /**
  30. * Clicked point.
  31. * @name Highcharts.PointClickEventObject#point
  32. * @type {Highcharts.Point}
  33. */
  34. /**
  35. * Configuration hash for the data label and tooltip formatters.
  36. *
  37. * @interface Highcharts.PointLabelObject
  38. */ /**
  39. * The point's current color.
  40. * @name Highcharts.PointLabelObject#color
  41. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
  42. */ /**
  43. * The point's current color index, used in styled mode instead of `color`. The
  44. * color index is inserted in class names used for styling.
  45. * @name Highcharts.PointLabelObject#colorIndex
  46. * @type {number}
  47. */ /**
  48. * The name of the related point.
  49. * @name Highcharts.PointLabelObject#key
  50. * @type {string|undefined}
  51. */ /**
  52. * The percentage for related points in a stacked series or pies.
  53. * @name Highcharts.PointLabelObject#percentage
  54. * @type {number}
  55. */ /**
  56. * The related point.
  57. * @name Highcharts.PointLabelObject#point
  58. * @type {Highcharts.Point}
  59. */ /**
  60. * The related series.
  61. * @name Highcharts.PointLabelObject#series
  62. * @type {Highcharts.Series}
  63. */ /**
  64. * The total of values in either a stack for stacked series, or a pie in a pie
  65. * series.
  66. * @name Highcharts.PointLabelObject#total
  67. * @type {number|undefined}
  68. */ /**
  69. * For categorized axes this property holds the category name for the point. For
  70. * other axes it holds the X value.
  71. * @name Highcharts.PointLabelObject#x
  72. * @type {number|string|undefined}
  73. */ /**
  74. * The y value of the point.
  75. * @name Highcharts.PointLabelObject#y
  76. * @type {number|undefined}
  77. */
  78. /**
  79. * Gets fired when the mouse leaves the area close to the point.
  80. *
  81. * @callback Highcharts.PointMouseOutCallbackFunction
  82. *
  83. * @param {Highcharts.Point} this
  84. * Point where the event occured.
  85. *
  86. * @param {global.PointerEvent} event
  87. * Event that occured.
  88. */
  89. /**
  90. * Gets fired when the mouse enters the area close to the point.
  91. *
  92. * @callback Highcharts.PointMouseOverCallbackFunction
  93. *
  94. * @param {Highcharts.Point} this
  95. * Point where the event occured.
  96. *
  97. * @param {global.Event} event
  98. * Event that occured.
  99. */
  100. /**
  101. * The generic point options for all series.
  102. *
  103. * In TypeScript you have to extend `PointOptionsObject` with an additional
  104. * declaration to allow custom data options:
  105. *
  106. * ```
  107. * declare interface PointOptionsObject {
  108. * customProperty: string;
  109. * }
  110. * ```
  111. *
  112. * @interface Highcharts.PointOptionsObject
  113. */
  114. /**
  115. * Possible option types for a data point.
  116. *
  117. * @typedef {number|string|Array<(number|string)>|Highcharts.PointOptionsObject|null} Highcharts.PointOptionsType
  118. */
  119. /**
  120. * Gets fired when the point is removed using the `.remove()` method.
  121. *
  122. * @callback Highcharts.PointRemoveCallbackFunction
  123. *
  124. * @param {Highcharts.Point} this
  125. * Point where the event occured.
  126. *
  127. * @param {global.Event} event
  128. * Event that occured.
  129. */
  130. /**
  131. * Possible key values for the point state options.
  132. *
  133. * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.PointStateValue
  134. */
  135. /**
  136. * Gets fired when the point is updated programmatically through the `.update()`
  137. * method.
  138. *
  139. * @callback Highcharts.PointUpdateCallbackFunction
  140. *
  141. * @param {Highcharts.Point} this
  142. * Point where the event occured.
  143. *
  144. * @param {Highcharts.PointUpdateEventObject} event
  145. * Event that occured.
  146. */
  147. /**
  148. * Information about the update event.
  149. *
  150. * @interface Highcharts.PointUpdateEventObject
  151. * @extends global.Event
  152. */ /**
  153. * Options data of the update event.
  154. * @name Highcharts.PointUpdateEventObject#options
  155. * @type {Highcharts.PointOptionsType}
  156. */
  157. import U from './Utilities.js';
  158. var animObject = U.animObject, defined = U.defined, erase = U.erase, extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, syncTimeout = U.syncTimeout, pick = U.pick;
  159. var Point, H = Highcharts, fireEvent = H.fireEvent, format = H.format, uniqueKey = H.uniqueKey, removeEvent = H.removeEvent;
  160. /* eslint-disable no-invalid-this, valid-jsdoc */
  161. /**
  162. * The Point object. The point objects are generated from the `series.data`
  163. * configuration objects or raw numbers. They can be accessed from the
  164. * `Series.points` array. Other ways to instantiate points are through {@link
  165. * Highcharts.Series#addPoint} or {@link Highcharts.Series#setData}.
  166. *
  167. * @class
  168. * @name Highcharts.Point
  169. */
  170. Highcharts.Point = Point = function () { };
  171. Highcharts.Point.prototype = {
  172. /**
  173. * Initialize the point. Called internally based on the `series.data`
  174. * option.
  175. *
  176. * @function Highcharts.Point#init
  177. *
  178. * @param {Highcharts.Series} series
  179. * The series object containing this point.
  180. *
  181. * @param {Highcharts.PointOptionsType} options
  182. * The data in either number, array or object format.
  183. *
  184. * @param {number} [x]
  185. * Optionally, the X value of the point.
  186. *
  187. * @return {Highcharts.Point}
  188. * The Point instance.
  189. *
  190. * @fires Highcharts.Point#event:afterInit
  191. */
  192. init: function (series, options, x) {
  193. /**
  194. * The series object associated with the point.
  195. *
  196. * @name Highcharts.Point#series
  197. * @type {Highcharts.Series}
  198. */
  199. this.series = series;
  200. this.applyOptions(options, x);
  201. // Add a unique ID to the point if none is assigned
  202. this.id = defined(this.id) ? this.id : uniqueKey();
  203. this.resolveColor();
  204. series.chart.pointCount++;
  205. fireEvent(this, 'afterInit');
  206. return this;
  207. },
  208. /**
  209. * @private
  210. * @function Highcharts.Point#resolveColor
  211. * @return {void}
  212. */
  213. resolveColor: function () {
  214. var series = this.series, colors, optionsChart = series.chart.options.chart, colorCount = optionsChart.colorCount, styledMode = series.chart.styledMode, colorIndex;
  215. /**
  216. * The point's current color.
  217. *
  218. * @name Highcharts.Point#color
  219. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
  220. */
  221. if (!styledMode && !this.options.color) {
  222. this.color = series.color; // #3445
  223. }
  224. if (series.options.colorByPoint) {
  225. if (!styledMode) {
  226. colors = series.options.colors || series.chart.options.colors;
  227. this.color = this.color || colors[series.colorCounter];
  228. colorCount = colors.length;
  229. }
  230. colorIndex = series.colorCounter;
  231. series.colorCounter++;
  232. // loop back to zero
  233. if (series.colorCounter === colorCount) {
  234. series.colorCounter = 0;
  235. }
  236. }
  237. else {
  238. colorIndex = series.colorIndex;
  239. }
  240. /**
  241. * The point's current color index, used in styled mode instead of
  242. * `color`. The color index is inserted in class names used for styling.
  243. *
  244. * @name Highcharts.Point#colorIndex
  245. * @type {number}
  246. */
  247. this.colorIndex = pick(this.colorIndex, colorIndex);
  248. },
  249. /**
  250. * Apply the options containing the x and y data and possible some extra
  251. * properties. Called on point init or from point.update.
  252. *
  253. * @private
  254. * @function Highcharts.Point#applyOptions
  255. *
  256. * @param {Highcharts.PointOptionsType} options
  257. * The point options as defined in series.data.
  258. *
  259. * @param {number} [x]
  260. * Optionally, the x value.
  261. *
  262. * @return {Highcharts.Point}
  263. * The Point instance.
  264. */
  265. applyOptions: function (options, x) {
  266. var point = this, series = point.series, pointValKey = series.options.pointValKey || series.pointValKey;
  267. options = Point.prototype.optionsToObject.call(this, options);
  268. // copy options directly to point
  269. extend(point, options);
  270. /**
  271. * The point's options as applied in the initial configuration, or
  272. * extended through `Point.update`.
  273. *
  274. * In TypeScript you have to extend `PointOptionsObject` via an
  275. * additional interface to allow custom data options:
  276. *
  277. * ```
  278. * declare interface PointOptionsObject {
  279. * customProperty: string;
  280. * }
  281. * ```
  282. *
  283. * @name Highcharts.Point#options
  284. * @type {Highcharts.PointOptionsObject}
  285. */
  286. point.options = point.options ?
  287. extend(point.options, options) :
  288. options;
  289. // Since options are copied into the Point instance, some accidental
  290. // options must be shielded (#5681)
  291. if (options.group) {
  292. delete point.group;
  293. }
  294. if (options.dataLabels) {
  295. delete point.dataLabels;
  296. }
  297. /**
  298. * The y value of the point.
  299. * @name Highcharts.Point#y
  300. * @type {number|undefined}
  301. */
  302. // For higher dimension series types. For instance, for ranges, point.y
  303. // is mapped to point.low.
  304. if (pointValKey) {
  305. point.y = point[pointValKey];
  306. }
  307. point.isNull = pick(point.isValid && !point.isValid(), point.x === null || !isNumber(point.y)); // #3571, check for NaN
  308. point.formatPrefix = point.isNull ? 'null' : 'point'; // #9233, #10874
  309. // The point is initially selected by options (#5777)
  310. if (point.selected) {
  311. point.state = 'select';
  312. }
  313. /**
  314. * The x value of the point.
  315. * @name Highcharts.Point#x
  316. * @type {number}
  317. */
  318. // If no x is set by now, get auto incremented value. All points must
  319. // have an x value, however the y value can be null to create a gap in
  320. // the series
  321. if ('name' in point &&
  322. typeof x === 'undefined' &&
  323. series.xAxis &&
  324. series.xAxis.hasNames) {
  325. point.x = series.xAxis.nameToX(point);
  326. }
  327. if (typeof point.x === 'undefined' && series) {
  328. if (typeof x === 'undefined') {
  329. point.x = series.autoIncrement(point);
  330. }
  331. else {
  332. point.x = x;
  333. }
  334. }
  335. return point;
  336. },
  337. /**
  338. * Set a value in an object, on the property defined by key. The key
  339. * supports nested properties using dot notation. The function modifies the
  340. * input object and does not make a copy.
  341. *
  342. * @function Highcharts.Point#setNestedProperty<T>
  343. *
  344. * @param {T} object
  345. * The object to set the value on.
  346. *
  347. * @param {*} value
  348. * The value to set.
  349. *
  350. * @param {string} key
  351. * Key to the property to set.
  352. *
  353. * @return {T}
  354. * The modified object.
  355. */
  356. setNestedProperty: function (object, value, key) {
  357. var nestedKeys = key.split('.');
  358. nestedKeys.reduce(function (result, key, i, arr) {
  359. var isLastKey = arr.length - 1 === i;
  360. result[key] = (isLastKey ?
  361. value :
  362. isObject(result[key], true) ?
  363. result[key] :
  364. {});
  365. return result[key];
  366. }, object);
  367. return object;
  368. },
  369. /**
  370. * Transform number or array configs into objects. Also called for object
  371. * configs. Used internally to unify the different configuration formats for
  372. * points. For example, a simple number `10` in a line series will be
  373. * transformed to `{ y: 10 }`, and an array config like `[1, 10]` in a
  374. * scatter series will be transformed to `{ x: 1, y: 10 }`.
  375. *
  376. * @function Highcharts.Point#optionsToObject
  377. *
  378. * @param {Highcharts.PointOptionsType} options
  379. * The input option.
  380. *
  381. * @return {Highcharts.Dictionary<*>}
  382. * Transformed options.
  383. */
  384. optionsToObject: function (options) {
  385. var ret = {}, series = this.series, keys = series.options.keys, pointArrayMap = keys || series.pointArrayMap || ['y'], valueCount = pointArrayMap.length, firstItemType, i = 0, j = 0;
  386. if (isNumber(options) || options === null) {
  387. ret[pointArrayMap[0]] = options;
  388. }
  389. else if (isArray(options)) {
  390. // with leading x value
  391. if (!keys && options.length > valueCount) {
  392. firstItemType = typeof options[0];
  393. if (firstItemType === 'string') {
  394. ret.name = options[0];
  395. }
  396. else if (firstItemType === 'number') {
  397. ret.x = options[0];
  398. }
  399. i++;
  400. }
  401. while (j < valueCount) {
  402. // Skip undefined positions for keys
  403. if (!keys || typeof options[i] !== 'undefined') {
  404. if (pointArrayMap[j].indexOf('.') > 0) {
  405. // Handle nested keys, e.g. ['color.pattern.image']
  406. // Avoid function call unless necessary.
  407. H.Point.prototype.setNestedProperty(ret, options[i], pointArrayMap[j]);
  408. }
  409. else {
  410. ret[pointArrayMap[j]] = options[i];
  411. }
  412. }
  413. i++;
  414. j++;
  415. }
  416. }
  417. else if (typeof options === 'object') {
  418. ret = options;
  419. // This is the fastest way to detect if there are individual point
  420. // dataLabels that need to be considered in drawDataLabels. These
  421. // can only occur in object configs.
  422. if (options.dataLabels) {
  423. series._hasPointLabels = true;
  424. }
  425. // Same approach as above for markers
  426. if (options.marker) {
  427. series._hasPointMarkers = true;
  428. }
  429. }
  430. return ret;
  431. },
  432. /**
  433. * Get the CSS class names for individual points. Used internally where the
  434. * returned value is set on every point.
  435. *
  436. * @function Highcharts.Point#getClassName
  437. *
  438. * @return {string}
  439. * The class names.
  440. */
  441. getClassName: function () {
  442. return 'highcharts-point' +
  443. (this.selected ? ' highcharts-point-select' : '') +
  444. (this.negative ? ' highcharts-negative' : '') +
  445. (this.isNull ? ' highcharts-null-point' : '') +
  446. (typeof this.colorIndex !== 'undefined' ?
  447. ' highcharts-color-' + this.colorIndex : '') +
  448. (this.options.className ? ' ' + this.options.className : '') +
  449. (this.zone && this.zone.className ? ' ' +
  450. this.zone.className.replace('highcharts-negative', '') : '');
  451. },
  452. /**
  453. * In a series with `zones`, return the zone that the point belongs to.
  454. *
  455. * @function Highcharts.Point#getZone
  456. *
  457. * @return {Highcharts.SeriesZonesOptionsObject}
  458. * The zone item.
  459. */
  460. getZone: function () {
  461. var series = this.series, zones = series.zones, zoneAxis = series.zoneAxis || 'y', i = 0, zone;
  462. zone = zones[i];
  463. while (this[zoneAxis] >= zone.value) {
  464. zone = zones[++i];
  465. }
  466. // For resetting or reusing the point (#8100)
  467. if (!this.nonZonedColor) {
  468. this.nonZonedColor = this.color;
  469. }
  470. if (zone && zone.color && !this.options.color) {
  471. this.color = zone.color;
  472. }
  473. else {
  474. this.color = this.nonZonedColor;
  475. }
  476. return zone;
  477. },
  478. /**
  479. * Utility to check if point has new shape type. Used in column series and
  480. * all others that are based on column series.
  481. *
  482. * @return boolean|undefined
  483. */
  484. hasNewShapeType: function () {
  485. var oldShapeType = this.graphic &&
  486. (this.graphic.symbolName || this.graphic.element.nodeName);
  487. return oldShapeType !== this.shapeType;
  488. },
  489. /**
  490. * Destroy a point to clear memory. Its reference still stays in
  491. * `series.data`.
  492. *
  493. * @private
  494. * @function Highcharts.Point#destroy
  495. * @return {void}
  496. */
  497. destroy: function () {
  498. var point = this, series = point.series, chart = series.chart, dataSorting = series.options.dataSorting, hoverPoints = chart.hoverPoints, globalAnimation = point.series.chart.renderer.globalAnimation, animation = animObject(globalAnimation), prop;
  499. /**
  500. * Allow to call after animation.
  501. * @private
  502. */
  503. function destroyPoint() {
  504. if (hoverPoints) {
  505. point.setState();
  506. erase(hoverPoints, point);
  507. if (!hoverPoints.length) {
  508. chart.hoverPoints = null;
  509. }
  510. }
  511. if (point === chart.hoverPoint) {
  512. point.onMouseOut();
  513. }
  514. // Remove all events and elements
  515. if (point.graphic || point.dataLabel || point.dataLabels) {
  516. removeEvent(point);
  517. point.destroyElements();
  518. }
  519. for (prop in point) { // eslint-disable-line guard-for-in
  520. point[prop] = null;
  521. }
  522. }
  523. // Remove properties after animation
  524. if (!dataSorting || !dataSorting.enabled) {
  525. destroyPoint();
  526. }
  527. else {
  528. this.animateBeforeDestroy();
  529. syncTimeout(destroyPoint, animation.duration);
  530. }
  531. chart.pointCount--;
  532. if (point.legendItem) { // pies have legend items
  533. chart.legend.destroyItem(point);
  534. }
  535. },
  536. /**
  537. * Animate SVG elements associated with the point.
  538. *
  539. * @private
  540. * @function Highcharts.Point#animateBeforeDestroy
  541. * @return {void}
  542. */
  543. animateBeforeDestroy: function () {
  544. var point = this, animateParams = { x: point.startXPos, opacity: 0 }, isDataLabel, graphicalProps = point.getGraphicalProps();
  545. graphicalProps.singular.forEach(function (prop) {
  546. isDataLabel = prop === 'dataLabel';
  547. point[prop] = point[prop].animate(isDataLabel ? {
  548. x: point[prop].startXPos,
  549. y: point[prop].startYPos,
  550. opacity: 0
  551. } : animateParams);
  552. });
  553. graphicalProps.plural.forEach(function (plural) {
  554. point[plural].forEach(function (item) {
  555. if (item.element) {
  556. item.animate(extend({ x: point.startXPos }, (item.startYPos ? {
  557. x: item.startXPos,
  558. y: item.startYPos
  559. } : {})));
  560. }
  561. });
  562. });
  563. },
  564. /**
  565. * Destroy SVG elements associated with the point.
  566. *
  567. * @private
  568. * @function Highcharts.Point#destroyElements
  569. * @param {Highcharts.Dictionary<number>} [kinds]
  570. * @return {void}
  571. */
  572. destroyElements: function (kinds) {
  573. var point = this, props = point.getGraphicalProps(kinds);
  574. props.singular.forEach(function (prop) {
  575. point[prop] = point[prop].destroy();
  576. });
  577. props.plural.forEach(function (plural) {
  578. point[plural].forEach(function (item) {
  579. if (item.element) {
  580. item.destroy();
  581. }
  582. });
  583. delete point[plural];
  584. });
  585. },
  586. /**
  587. * Get props of all existing graphical point elements.
  588. *
  589. * @private
  590. * @function Highcharts.Point#getGraphicalProps
  591. * @param {Highcharts.Dictionary<number>} [kinds]
  592. * @return {Highcharts.PointGraphicalProps}
  593. */
  594. getGraphicalProps: function (kinds) {
  595. var point = this, props = [], prop, i, graphicalProps = { singular: [], plural: [] };
  596. kinds = kinds || { graphic: 1, dataLabel: 1 };
  597. if (kinds.graphic) {
  598. props.push('graphic', 'shadowGroup');
  599. }
  600. if (kinds.dataLabel) {
  601. props.push('dataLabel', 'dataLabelUpper', 'connector');
  602. }
  603. i = props.length;
  604. while (i--) {
  605. prop = props[i];
  606. if (point[prop]) {
  607. graphicalProps.singular.push(prop);
  608. }
  609. }
  610. ['dataLabel', 'connector'].forEach(function (prop) {
  611. var plural = prop + 's';
  612. if (kinds[prop] && point[plural]) {
  613. graphicalProps.plural.push(plural);
  614. }
  615. });
  616. return graphicalProps;
  617. },
  618. /**
  619. * Return the configuration hash needed for the data label and tooltip
  620. * formatters.
  621. *
  622. * @function Highcharts.Point#getLabelConfig
  623. *
  624. * @return {Highcharts.PointLabelObject}
  625. * Abstract object used in formatters and formats.
  626. */
  627. getLabelConfig: function () {
  628. return {
  629. x: this.category,
  630. y: this.y,
  631. color: this.color,
  632. colorIndex: this.colorIndex,
  633. key: this.name || this.category,
  634. series: this.series,
  635. point: this,
  636. percentage: this.percentage,
  637. total: this.total || this.stackTotal
  638. };
  639. },
  640. /**
  641. * Extendable method for formatting each point's tooltip line.
  642. *
  643. * @function Highcharts.Point#tooltipFormatter
  644. *
  645. * @param {string} pointFormat
  646. * The point format.
  647. *
  648. * @return {string}
  649. * A string to be concatenated in to the common tooltip text.
  650. */
  651. tooltipFormatter: function (pointFormat) {
  652. // Insert options for valueDecimals, valuePrefix, and valueSuffix
  653. var series = this.series, seriesTooltipOptions = series.tooltipOptions, valueDecimals = pick(seriesTooltipOptions.valueDecimals, ''), valuePrefix = seriesTooltipOptions.valuePrefix || '', valueSuffix = seriesTooltipOptions.valueSuffix || '';
  654. // Replace default point style with class name
  655. if (series.chart.styledMode) {
  656. pointFormat =
  657. series.chart.tooltip.styledModeFormat(pointFormat);
  658. }
  659. // Loop over the point array map and replace unformatted values with
  660. // sprintf formatting markup
  661. (series.pointArrayMap || ['y']).forEach(function (key) {
  662. key = '{point.' + key; // without the closing bracket
  663. if (valuePrefix || valueSuffix) {
  664. pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), valuePrefix + key + '}' + valueSuffix);
  665. }
  666. pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), key + ':,.' + valueDecimals + 'f}');
  667. });
  668. return format(pointFormat, {
  669. point: this,
  670. series: this.series
  671. }, series.chart);
  672. },
  673. /**
  674. * Fire an event on the Point object.
  675. *
  676. * @private
  677. * @function Highcharts.Point#firePointEvent
  678. *
  679. * @param {string} eventType
  680. * Type of the event.
  681. *
  682. * @param {Highcharts.Dictionary<any>|Event} [eventArgs]
  683. * Additional event arguments.
  684. *
  685. * @param {Highcharts.EventCallbackFunction<Highcharts.Point>|Function} [defaultFunction]
  686. * Default event handler.
  687. *
  688. * @fires Highcharts.Point#event:*
  689. */
  690. firePointEvent: function (eventType, eventArgs, defaultFunction) {
  691. var point = this, series = this.series, seriesOptions = series.options;
  692. // load event handlers on demand to save time on mouseover/out
  693. if (seriesOptions.point.events[eventType] ||
  694. (point.options &&
  695. point.options.events &&
  696. point.options.events[eventType])) {
  697. this.importEvents();
  698. }
  699. // add default handler if in selection mode
  700. if (eventType === 'click' && seriesOptions.allowPointSelect) {
  701. defaultFunction = function (event) {
  702. // Control key is for Windows, meta (= Cmd key) for Mac, Shift
  703. // for Opera.
  704. if (point.select) { // #2911
  705. point.select(null, event.ctrlKey || event.metaKey || event.shiftKey);
  706. }
  707. };
  708. }
  709. fireEvent(this, eventType, eventArgs, defaultFunction);
  710. },
  711. /**
  712. * For categorized axes this property holds the category name for the
  713. * point. For other axes it holds the X value.
  714. *
  715. * @name Highcharts.Point#category
  716. * @type {number|string}
  717. */
  718. /**
  719. * The name of the point. The name can be given as the first position of the
  720. * point configuration array, or as a `name` property in the configuration:
  721. *
  722. * @example
  723. * // Array config
  724. * data: [
  725. * ['John', 1],
  726. * ['Jane', 2]
  727. * ]
  728. *
  729. * // Object config
  730. * data: [{
  731. * name: 'John',
  732. * y: 1
  733. * }, {
  734. * name: 'Jane',
  735. * y: 2
  736. * }]
  737. *
  738. * @name Highcharts.Point#name
  739. * @type {string}
  740. */
  741. /**
  742. * The percentage for points in a stacked series or pies.
  743. *
  744. * @name Highcharts.Point#percentage
  745. * @type {number}
  746. */
  747. /**
  748. * The total of values in either a stack for stacked series, or a pie in a
  749. * pie series.
  750. *
  751. * @name Highcharts.Point#total
  752. * @type {number}
  753. */
  754. /**
  755. * For certain series types, like pie charts, where individual points can
  756. * be shown or hidden.
  757. *
  758. * @name Highcharts.Point#visible
  759. * @type {boolean}
  760. */
  761. visible: true
  762. };