Chart/api/selection.ts

  1. /**
  2. * Copyright (c) 2017 ~ present NAVER Corp.
  3. * billboard.js project is licensed under the MIT license
  4. */
  5. import {select as d3Select} from "d3-selection";
  6. import type {DataItem} from "../../../types/types";
  7. import {$AREA, $LINE, $SELECT, $SHAPE} from "../../config/classes";
  8. import {isDefined} from "../../module/util";
  9. /**
  10. * Toggler function to select or unselect
  11. * @param {boolean} isSelection Weather select or unselect
  12. * @param {Array} ids Target ids
  13. * @param {Array} indices Indices number
  14. * @param {boolean} resetOther Weather reset other selected points (only for selection)
  15. * @private
  16. */
  17. function setSelection(
  18. isSelection = false,
  19. ids?: string | string[],
  20. indices?: number[],
  21. resetOther?: boolean
  22. ): void {
  23. const $$ = this;
  24. const {config, $el: {main}} = $$;
  25. const selectionGrouped = config.data_selection_grouped;
  26. const isSelectable = config.data_selection_isselectable.bind($$.api);
  27. if (!config.data_selection_enabled) {
  28. return;
  29. }
  30. main.selectAll(`.${$SHAPE.shapes}`)
  31. .selectAll(`.${$SHAPE.shape}`)
  32. .each(function(d) {
  33. const shape = d3Select(this);
  34. const {id, index} = d.data ? d.data : d;
  35. const toggle = $$.getToggle(this, d).bind($$);
  36. const isTargetId = selectionGrouped || !ids || ids.indexOf(id) >= 0;
  37. const isTargetIndex = !indices || indices.indexOf(index) >= 0;
  38. const isSelected = shape.classed($SELECT.SELECTED);
  39. // line/area selection not supported yet
  40. if (shape.classed($LINE.line) || shape.classed($AREA.area)) {
  41. return;
  42. }
  43. if (isSelection) {
  44. if (isTargetId && isTargetIndex && isSelectable(d) && !isSelected) {
  45. toggle(true, shape.classed($SELECT.SELECTED, true), d, index);
  46. } else if (isDefined(resetOther) && resetOther && isSelected) {
  47. toggle(false, shape.classed($SELECT.SELECTED, false), d, index);
  48. }
  49. } else {
  50. if (isTargetId && isTargetIndex && isSelectable(d) && isSelected) {
  51. toggle(false, shape.classed($SELECT.SELECTED, false), d, index);
  52. }
  53. }
  54. });
  55. }
  56. export default {
  57. /**
  58. * Get selected data points.<br><br>
  59. * By this API, you can get selected data points information. To use this API, data.selection.enabled needs to be set true.
  60. * @function selected
  61. * @instance
  62. * @memberof Chart
  63. * @param {string} [targetId] You can filter the result by giving target id that you want to get. If not given, all of data points will be returned.
  64. * @returns {Array} dataPoint Array of the data points.<br>ex.) `[{x: 1, value: 200, id: "data1", index: 1, name: "data1"}, ...]`
  65. * @example
  66. * // all selected data points will be returned.
  67. * chart.selected();
  68. * // --> ex.) [{x: 1, value: 200, id: "data1", index: 1, name: "data1"}, ... ]
  69. *
  70. * // all selected data points of data1 will be returned.
  71. * chart.selected("data1");
  72. */
  73. selected(targetId?: string): DataItem[] {
  74. const $$ = this.internal;
  75. const dataPoint: DataItem[] = [];
  76. $$.$el.main.selectAll(`.${$SHAPE.shapes + $$.getTargetSelectorSuffix(targetId)}`)
  77. .selectAll(`.${$SHAPE.shape}`)
  78. .filter(function() {
  79. return d3Select(this).classed($SELECT.SELECTED);
  80. })
  81. .each(d => dataPoint.push(d));
  82. return dataPoint;
  83. },
  84. /**
  85. * Set data points to be selected. ([`data.selection.enabled`](Options.html#.data%25E2%2580%25A4selection%25E2%2580%25A4enabled) option should be set true to use this method)
  86. * @function select
  87. * @instance
  88. * @memberof Chart
  89. * @param {string|Array} [ids] id value to get selected.
  90. * @param {Array} [indices] The index array of data points. If falsy value given, will select all data points.
  91. * @param {boolean} [resetOther] Unselect already selected.
  92. * @example
  93. * // select all data points
  94. * chart.select();
  95. *
  96. * // select all from 'data2'
  97. * chart.select("data2");
  98. *
  99. * // select all from 'data1' and 'data2'
  100. * chart.select(["data1", "data2"]);
  101. *
  102. * // select from 'data1', indices 2 and unselect others selected
  103. * chart.select("data1", [2], true);
  104. *
  105. * // select from 'data1', indices 0, 3 and 5
  106. * chart.select("data1", [0, 3, 5]);
  107. */
  108. select(ids?: string[] | string, indices?: number[], resetOther?: boolean): void {
  109. const $$ = this.internal;
  110. setSelection.bind($$)(true, ids, indices, resetOther);
  111. },
  112. /**
  113. * Set data points to be un-selected.
  114. * @function unselect
  115. * @instance
  116. * @memberof Chart
  117. * @param {string|Array} [ids] id value to be unselected.
  118. * @param {Array} [indices] The index array of data points. If falsy value given, will select all data points.
  119. * @example
  120. * // unselect all data points
  121. * chart.unselect();
  122. *
  123. * // unselect all from 'data1'
  124. * chart.unselect("data1");
  125. *
  126. * // unselect from 'data1', indices 2
  127. * chart.unselect("data1", [2]);
  128. */
  129. unselect(ids?: string | string[], indices?: number[]): void {
  130. const $$ = this.internal;
  131. setSelection.bind($$)(false, ids, indices);
  132. }
  133. };