AtTimeSeries.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. const { I } = inject();
  2. module.exports = {
  3. _rootSelector: ".htx-timeseries",
  4. _channelSelector: ".htx-timeseries-channel .overlay",
  5. _overviewSelector: ".htx-timeseries-overview .overlay",
  6. _westHandleSelector: ".htx-timeseries-overview .handle--w",
  7. _eastHandleSelector: ".htx-timeseries-overview .handle--e",
  8. _stickSelector: '[text-anchor="start"]',
  9. get _channelStageSelector() {
  10. return `${this._rootSelector} .htx-timeseries-channel .new_brush`;
  11. },
  12. get _channelStickSelector() {
  13. return `${this._rootSelector} .htx-timeseries-channel [text-anchor="start"]`;
  14. },
  15. _stageBBox: { x: 0, y: 0, width: 0, height: 0 },
  16. WEST: "west",
  17. EAST: "east",
  18. async lookForStage() {
  19. I.scrollPageToTop();
  20. const bbox = await I.grabElementBoundingRect(this._channelStageSelector);
  21. this._stageBBox = bbox;
  22. },
  23. /**
  24. * Retrieves timestamp value from a text element of timeseries' stick (cursor).
  25. * **should be used inside async with `await`** operator.
  26. *
  27. * ```js
  28. * let timestamp = await I.grabStickTime();
  29. * ```
  30. * @returns timestamp value
  31. *
  32. * {{ react }}
  33. */
  34. async grabStickTime() {
  35. // xPath cannot find `text` tag so we exchange it with `*`
  36. const rawValue = await I.grabTextFrom(locate(this._channelStickSelector).find("*").at(2));
  37. const numericPart = rawValue.match(/-?\d+(?:\.\d+)?/);
  38. const parsedValue = numericPart ? Number(numericPart[0]) : Number(rawValue);
  39. // Cursor labels are formatted with one decimal place (e.g. "0.8 Hz") even when the
  40. // underlying data is integer-based. Round to the nearest integer so equality checks
  41. // on sequential timestamps keep passing regardless of the display format.
  42. return Number.isFinite(parsedValue) ? Math.round(parsedValue) : parsedValue;
  43. },
  44. /**
  45. * Select range on overview to zoom in
  46. * **should be used inside async with `await`** operator.
  47. * @param {number} from - relative position of start between 0 and 1
  48. * @param {number} to - relative position of finish between 0 and 1
  49. * @returns {Promise<void>}
  50. *
  51. * @example
  52. * await AtTimeSeries.selectOverviewRange(.25, .75);
  53. */
  54. async selectOverviewRange(from, to) {
  55. I.scrollPageToTop();
  56. const overviewBBox = await I.grabElementBoundingRect(this._overviewSelector);
  57. I.moveMouse(overviewBBox.x + overviewBBox.width * from, overviewBBox.y + overviewBBox.height / 2);
  58. I.pressMouseDown();
  59. I.moveMouse(overviewBBox.x + overviewBBox.width * to, overviewBBox.y + overviewBBox.height / 2, 3);
  60. I.pressMouseUp();
  61. },
  62. /**
  63. * Move range on overview to another position
  64. * @param {number} where - position between 0 and 1
  65. * @returns {Promise<void>}
  66. */
  67. async clickOverview(where) {
  68. I.scrollPageToTop();
  69. const overviewBBox = await I.grabElementBoundingRect(this._overviewSelector);
  70. I.clickAt(overviewBBox.x + overviewBBox.width * where, overviewBBox.y + overviewBBox.height / 2);
  71. },
  72. /**
  73. * Move overview handle by mouse drag
  74. * **should be used inside async with `await`** operator.
  75. * @param {number} where - position between 0 and 1
  76. * @param {"west"|"east"} [which="west"] - handler name
  77. * @returns {Promise<void>}
  78. *
  79. * @example
  80. * await AtTimeSeries.moveHandle(.5, AtTimeSeries.WEST);
  81. */
  82. async moveHandle(where, which = this.WEST) {
  83. I.scrollPageToTop();
  84. const handlerBBox = await I.grabElementBoundingRect(this[`_${which}HandleSelector`]);
  85. const overviewBBox = await I.grabElementBoundingRect(this._overviewSelector);
  86. I.moveMouse(handlerBBox.x + handlerBBox.width / 2, handlerBBox.y + handlerBBox.height / 2);
  87. I.pressMouseDown();
  88. I.moveMouse(overviewBBox.x + overviewBBox.width * where, overviewBBox.y + overviewBBox.height / 2, 3);
  89. I.pressMouseUp();
  90. },
  91. /**
  92. * Zoom by mouse wheel over the channel
  93. * **should be used inside async with `await`** operator.
  94. * @param {number} deltaY
  95. * @param {Object} [atPoint] - Point where will be called wheel action
  96. * @param {number} [atPoint.x=0.5] - relative X coordinate
  97. * @param {number} [atPoint.y=0.5] - relative Y coordinate
  98. * @returns {Promise<void>}
  99. *
  100. * @example
  101. * // zoom in
  102. * await AtTimeSeries.zoomByMouse(-100, { x: .01 });
  103. * // zoom out
  104. * await AtTimeSeries.zoomByMouse(100);
  105. */
  106. async zoomByMouse(deltaY, atPoint) {
  107. const { x = 0.5, y = 0.5 } = atPoint;
  108. I.scrollPageToTop();
  109. const channelBBox = await I.grabElementBoundingRect(this._channelSelector);
  110. I.moveMouse(channelBBox.x + channelBBox.width * x, channelBBox.y + channelBBox.height * y);
  111. I.pressKeyDown("CommandOrControl");
  112. I.mouseWheel({ deltaY });
  113. I.pressKeyUp("CommandOrControl");
  114. },
  115. /**
  116. * Move mouse over the channel
  117. * **should be used inside async with `await`** operator.
  118. * @param {Object} [atPoint] - Point where will be called wheel action
  119. * @param {number} [atPoint.x=0.5] - relative X coordinate
  120. * @param {number} [atPoint.y=0.5] - relative Y coordinate
  121. * @returns {Promise<void>}
  122. *
  123. * @example
  124. * await AtTimeSeries.moveMouseOverChannel({ x: .01 });
  125. */
  126. async moveMouseOverChannel(atPoint) {
  127. const { x = 0.5, y = 0.5 } = atPoint;
  128. I.scrollPageToTop();
  129. const channelBBox = await I.grabElementBoundingRect(this._channelSelector);
  130. I.moveMouse(channelBBox.x + channelBBox.width * x, channelBBox.y + channelBBox.height * y);
  131. },
  132. /**
  133. * Mousedown - mousemove - mouseup drawing a region on the first Channel. Works in conjunction with lookForStage.
  134. * @example
  135. * await AtTimeSeries.lookForStage();
  136. * AtTimeseries.drawByDrag(50, 200);
  137. * @param x
  138. * @param shiftX
  139. */
  140. drawByDrag(x, shiftX) {
  141. I.scrollPageToTop();
  142. I.moveMouse(this._stageBBox.x + x, this._stageBBox.y + this._stageBBox.height / 2);
  143. I.pressMouseDown();
  144. I.moveMouse(this._stageBBox.x + x + shiftX, this._stageBBox.y + this._stageBBox.height / 2, 3);
  145. I.pressMouseUp();
  146. },
  147. };