PopoverManager.js 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /*!
  2. * All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. * See https://github.com/Esri/calcite-components/blob/master/LICENSE.md for details.
  4. * v1.0.0-beta.97
  5. */
  6. import { isPrimaryPointerButton } from "../../utils/dom";
  7. import { isActivationKey } from "../../utils/key";
  8. export default class PopoverManager {
  9. constructor() {
  10. // --------------------------------------------------------------------------
  11. //
  12. // Private Properties
  13. //
  14. // --------------------------------------------------------------------------
  15. this.registeredElements = new Map();
  16. this.registeredElementCount = 0;
  17. // --------------------------------------------------------------------------
  18. //
  19. // Private Methods
  20. //
  21. // --------------------------------------------------------------------------
  22. this.queryPopover = (composedPath) => {
  23. const { registeredElements } = this;
  24. const registeredElement = composedPath.find((pathEl) => registeredElements.has(pathEl));
  25. return registeredElements.get(registeredElement);
  26. };
  27. this.togglePopovers = (event) => {
  28. const composedPath = event.composedPath();
  29. const togglePopover = this.queryPopover(composedPath);
  30. if (togglePopover && !togglePopover.triggerDisabled) {
  31. togglePopover.toggle();
  32. }
  33. Array.from(this.registeredElements.values())
  34. .filter((popover) => popover !== togglePopover && popover.autoClose && popover.open && !composedPath.includes(popover))
  35. .forEach((popover) => popover.toggle(false));
  36. };
  37. this.keyHandler = (event) => {
  38. if (event.defaultPrevented || !isActivationKey(event.key)) {
  39. return;
  40. }
  41. this.togglePopovers(event);
  42. };
  43. this.clickHandler = (event) => {
  44. if (isPrimaryPointerButton(event)) {
  45. this.togglePopovers(event);
  46. }
  47. };
  48. }
  49. // --------------------------------------------------------------------------
  50. //
  51. // Public Methods
  52. //
  53. // --------------------------------------------------------------------------
  54. registerElement(referenceEl, popover) {
  55. this.registeredElementCount++;
  56. this.registeredElements.set(referenceEl, popover);
  57. if (this.registeredElementCount === 1) {
  58. this.addListeners();
  59. }
  60. }
  61. unregisterElement(referenceEl) {
  62. if (this.registeredElements.delete(referenceEl)) {
  63. this.registeredElementCount--;
  64. }
  65. if (this.registeredElementCount === 0) {
  66. this.removeListeners();
  67. }
  68. }
  69. addListeners() {
  70. document.addEventListener("pointerdown", this.clickHandler, { capture: true });
  71. document.addEventListener("keydown", this.keyHandler, { capture: true });
  72. }
  73. removeListeners() {
  74. document.removeEventListener("pointerdown", this.clickHandler, { capture: true });
  75. document.removeEventListener("keydown", this.keyHandler, { capture: true });
  76. }
  77. }