Chart/api/tooltip.ts

  1. /**
  2. * Copyright (c) 2017 ~ present NAVER Corp.
  3. * billboard.js project is licensed under the MIT license
  4. */
  5. import {$SHAPE} from "../../config/classes";
  6. import {isDefined} from "../../module/util";
  7. /**
  8. * Define tooltip
  9. * @ignore
  10. */
  11. const tooltip = {
  12. /**
  13. * Show tooltip
  14. * @function tooltip․show
  15. * @instance
  16. * @memberof Chart
  17. * @param {object} args The object can consist with following members:<br>
  18. *
  19. * | Key | Type | Description |
  20. * | --- | --- | --- |
  21. * | index | Number | Determine focus by index |
  22. * | x | Number &vert; Date | Determine focus by x Axis index |
  23. * | mouse | Array | Determine x and y coordinate value relative the targeted '.bb-event-rect' x Axis.<br>It should be used along with `data`, `index` or `x` value. The default value is set as `[0,0]` |
  24. * | data | Object | When [data.xs](Options.html#.data%25E2%2580%25A4xs) option is used or [tooltip.grouped](Options.html#.tooltip) set to 'false', `should be used giving this param`.<br><br>**Key:**<br>- x {number &verbar; Date}: x Axis value<br>- index {number}: x Axis index (useless for data.xs)<br>- id {string}: data id<br>- value {number}: The corresponding value for tooltip. |
  25. *
  26. * @example
  27. * // show the 2nd x Axis coordinate tooltip
  28. * // for Arc(gauge, donut & pie) and radar type, approch showing tooltip by using "index" number.
  29. * chart.tooltip.show({
  30. * index: 1
  31. * });
  32. *
  33. * // show tooltip for the 3rd x Axis in x:50 and y:100 coordinate of '.bb-event-rect' of the x Axis.
  34. * chart.tooltip.show({
  35. * x: 2,
  36. * mouse: [50, 100]
  37. * });
  38. *
  39. * // show tooltip for timeseries x axis
  40. * chart.tooltip.show({
  41. * x: new Date("2018-01-02 00:00")
  42. * });
  43. *
  44. * // treemap type can be shown by using "id" only.
  45. * chart.tooltip.show({
  46. * data: {
  47. * id: "data1" // data id
  48. * }
  49. * });
  50. *
  51. * // for Arc types, specify 'id' or 'index'
  52. * chart.tooltip.show({ data: { id: "data2" }});
  53. * chart.tooltip.show({ data: { index: 2 }});
  54. *
  55. * // when data.xs is used
  56. * chart.tooltip.show({
  57. * data: {
  58. * x: 3, // x Axis value
  59. * id: "data1", // data id
  60. * value: 500 // data value
  61. * }
  62. * });
  63. *
  64. * // when data.xs isn't used, but tooltip.grouped=false is set
  65. * chart.tooltip.show({
  66. * data: {
  67. * index: 3, // or 'x' key value
  68. * id: "data1", // data id
  69. * value: 500 // data value
  70. * }
  71. * });
  72. */
  73. show: function(args): void {
  74. const $$ = this.internal;
  75. const {$el, config, state: {eventReceiver, hasFunnel, hasTreemap, inputType}} = $$;
  76. let index;
  77. let mouse;
  78. // determine mouse position on the chart
  79. if (args.mouse) {
  80. mouse = args.mouse;
  81. }
  82. // determine focus data
  83. if (args.data) {
  84. const {data} = args;
  85. const y = $$.getYScaleById(data.id)?.(data.value);
  86. if ((hasFunnel || hasTreemap) && data.id) {
  87. const selector = $$.selectorTarget(data.id, undefined, `.${$SHAPE.shape}`);
  88. eventReceiver.rect = $el.main.select(selector);
  89. } else if ($$.isMultipleX()) {
  90. // if multiple xs, target point will be determined by mouse
  91. mouse = [$$.xx(data), y];
  92. } else {
  93. if (!config.tooltip_grouped) {
  94. mouse = [0, y];
  95. }
  96. index = data.index ?? (
  97. $$.hasArcType() && data.id ?
  98. $$.getArcElementByIdOrIndex(data.id)?.datum().index :
  99. $$.getIndexByX(data.x)
  100. );
  101. }
  102. } else if (isDefined(args.x)) {
  103. index = $$.getIndexByX(args.x);
  104. } else if (isDefined(args.index)) {
  105. index = args.index;
  106. }
  107. (inputType === "mouse" ? ["mouseover", "mousemove"] : ["touchstart"]).forEach(eventName => {
  108. $$.dispatchEvent(eventName, index, mouse);
  109. });
  110. },
  111. /**
  112. * Hide tooltip
  113. * @function tooltip․hide
  114. * @instance
  115. * @memberof Chart
  116. */
  117. hide: function(): void {
  118. const $$ = this.internal;
  119. const {state: {inputType}, $el: {tooltip}} = $$;
  120. const data = tooltip?.datum();
  121. if (data) {
  122. const {index} = JSON.parse(data.current)[0];
  123. // make to finalize, possible pending event flow set from '.tooltip.show()' call
  124. (inputType === "mouse" ? ["mouseout"] : ["touchend"]).forEach(eventName => {
  125. $$.dispatchEvent(eventName, index);
  126. });
  127. }
  128. // reset last touch point index
  129. inputType === "touch" && $$.callOverOutForTouch();
  130. $$.hideTooltip(true);
  131. $$.hideGridFocus?.();
  132. $$.unexpandCircles?.();
  133. $$.expandBarTypeShapes?.(false);
  134. }
  135. };
  136. export default {tooltip};