@zoho_apptics/apptics-js-sdk 2.0.0-beta → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/CHANGELOG.md +111 -5
  2. package/README.md +399 -300
  3. package/dist/apptics.esm.min.js +2 -2
  4. package/dist/apptics.esm.min.js.map +1 -1
  5. package/dist/apptics.min.js +2 -2
  6. package/dist/apptics.min.js.map +1 -1
  7. package/dist/chunks/lifecycle-VYr43KcB.min.js +3 -0
  8. package/dist/chunks/lifecycle-VYr43KcB.min.js.map +1 -0
  9. package/dist/cjs/auto-init.d.ts +3 -3
  10. package/dist/cjs/auto-init.js +1 -1
  11. package/dist/cjs/core/attempts.js +1 -1
  12. package/dist/cjs/core/batch.js +2 -1
  13. package/dist/cjs/core/callsite.d.ts +6 -0
  14. package/dist/cjs/core/callsite.js +25 -3
  15. package/dist/cjs/core/consent.d.ts +5 -1
  16. package/dist/cjs/core/consent.js +8 -6
  17. package/dist/cjs/core/constants.d.ts +35 -10
  18. package/dist/cjs/core/constants.js +31 -15
  19. package/dist/cjs/core/db.d.ts +12 -4
  20. package/dist/cjs/core/db.js +167 -34
  21. package/dist/cjs/core/debug.js +1 -1
  22. package/dist/cjs/core/env.js +1 -1
  23. package/dist/cjs/core/framework-id.d.ts +1 -1
  24. package/dist/cjs/core/framework-id.js +3 -3
  25. package/dist/cjs/core/guard.d.ts +9 -0
  26. package/dist/cjs/core/guard.js +27 -13
  27. package/dist/cjs/core/hooks.d.ts +2 -4
  28. package/dist/cjs/core/hooks.js +2 -3
  29. package/dist/cjs/core/locks.d.ts +9 -0
  30. package/dist/cjs/core/locks.js +22 -0
  31. package/dist/cjs/core/logger.d.ts +3 -4
  32. package/dist/cjs/core/logger.js +4 -40
  33. package/dist/cjs/core/state.d.ts +3 -2
  34. package/dist/cjs/core/state.js +2 -2
  35. package/dist/cjs/core/storage.d.ts +20 -5
  36. package/dist/cjs/core/storage.js +115 -17
  37. package/dist/cjs/core/stylesheet.d.ts +8 -0
  38. package/dist/cjs/core/stylesheet.js +29 -0
  39. package/dist/cjs/core/transport.d.ts +2 -0
  40. package/dist/cjs/core/transport.js +19 -4
  41. package/dist/cjs/core/utils.js +1 -1
  42. package/dist/cjs/core/validate.js +2 -2
  43. package/dist/cjs/device/appversion.d.ts +1 -6
  44. package/dist/cjs/device/appversion.js +13 -1
  45. package/dist/cjs/device/index.d.ts +11 -0
  46. package/dist/cjs/device/index.js +120 -20
  47. package/dist/cjs/engagement/api-rules.d.ts +32 -67
  48. package/dist/cjs/engagement/api-rules.js +144 -157
  49. package/dist/cjs/engagement/auto-api.js +2 -2
  50. package/dist/cjs/engagement/auto-screen.d.ts +2 -0
  51. package/dist/cjs/engagement/auto-screen.js +67 -3
  52. package/dist/cjs/engagement/defined-events.js +1 -1
  53. package/dist/cjs/engagement/send.js +6 -1
  54. package/dist/cjs/engagement/session.d.ts +12 -3
  55. package/dist/cjs/engagement/session.js +161 -25
  56. package/dist/cjs/engagement/track.js +45 -20
  57. package/dist/cjs/errors/send.js +1 -1
  58. package/dist/cjs/errors/track.d.ts +1 -1
  59. package/dist/cjs/errors/track.js +46 -6
  60. package/dist/cjs/feedback/controls.d.ts +6 -0
  61. package/dist/cjs/feedback/controls.js +31 -1
  62. package/dist/cjs/feedback/index.d.ts +8 -7
  63. package/dist/cjs/feedback/index.js +32 -13
  64. package/dist/cjs/feedback/logs.d.ts +10 -5
  65. package/dist/cjs/feedback/logs.js +52 -13
  66. package/dist/cjs/feedback/quartz.d.ts +18 -0
  67. package/dist/cjs/feedback/quartz.js +105 -0
  68. package/dist/cjs/feedback/send.d.ts +3 -0
  69. package/dist/cjs/feedback/send.js +28 -3
  70. package/dist/cjs/feedback/styles.d.ts +10 -0
  71. package/dist/cjs/feedback/styles.js +8 -0
  72. package/dist/cjs/feedback/template.d.ts +1 -1
  73. package/dist/cjs/feedback/template.js +12 -12
  74. package/dist/cjs/feedback/ui.d.ts +14 -6
  75. package/dist/cjs/feedback/ui.js +126 -48
  76. package/dist/cjs/heatmap/send.js +1 -1
  77. package/dist/cjs/heatmap/track.d.ts +1 -1
  78. package/dist/cjs/heatmap/track.js +87 -16
  79. package/dist/cjs/index.d.ts +17 -63
  80. package/dist/cjs/index.js +104 -92
  81. package/dist/cjs/lifecycle.d.ts +8 -1
  82. package/dist/cjs/lifecycle.js +258 -62
  83. package/dist/cjs/remoteconfig/country.d.ts +4 -0
  84. package/dist/cjs/remoteconfig/country.js +73 -0
  85. package/dist/cjs/remoteconfig/custom.d.ts +7 -7
  86. package/dist/cjs/remoteconfig/custom.js +31 -51
  87. package/dist/cjs/remoteconfig/evaluate.d.ts +3 -3
  88. package/dist/cjs/remoteconfig/evaluate.js +56 -43
  89. package/dist/cjs/remoteconfig/fetch.d.ts +3 -3
  90. package/dist/cjs/remoteconfig/fetch.js +9 -23
  91. package/dist/cjs/remoteconfig/index.d.ts +10 -8
  92. package/dist/cjs/remoteconfig/index.js +65 -39
  93. package/dist/cjs/remoteconfig/store.js +1 -1
  94. package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
  95. package/dist/cjs/remoteconfig/tz-countries.js +13 -0
  96. package/dist/cjs/remotelog/gate.d.ts +2 -11
  97. package/dist/cjs/remotelog/gate.js +9 -35
  98. package/dist/cjs/remotelog/index.d.ts +4 -21
  99. package/dist/cjs/remotelog/logger.d.ts +11 -17
  100. package/dist/cjs/remotelog/logger.js +30 -58
  101. package/dist/cjs/remotelog/send.js +10 -10
  102. package/dist/cjs/remotelogger/index.d.ts +12 -0
  103. package/dist/cjs/remotelogger/index.js +18 -0
  104. package/dist/cjs/scheduler.js +2 -2
  105. package/dist/cjs/types.d.ts +155 -82
  106. package/dist/cjs/user/index.js +11 -6
  107. package/dist/esm/auto-init.d.ts +3 -3
  108. package/dist/esm/auto-init.js +1 -1
  109. package/dist/esm/core/attempts.js +1 -1
  110. package/dist/esm/core/batch.js +2 -1
  111. package/dist/esm/core/callsite.d.ts +6 -0
  112. package/dist/esm/core/callsite.js +25 -4
  113. package/dist/esm/core/consent.d.ts +5 -1
  114. package/dist/esm/core/consent.js +9 -7
  115. package/dist/esm/core/constants.d.ts +35 -10
  116. package/dist/esm/core/constants.js +30 -15
  117. package/dist/esm/core/db.d.ts +12 -4
  118. package/dist/esm/core/db.js +164 -35
  119. package/dist/esm/core/debug.js +1 -1
  120. package/dist/esm/core/env.js +1 -1
  121. package/dist/esm/core/framework-id.d.ts +1 -1
  122. package/dist/esm/core/framework-id.js +3 -3
  123. package/dist/esm/core/guard.d.ts +9 -0
  124. package/dist/esm/core/guard.js +27 -14
  125. package/dist/esm/core/hooks.d.ts +2 -4
  126. package/dist/esm/core/hooks.js +2 -3
  127. package/dist/esm/core/locks.d.ts +9 -0
  128. package/dist/esm/core/locks.js +20 -0
  129. package/dist/esm/core/logger.d.ts +3 -4
  130. package/dist/esm/core/logger.js +4 -40
  131. package/dist/esm/core/state.d.ts +3 -2
  132. package/dist/esm/core/state.js +2 -2
  133. package/dist/esm/core/storage.d.ts +20 -5
  134. package/dist/esm/core/storage.js +113 -18
  135. package/dist/esm/core/stylesheet.d.ts +8 -0
  136. package/dist/esm/core/stylesheet.js +27 -0
  137. package/dist/esm/core/transport.d.ts +2 -0
  138. package/dist/esm/core/transport.js +19 -5
  139. package/dist/esm/core/utils.js +1 -1
  140. package/dist/esm/core/validate.js +2 -2
  141. package/dist/esm/device/appversion.d.ts +1 -6
  142. package/dist/esm/device/appversion.js +13 -2
  143. package/dist/esm/device/index.d.ts +11 -0
  144. package/dist/esm/device/index.js +123 -24
  145. package/dist/esm/engagement/api-rules.d.ts +32 -67
  146. package/dist/esm/engagement/api-rules.js +143 -155
  147. package/dist/esm/engagement/auto-api.js +3 -3
  148. package/dist/esm/engagement/auto-screen.d.ts +2 -0
  149. package/dist/esm/engagement/auto-screen.js +67 -4
  150. package/dist/esm/engagement/defined-events.js +1 -1
  151. package/dist/esm/engagement/send.js +6 -1
  152. package/dist/esm/engagement/session.d.ts +12 -3
  153. package/dist/esm/engagement/session.js +162 -29
  154. package/dist/esm/engagement/track.js +52 -27
  155. package/dist/esm/errors/send.js +1 -1
  156. package/dist/esm/errors/track.d.ts +1 -1
  157. package/dist/esm/errors/track.js +46 -6
  158. package/dist/esm/feedback/controls.d.ts +6 -0
  159. package/dist/esm/feedback/controls.js +31 -2
  160. package/dist/esm/feedback/index.d.ts +8 -7
  161. package/dist/esm/feedback/index.js +34 -13
  162. package/dist/esm/feedback/logs.d.ts +10 -5
  163. package/dist/esm/feedback/logs.js +54 -15
  164. package/dist/esm/feedback/quartz.d.ts +18 -0
  165. package/dist/esm/feedback/quartz.js +99 -0
  166. package/dist/esm/feedback/send.d.ts +3 -0
  167. package/dist/esm/feedback/send.js +28 -5
  168. package/dist/esm/feedback/styles.d.ts +10 -0
  169. package/dist/esm/feedback/styles.js +4 -0
  170. package/dist/esm/feedback/template.d.ts +1 -1
  171. package/dist/esm/feedback/template.js +12 -12
  172. package/dist/esm/feedback/ui.d.ts +14 -6
  173. package/dist/esm/feedback/ui.js +126 -49
  174. package/dist/esm/heatmap/send.js +1 -1
  175. package/dist/esm/heatmap/track.d.ts +1 -1
  176. package/dist/esm/heatmap/track.js +87 -16
  177. package/dist/esm/index.d.ts +17 -63
  178. package/dist/esm/index.js +108 -80
  179. package/dist/esm/lifecycle.d.ts +8 -1
  180. package/dist/esm/lifecycle.js +266 -71
  181. package/dist/esm/remoteconfig/country.d.ts +4 -0
  182. package/dist/esm/remoteconfig/country.js +70 -0
  183. package/dist/esm/remoteconfig/custom.d.ts +7 -7
  184. package/dist/esm/remoteconfig/custom.js +32 -52
  185. package/dist/esm/remoteconfig/evaluate.d.ts +3 -3
  186. package/dist/esm/remoteconfig/evaluate.js +57 -44
  187. package/dist/esm/remoteconfig/fetch.d.ts +3 -3
  188. package/dist/esm/remoteconfig/fetch.js +9 -23
  189. package/dist/esm/remoteconfig/index.d.ts +10 -8
  190. package/dist/esm/remoteconfig/index.js +66 -40
  191. package/dist/esm/remoteconfig/store.js +1 -1
  192. package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
  193. package/dist/esm/remoteconfig/tz-countries.js +11 -0
  194. package/dist/esm/remotelog/gate.d.ts +2 -11
  195. package/dist/esm/remotelog/gate.js +10 -32
  196. package/dist/esm/remotelog/index.d.ts +4 -21
  197. package/dist/esm/remotelog/logger.d.ts +11 -17
  198. package/dist/esm/remotelog/logger.js +32 -60
  199. package/dist/esm/remotelog/send.js +12 -12
  200. package/dist/esm/remotelogger/index.d.ts +12 -0
  201. package/dist/esm/remotelogger/index.js +13 -0
  202. package/dist/esm/scheduler.js +2 -2
  203. package/dist/esm/types.d.ts +155 -82
  204. package/dist/esm/user/index.js +12 -6
  205. package/dist/feedback.esm.min.js +2 -2
  206. package/dist/feedback.esm.min.js.map +1 -1
  207. package/package.json +14 -16
  208. package/dist/chunks/batch-BU_mTpm1.min.js +0 -3
  209. package/dist/chunks/batch-BU_mTpm1.min.js.map +0 -1
  210. package/dist/chunks/logs-Bea5zUW_.min.js +0 -3
  211. package/dist/chunks/logs-Bea5zUW_.min.js.map +0 -1
  212. package/dist/cjs/heatmap/index.d.ts +0 -16
  213. package/dist/cjs/heatmap/index.js +0 -22
  214. package/dist/cjs/remotelog/index.js +0 -55
  215. package/dist/esm/heatmap/index.d.ts +0 -16
  216. package/dist/esm/heatmap/index.js +0 -17
  217. package/dist/esm/remotelog/index.js +0 -51
  218. package/dist/heatmap.esm.min.js +0 -3
  219. package/dist/heatmap.esm.min.js.map +0 -1
  220. package/dist/style.css +0 -1
@@ -1,25 +1,25 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  // Feedback modal markup (moved from js/apptics.js).
5
- const feedbackUIHtml = `<div id="zasdkFeedbackconatiner" class="zasdk-modal-content">
5
+ const feedbackUIHtml = `<div id="zasdkFeedbackconatiner" class="zasdk-modal-content" role="dialog" aria-modal="true" aria-labelledby="zasdkFeedbackTitle">
6
6
  <div class="zasdk-header">
7
- <h2 class="zasdk-title">Share feedback</h2>
8
- <span id="appticsfeedbackclose" class="zasdk-close"><svg viewBox="0 0 24 24" style=" width: 20px; "><path d="M19.92,19.08c.23.23.23.61,0,.85-.12.12-.27.18-.42.18s-.31-.06-.42-.18l-7.08-7.08-7.08,7.08c-.12.12-.27.18-.42.18s-.31-.06-.42-.18c-.23-.23-.23-.61,0-.85l7.08-7.08-7.08-7.08c-.23-.23-.23-.61,0-.85s.61-.23.85,0l7.08,7.08,7.08-7.08c.23-.23.61-.23.85,0s.23.61,0,.85l-7.08,7.08,7.08,7.08Z"/></svg></span>
7
+ <h2 id="zasdkFeedbackTitle" class="zasdk-title">Share feedback</h2>
8
+ <span id="appticsfeedbackclose" class="zasdk-close" role="button" tabindex="0" aria-label="Close"><svg viewBox="0 0 24 24" style=" width: 20px; "><path d="M19.92,19.08c.23.23.23.61,0,.85-.12.12-.27.18-.42.18s-.31-.06-.42-.18l-7.08-7.08-7.08,7.08c-.12.12-.27.18-.42.18s-.31-.06-.42-.18c-.23-.23-.23-.61,0-.85l7.08-7.08-7.08-7.08c-.23-.23-.23-.61,0-.85s.61-.23.85,0l7.08,7.08,7.08-7.08c.23-.23.61-.23.85,0s.23.61,0,.85l-7.08,7.08,7.08,7.08Z"/></svg></span>
9
9
  </div>
10
10
  <div class="zasdk-feedback-types" data-type="">
11
- <div class="zasdk-feedback-type zasdk-selected" data-type="bug">
12
- <div class="zasdk-iconcnt zasdkfeedback__icon-report">
13
- <i class="zasdkfeedback__icon"><svg viewBox="0 0 24 24"><path d="M15.6,6.58c-.13-.37-.3-.7-.5-.97l1.23-1.18c.24-.23.25-.61.02-.85-.23-.24-.61-.25-.85-.02l-1.26,1.21c-.66-.45-1.37-.62-1.79-.68-.25-.04-.51-.04-.76-.02-.83.08-1.45.35-1.93.7l-1.22-1.2c-.24-.23-.62-.23-.85,0-.23.24-.23.62,0,.85l1.21,1.19c-.24.34-.41.68-.51.96-2.02,1.37-3.27,3.82-3.27,6.44,0,4.18,3.08,7.58,6.87,7.58s6.87-3.4,6.87-7.58c0-2.62-1.25-5.06-3.26-6.44ZM11.82,5.27c.15-.02.31-.01.47.01.69.1,1.86.48,2.26,1.9-.17.17-.51.44-1.14.65-1.08.36-2.31.28-3.36-.23-.24-.11-.44-.23-.6-.36,0-.01,0-.03.01-.04.18-.65.73-1.77,2.36-1.93ZM12,19.4c-3.12,0-5.67-2.86-5.67-6.38,0-1.98.82-3.82,2.19-5.02.26.25.59.48,1.01.68.78.38,1.65.57,2.5.57.6,0,1.19-.09,1.76-.28.88-.29,1.39-.7,1.67-1,1.38,1.2,2.21,3.06,2.21,5.05,0,3.52-2.54,6.38-5.67,6.38ZM9.12,9.86c-.92,0-1.67.75-1.67,1.67s.75,1.67,1.67,1.67,1.67-.75,1.67-1.67-.75-1.67-1.67-1.67ZM9.12,11.99c-.26,0-.47-.21-.47-.47s.21-.47.47-.47.47.21.47.47-.21.47-.47.47ZM14.88,9.86c-.92,0-1.67.75-1.67,1.67s.75,1.67,1.67,1.67,1.67-.75,1.67-1.67-.75-1.67-1.67-1.67ZM14.88,11.99c-.26,0-.47-.21-.47-.47s.21-.47.47-.47.47.21.47.47-.21.47-.47.47ZM12,14.49c-.92,0-1.67.75-1.67,1.67s.75,1.67,1.67,1.67,1.67-.75,1.67-1.67-.75-1.67-1.67-1.67ZM12,16.62c-.26,0-.47-.21-.47-.47s.21-.47.47-.47.47.21.47.47-.21.47-.47.47Z"/></svg></i>
14
- </div>
15
- <div>Bug</div>
16
- </div>
17
- <div class="zasdk-feedback-type" data-type="feedback">
11
+ <div class="zasdk-feedback-type zasdk-selected" data-type="feedback">
18
12
  <div class="zasdk-iconcnt zasdkfeedback__icon-reqest">
19
13
  <i class="zasdkfeedback__icon"><svg viewBox="0 0 24 24"><path d="M6.69,9.25h10.81c.41,0,.75-.34.75-.75s-.34-.75-.75-.75H6.69c-.41,0-.75.34-.75.75s.34.75.75.75Z"/><path d="M6.69,13.07h8.11c.41,0,.75-.34.75-.75s-.34-.75-.75-.75H6.69c-.41,0-.75.34-.75.75s.34.75.75.75Z"/><path d="M20.72,5.17c0-.68-.55-1.23-1.23-1.23H4.48c-.68,0-1.23.55-1.23,1.23v11.84c0,.68.55,1.23,1.23,1.23h13.49l1.25,1.51c.17.2.41.31.67.31.1,0,.2-.02.3-.05.34-.13.57-.46.56-.83l-.03-14.01ZM19.22,17.39l-.17-.2c-.24-.29-.58-.45-.95-.45H4.75V5.44h14.47v11.95Z"/></svg></i>
20
14
  </div>
21
15
  <div>Feedback</div>
22
16
  </div>
17
+ <div class="zasdk-feedback-type" data-type="bug">
18
+ <div class="zasdk-iconcnt zasdkfeedback__icon-report">
19
+ <i class="zasdkfeedback__icon"><svg viewBox="0 0 24 24"><path d="M15.6,6.58c-.13-.37-.3-.7-.5-.97l1.23-1.18c.24-.23.25-.61.02-.85-.23-.24-.61-.25-.85-.02l-1.26,1.21c-.66-.45-1.37-.62-1.79-.68-.25-.04-.51-.04-.76-.02-.83.08-1.45.35-1.93.7l-1.22-1.2c-.24-.23-.62-.23-.85,0-.23.24-.23.62,0,.85l1.21,1.19c-.24.34-.41.68-.51.96-2.02,1.37-3.27,3.82-3.27,6.44,0,4.18,3.08,7.58,6.87,7.58s6.87-3.4,6.87-7.58c0-2.62-1.25-5.06-3.26-6.44ZM11.82,5.27c.15-.02.31-.01.47.01.69.1,1.86.48,2.26,1.9-.17.17-.51.44-1.14.65-1.08.36-2.31.28-3.36-.23-.24-.11-.44-.23-.6-.36,0-.01,0-.03.01-.04.18-.65.73-1.77,2.36-1.93ZM12,19.4c-3.12,0-5.67-2.86-5.67-6.38,0-1.98.82-3.82,2.19-5.02.26.25.59.48,1.01.68.78.38,1.65.57,2.5.57.6,0,1.19-.09,1.76-.28.88-.29,1.39-.7,1.67-1,1.38,1.2,2.21,3.06,2.21,5.05,0,3.52-2.54,6.38-5.67,6.38ZM9.12,9.86c-.92,0-1.67.75-1.67,1.67s.75,1.67,1.67,1.67,1.67-.75,1.67-1.67-.75-1.67-1.67-1.67ZM9.12,11.99c-.26,0-.47-.21-.47-.47s.21-.47.47-.47.47.21.47.47-.21.47-.47.47ZM14.88,9.86c-.92,0-1.67.75-1.67,1.67s.75,1.67,1.67,1.67,1.67-.75,1.67-1.67-.75-1.67-1.67-1.67ZM14.88,11.99c-.26,0-.47-.21-.47-.47s.21-.47.47-.47.47.21.47.47-.21.47-.47.47ZM12,14.49c-.92,0-1.67.75-1.67,1.67s.75,1.67,1.67,1.67,1.67-.75,1.67-1.67-.75-1.67-1.67-1.67ZM12,16.62c-.26,0-.47-.21-.47-.47s.21-.47.47-.47.47.21.47.47-.21.47-.47.47Z"/></svg></i>
20
+ </div>
21
+ <div>Bug</div>
22
+ </div>
23
23
  <div class="zasdk-feedback-type" data-type="help">
24
24
  <div class="zasdk-iconcnt zasdkfeedback__icon-help">
25
25
  <i class="zasdkfeedback__icon"><svg viewBox="0 0 24 24"><path d="M12.45,16.47c-.33,0-.6-.27-.6-.6v-2.7c0-.43.25-.82.64-.99.95-.42,3.15-1.62,3.15-3.51,0-1.6-1.01-3.03-2.51-3.55-.95-.33-1.97-.28-2.87.16-.91.43-1.59,1.2-1.92,2.14-.11.31-.45.48-.77.37-.31-.11-.48-.45-.37-.77.44-1.25,1.34-2.25,2.54-2.83,1.2-.57,2.54-.65,3.79-.21,1.99.7,3.32,2.58,3.31,4.69,0,2.46-2.34,3.91-3.79,4.57v2.63c0,.33-.27.6-.6.6ZM13.21,19.1c0-.66-.54-1.2-1.2-1.2h-.03c-.66,0-1.19.54-1.19,1.2s.55,1.2,1.21,1.2,1.2-.54,1.2-1.2Z"/></svg></i>
@@ -44,7 +44,7 @@ const feedbackUIHtml = `<div id="zasdkFeedbackconatiner" class="zasdk-modal-cont
44
44
  <ul id="zasdkEmailList" class="zasdk-select-list"></ul>
45
45
  </div>
46
46
  </div>
47
- <label class="zasdkdesclbl" for="zasdkDescription">Add details here<span class="zasdkmadfeld">*</span> <span class="zaleftcharspan"><span class="zaleftcharcnt">5000</span><span class="zaleftchartxt">character left</span></span></label>
47
+ <label class="zasdkdesclbl" for="zasdkDescription">Add details here<span class="zasdkmadfeld">*</span> <span class="zaleftcharspan"><span class="zaleftcharcnt">5000</span><span class="zaleftchartxt">characters left</span></span></label>
48
48
  <textarea id="zasdkDescription" name="description" placeholder="Please provide more details for us to help you better." reqname="name" maxlength="5000"></textarea>
49
49
  <div id="zasdkreccheckcnt" class="zasdkqz-container">
50
50
  <div class="zasdkqz-checkbox-wrapper">
@@ -1,8 +1,14 @@
1
- import type { FeedbackType } from '../types.js';
2
- export declare function sendFeedback(feedbackType?: FeedbackType, feedbackMessage?: string, attachments?: FileList | File[] | null, logsFiles?: FileList | File[] | null, includeDyninfo?: boolean, includeLog?: boolean): Promise<void>;
3
- export declare function feedbackOpen(type?: FeedbackType, message?: string, includeLog?: boolean, includeDyninfo?: boolean, attachments?: FileList | File[] | null, logFiles?: FileList | File[] | null, isAnonymous?: boolean): void;
4
- export declare function feedbackClose(): void;
5
- /** What feedbackOpen() may pre-set on the form. */
1
+ import type { FeedbackOpenOptions as PublicFeedbackOpenOptions, FeedbackType, SendFeedbackOptions } from '../types.js';
2
+ export declare function sendFeedback(options?: SendFeedbackOptions): Promise<void>;
3
+ export declare function feedbackFormOpen(options?: PublicFeedbackOpenOptions): void;
4
+ /**
5
+ * Sets the form's theme, for a page with its own light and dark modes: 'auto' follows the
6
+ * operating system, which is not what such a page shows. Restyles a form or recording timer that
7
+ * is open now, and every one opened after; Apptics.init()'s feedback_theme only sets the first.
8
+ */
9
+ export declare function setFeedbackTheme(theme: 'light' | 'dark' | 'auto'): void;
10
+ export declare function feedbackFormClose(): void;
11
+ /** What the form is built with, from the options feedbackFormOpen() was given. */
6
12
  export interface FeedbackOpenOptions {
7
13
  type?: FeedbackType;
8
14
  message?: string;
@@ -29,7 +35,7 @@ export interface FeedbackUI {
29
35
  timerInterval: ReturnType<typeof setInterval> | null;
30
36
  uploadTotalSize: number;
31
37
  MaxFileSize: number;
32
- /** What the last feedbackOpen() asked for; the form reads it as it is built. */
38
+ /** What the last feedbackFormOpen() asked for; the form reads it as it is built. */
33
39
  _opts: FeedbackOpenOptions;
34
40
  init(opts?: FeedbackOpenOptions): void;
35
41
  updateLeftCount(): void;
@@ -37,6 +43,8 @@ export interface FeedbackUI {
37
43
  handleErrorQuartzEvent(event: Event): void;
38
44
  bindQuartzEvent(event: Event): void;
39
45
  close(): void;
46
+ /** Escape closes the form; listened for from open to close. */
47
+ onEscape(e: KeyboardEvent): void;
40
48
  toggleWindowAnimation(): void;
41
49
  fileAttachment(): void;
42
50
  elementCreator<K extends keyof HTMLElementTagNameMap>(elType: K): HTMLElementTagNameMap[K];
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var constants = require('../core/constants.js');
@@ -9,6 +9,9 @@ var consent = require('../core/consent.js');
9
9
  var template = require('./template.js');
10
10
  var send = require('./send.js');
11
11
  var controls = require('./controls.js');
12
+ var stylesheet = require('../core/stylesheet.js');
13
+ var quartz$1 = require('./quartz.js');
14
+ var styles = require('./styles.js');
12
15
 
13
16
  // Quartz is an optional page-level SDK. Without it every call is a no-op (fix #5).
14
17
  const QUARTZ_NOOP = {
@@ -48,25 +51,45 @@ function submitFeedback(dataobj) {
48
51
  return result;
49
52
  });
50
53
  }
51
- function sendFeedback(feedbackType, feedbackMessage, attachments, logsFiles, includeDyninfo, includeLog) {
54
+ /** Whether a value is an options object: a plain object, not a type number or a message string. */
55
+ function isOptions(value) {
56
+ return value !== null && typeof value === 'object' && !Array.isArray(value); // no i18n
57
+ }
58
+ /** Said once: the old one-argument-after-another form of feedbackFormOpen. */
59
+ var saidOpenForm = false;
60
+ function sendFeedback(options) {
61
+ if (options !== undefined && !isOptions(options)) {
62
+ // the old form, sendFeedback(type, message, ...): sending it as it stands would send an
63
+ // empty report, so it is refused, and says what to pass instead
64
+ return Promise.reject(new Error('AppticsFeedback.sendFeedback: takes one options object, as sendFeedback({ type, message, attachments, logFiles, includeDiagnostics, includeLog, isAnonymous })')); // no i18n
65
+ }
66
+ const o = options || {};
52
67
  const dataobj = {
53
- type: !utils.isEmpty(feedbackType) ? feedbackType : 1,
54
- message: feedbackMessage || '', // no i18n
55
- attachment: attachments || null,
56
- logsFiles: logsFiles || null,
68
+ type: !utils.isEmpty(o.type) ? o.type : 1,
69
+ message: o.message || '', // no i18n
70
+ attachment: o.attachments || null,
71
+ logsFiles: o.logFiles || null,
57
72
  // both flags stay as given: unset lets send.ts decide from what is actually stored
58
- includeDyninfo: includeDyninfo,
59
- includeLog: includeLog,
73
+ includeDyninfo: o.includeDiagnostics,
74
+ includeLog: o.includeLog,
60
75
  quartzid: '' // no i18n
61
76
  };
77
+ // from the active user, or from nobody with isAnonymous; the form's own choice is put back after
78
+ var restoreUser = controls.chooseUserForSend(o.isAnonymous === true);
62
79
  // an app awaiting this must be able to tell its user the feedback did not go: resolving on a
63
80
  // failure would have it say "thanks, sent" for a report the server never received
64
81
  return submitFeedback(dataobj).then(function (result) {
82
+ restoreUser();
83
+ return result;
84
+ }, function (err) {
85
+ restoreUser();
86
+ throw err;
87
+ }).then(function (result) {
65
88
  if (!result) {
66
- throw new Error('apptics.sendFeedback: not sent, the browser is offline or Apptics is disabled for this client'); // no i18n
89
+ throw new Error('AppticsFeedback.sendFeedback: not sent, the browser is offline or Apptics is disabled for this client'); // no i18n
67
90
  }
68
91
  if (!result.ok) {
69
- throw new Error('apptics.sendFeedback: not sent, ' + result.message); // no i18n
92
+ throw new Error('AppticsFeedback.sendFeedback: not sent, ' + result.message); // no i18n
70
93
  }
71
94
  });
72
95
  }
@@ -111,23 +134,54 @@ function newTransfer() {
111
134
  return null;
112
135
  }
113
136
  }
114
- function feedbackOpen(type, message, includeLog, includeDyninfo, attachments, logFiles, isAnonymous) {
137
+ function feedbackFormOpen(options) {
138
+ if (options !== undefined && !isOptions(options) && !saidOpenForm) {
139
+ // the old form, feedbackFormOpen(type, message, ...): the form still opens, with its defaults
140
+ saidOpenForm = true;
141
+ logger.warnAlways('AppticsFeedback.feedbackFormOpen: takes one options object, as feedbackFormOpen({ type, message, includeLog, includeDiagnostics, attachments, logFiles, isAnonymous }); opening it with its defaults'); // no i18n
142
+ }
143
+ const o = isOptions(options) ? options : {};
115
144
  const opts = {
116
- includeLog: includeLog === true,
117
- includeDyninfo: includeDyninfo === true,
118
- isAnonymous: isAnonymous === true,
145
+ includeLog: o.includeLog === true,
146
+ includeDyninfo: o.includeDiagnostics === true,
147
+ isAnonymous: o.isAnonymous === true,
119
148
  };
120
- if (typeof type === 'number')
121
- opts.type = type; // no i18n
122
- if (typeof message === 'string' && message.length > 0)
123
- opts.message = message; // no i18n
124
- if (attachments && attachments.length > 0)
125
- opts.attachments = attachments;
126
- if (logFiles && logFiles.length > 0)
127
- opts.logFiles = logFiles;
149
+ if (typeof o.type === 'number')
150
+ opts.type = o.type; // no i18n
151
+ if (typeof o.message === 'string' && o.message.length > 0)
152
+ opts.message = o.message; // no i18n
153
+ if (o.attachments && o.attachments.length > 0)
154
+ opts.attachments = o.attachments;
155
+ if (o.logFiles && o.logFiles.length > 0)
156
+ opts.logFiles = o.logFiles;
157
+ // the form brings its own styles, so an app imports or links no css
158
+ stylesheet.injectStylesheet(styles.default);
128
159
  feedback.init(opts);
129
160
  }
130
- function feedbackClose() {
161
+ /** The themes the form has: 'auto' follows the visitor's system setting. */
162
+ const FEEDBACK_THEMES = ['light', 'dark', 'auto']; // no i18n
163
+ /**
164
+ * Sets the form's theme, for a page with its own light and dark modes: 'auto' follows the
165
+ * operating system, which is not what such a page shows. Restyles a form or recording timer that
166
+ * is open now, and every one opened after; Apptics.init()'s feedback_theme only sets the first.
167
+ */
168
+ function setFeedbackTheme(theme) {
169
+ if (FEEDBACK_THEMES.indexOf(theme) === -1) {
170
+ logger.Console.warn('AppticsFeedback.setFeedbackTheme: takes \'light\', \'dark\' or \'auto\', not ' + JSON.stringify(theme)); // no i18n
171
+ return;
172
+ }
173
+ state._ZAP._config.feedback_theme = theme;
174
+ if (typeof document === 'undefined') { // no i18n
175
+ return;
176
+ }
177
+ ['zasdkFeedbackModal', 'zasdkrectimer'].forEach(function (id) {
178
+ var open = document.getElementById(id);
179
+ if (open) {
180
+ open.setAttribute('data-zasdk-theme', theme); // no i18n
181
+ }
182
+ });
183
+ }
184
+ function feedbackFormClose() {
131
185
  feedback.close();
132
186
  }
133
187
  const feedback = {
@@ -158,25 +212,15 @@ const feedback = {
158
212
  feedback.uploadFileAry = [];
159
213
  tempContainer.id = 'zasdkFeedbackModal'; // no i18n
160
214
  tempContainer.className = 'zasdk-modal'; // no i18n
215
+ tempContainer.setAttribute('data-zasdk-theme', state._ZAP._config.feedback_theme); // no i18n
161
216
  tempContainer.innerHTML = feedback.feedbackUIHtml;
162
217
  document.body.appendChild(tempContainer);
163
218
  var modal = document.getElementById("zasdkFeedbackModal"); // no i18n
164
- var defaultoption = state._ZAP._defaultoptions;
165
- var qz_ws_key = defaultoption.quartz_workspace_key;
166
- var qz_dp_key = defaultoption.quartz_department_key;
167
- var quartz_DC = {
168
- "Local": "https://quartz.localzoho.com", // no i18n
169
- "US": "https://quartz.zoho.com", // no i18n
170
- "EU": "https://quartz.zoho.eu", // no i18n
171
- "IN": "https://quartz.zoho.in", // no i18n
172
- "AU": "https://quartz.zoho.com.au", // no i18n
173
- "CN": "https://quartz.zoho.com.cn", // no i18n
174
- "CA": "https://quartz.zohocloud.ca", // no i18n
175
- "JP": "https://quartz.zoho.jp", // no i18n
176
- "SA": "https://quartz.zoho.sa", // no i18n
177
- "AE": "https://quartz.zoho.ae" // no i18n
178
- };
179
- var qz_dc_key = (!utils.isEmpty(defaultoption.DC) && defaultoption.DC !== '-') ? (quartz_DC[defaultoption.DC] || '') : ''; // no i18n
219
+ // screen recording as the console set it up for this app (getsdkconfig's quartz block)
220
+ var qz = state._ZAP._quartz;
221
+ var qz_ws_key = qz.workspace;
222
+ var qz_dp_key = qz.department;
223
+ var qz_dc_key = quartz$1.recordingDomain(qz.domain);
180
224
  var closeBtn = modal.querySelector("#appticsfeedbackclose"); // no i18n
181
225
  var feedbackTypes = modal.querySelectorAll(".zasdk-feedback-type"); // no i18n
182
226
  feedback.fileInput = modal.querySelector("#zasdkFileInput"); // no i18n
@@ -199,12 +243,21 @@ const feedback = {
199
243
  document.addEventListener('quartz-feedback-state', feedback.bindQuartzEvent); // no i18n
200
244
  document.removeEventListener('quartz-feedback-error', feedback.handleErrorQuartzEvent); // no i18n
201
245
  document.addEventListener('quartz-feedback-error', feedback.handleErrorQuartzEvent); // no i18n
202
- // the consent checkbox and its label only when a recording can actually be made: the Quartz
203
- // script on the page, a DC it knows, and both keys. "-" for any of them turns it off; DC "-"
204
- // has already become '' above. A checkbox that leads only to "unavailable" is not offered
205
- var recordingAvailable = hasQuartz() && !utils.isEmpty(qz_dc_key)
206
- && !utils.isEmpty(qz_ws_key) && qz_ws_key !== "-" && !utils.isEmpty(qz_dp_key) && qz_dp_key !== "-"; // no i18n
207
- modal.querySelector("#zasdkreccheckcnt").style.display = recordingAvailable ? "block" : "none"; // no i18n
246
+ // the consent checkbox and its label only when a recording can actually be made: recording
247
+ // on for the app, its workspace, department and domain, and Quartz on the page. A checkbox
248
+ // that leads only to "unavailable" is not offered. Quartz is loaded here, the first time
249
+ // the form needs it, and the checkbox shows once it has arrived
250
+ var recordingConfigured = qz.enabled && !utils.isEmpty(qz_dc_key) && !utils.isEmpty(qz_ws_key) && !utils.isEmpty(qz_dp_key);
251
+ var recordingBlock = modal.querySelector("#zasdkreccheckcnt"); // no i18n
252
+ recordingBlock.style.display = recordingConfigured && hasQuartz() ? "block" : "none"; // no i18n
253
+ if (recordingConfigured && !hasQuartz()) {
254
+ // quartz_cdn_url, or Zoho's CDN for this serviceUrl when the answer carries none
255
+ quartz$1.loadQuartz(quartz$1.quartzScriptSource(qz.cdnUrl, String(state._ZAP._defaultoptions.serviceUrl || ''))).then(function (loaded) {
256
+ if (loaded && recordingBlock.isConnected) {
257
+ recordingBlock.style.display = "block"; // no i18n
258
+ }
259
+ });
260
+ }
208
261
  feedbackbox.addEventListener('transitionend', function (event) {
209
262
  if (event.propertyName === 'transform' && feedback.isScaled) { // no i18n
210
263
  feedback.toggleWindowAnimation();
@@ -233,6 +286,14 @@ const feedback = {
233
286
  closeBtn.onclick = function () {
234
287
  feedback.close();
235
288
  };
289
+ // keyboard: Enter or Space on the close control, and Escape anywhere, close the form
290
+ closeBtn.onkeydown = function (e) {
291
+ if (e.key === 'Enter' || e.key === ' ') { // no i18n
292
+ e.preventDefault();
293
+ feedback.close();
294
+ }
295
+ };
296
+ document.addEventListener('keydown', feedback.onEscape); // no i18n
236
297
  preivewButton.addEventListener('click', function () {
237
298
  quartz().previewVideo();
238
299
  });
@@ -283,6 +344,11 @@ const feedback = {
283
344
  }
284
345
  });
285
346
  descriptionField.addEventListener('input', feedback.validateFeedbackField); // no i18n
347
+ // keyboard and screen-reader users land in the form, not behind it
348
+ try {
349
+ descriptionField.focus({ preventScroll: true });
350
+ }
351
+ catch (err) { /* focus is a courtesy */ }
286
352
  feedbackTypes.forEach(function (type) {
287
353
  type.addEventListener("click", function () {
288
354
  feedbackTypes.forEach(function (t) {
@@ -291,7 +357,7 @@ const feedback = {
291
357
  this.classList.add("zasdk-selected"); // no i18n
292
358
  });
293
359
  });
294
- // what feedbackOpen() was given: select that type, fill the description
360
+ // what feedbackFormOpen() was given: select that type, fill the description
295
361
  if (typeof feedback._opts.type === 'number') { // no i18n
296
362
  var wanted = Object.keys(feedback.typeObj).filter(function (name) {
297
363
  return feedback.typeObj[name] === feedback._opts.type;
@@ -351,6 +417,10 @@ const feedback = {
351
417
  let counterElem = elem.parentElement ? elem.parentElement.querySelector(".zaleftcharcnt") : null; // no i18n
352
418
  if (counterElem) {
353
419
  counterElem.textContent = String(maxLength - val.length); // Update remaining count
420
+ var unit = counterElem.parentElement ? counterElem.parentElement.querySelector(".zaleftchartxt") : null; // no i18n
421
+ if (unit) {
422
+ unit.textContent = maxLength - val.length === 1 ? 'character left' : 'characters left'; // no i18n
423
+ }
354
424
  }
355
425
  });
356
426
  },
@@ -394,6 +464,7 @@ const feedback = {
394
464
  const tempDiv = document.createElement("div"); // no i18n
395
465
  tempDiv.innerHTML = feedback.timerHtml;
396
466
  const node = tempDiv.firstElementChild;
467
+ node.setAttribute('data-zasdk-theme', state._ZAP._config.feedback_theme); // no i18n
397
468
  document.body.appendChild(node);
398
469
  var feedbacktimer = document.getElementById("zasdkrectimer"); // no i18n
399
470
  feedback.timerDisplay = feedbacktimer.querySelector('#zasdkTimerDisplay'); // no i18n
@@ -406,8 +477,14 @@ const feedback = {
406
477
  feedback.toggleWindowAnimation();
407
478
  }
408
479
  },
480
+ onEscape: function (e) {
481
+ if (e.key === 'Escape') { // no i18n
482
+ feedback.close();
483
+ }
484
+ },
409
485
  close: function () {
410
486
  var modal = document.getElementById("zasdkFeedbackModal"); // no i18n
487
+ document.removeEventListener('keydown', feedback.onEscape); // no i18n
411
488
  document.removeEventListener('quartz-feedback-state', feedback.bindQuartzEvent); // no i18n
412
489
  quartz().clearFeedback();
413
490
  if (!utils.isEmpty(modal)) {
@@ -626,6 +703,7 @@ const feedback = {
626
703
  };
627
704
 
628
705
  exports.feedback = feedback;
629
- exports.feedbackClose = feedbackClose;
630
- exports.feedbackOpen = feedbackOpen;
706
+ exports.feedbackFormClose = feedbackFormClose;
707
+ exports.feedbackFormOpen = feedbackFormOpen;
631
708
  exports.sendFeedback = sendFeedback;
709
+ exports.setFeedbackTheme = setFeedbackTheme;
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var state = require('../core/state.js');
@@ -1,4 +1,4 @@
1
1
  /** Turns capture on or off. Listeners are passive, so they never delay a click or a scroll. */
2
- export declare function enableHeatmap(status?: boolean): void;
2
+ export declare function trackHeatmap(status?: boolean): void;
3
3
  /** Forgets what this visit recorded. reset() calls it; the cap starts again from zero. */
4
4
  export declare function resetHeatmapSession(): void;
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var constants = require('../core/constants.js');
@@ -24,6 +24,12 @@ var debug = require('../core/debug.js');
24
24
  */
25
25
  /** How long the page must be still before a scroll burst counts as one finished gesture. */
26
26
  const SCROLL_IDLE_MS = 150;
27
+ /**
28
+ * How much of the viewport, each way, an element must cover for its scrolling to be the page's.
29
+ * An app whose layout scrolls a content pane instead of the window (most dashboards do) still
30
+ * gets a scroll map; a dropdown list or a small table scrolling on its own is not the page moving.
31
+ */
32
+ const PAGE_SCROLLER_SHARE = 0.5;
27
33
  /** Clicks closer than this in time and space count as one angry repetition. */
28
34
  const RAGE_WINDOW_MS = 1000;
29
35
  const RAGE_RADIUS_PX = 30;
@@ -42,6 +48,10 @@ var scrollStart = 0;
42
48
  var scrollStartX = 0;
43
49
  var scrollStartY = 0;
44
50
  var scrollTimer = null;
51
+ /** What the gesture in progress scrolls: null for the window, else the page's content pane. */
52
+ var scrolling = null;
53
+ /** Where each content pane was after its last gesture, as lastX / lastY are for the window. */
54
+ var paneAt = new WeakMap();
45
55
  /**
46
56
  * Where the page was before the current gesture began.
47
57
  *
@@ -124,7 +134,7 @@ function labelFor(node) {
124
134
  if (!node) {
125
135
  return ''; // no i18n
126
136
  }
127
- var attributes = ['data-ap-label', 'apeventaction', 'aria-label', 'name', 'id', 'title']; // no i18n
137
+ var attributes = ['data-ap-label', 'apeventaction', 'data-apeventaction', 'aria-label', 'name', 'id', 'title']; // no i18n
128
138
  for (var i = 0; i < attributes.length; i++) {
129
139
  var value = node.getAttribute ? node.getAttribute(attributes[i]) : null;
130
140
  if (!utils.isEmpty(value)) {
@@ -280,14 +290,57 @@ function watchForDeadClick(record, target) {
280
290
  }
281
291
  }, DEAD_CLICK_MS);
282
292
  }
283
- function onScroll() {
293
+ /**
294
+ * What a scroll event moved, as a gesture counts it: null for the window (the event's target is
295
+ * the document), the element when it is big enough to be the page's own scrolling, and undefined
296
+ * for anything smaller, which is not recorded.
297
+ */
298
+ function scrollerOf(target) {
299
+ var doc = document;
300
+ // the window and the document are not elements: either is the page itself scrolling
301
+ if (!target || target.nodeType !== 1 || target === doc.documentElement || target === doc.body) {
302
+ return null;
303
+ }
304
+ var el = target;
305
+ var big = el.clientHeight >= (window.innerHeight || 0) * PAGE_SCROLLER_SHARE
306
+ && el.clientWidth >= viewportWidth() * PAGE_SCROLLER_SHARE;
307
+ return big ? el : undefined;
308
+ }
309
+ /** Where a scroller is now. */
310
+ function positionOf(scroller) {
311
+ return scroller === null
312
+ ? { x: Math.round(window.scrollX || window.pageXOffset || 0), y: Math.round(window.scrollY || window.pageYOffset || 0) }
313
+ : { x: Math.round(scroller.scrollLeft || 0), y: Math.round(scroller.scrollTop || 0) };
314
+ }
315
+ /**
316
+ * Where a scroller was before this gesture: what the last one left. A content pane seen for the
317
+ * first time is taken to have been at its top, which is where a pane starts.
318
+ */
319
+ function startOf(scroller) {
320
+ if (scroller === null) {
321
+ return { x: lastX, y: lastY };
322
+ }
323
+ return paneAt.get(scroller) || { x: 0, y: 0 };
324
+ }
325
+ function onScroll(event) {
284
326
  if (!consent.canTrackHeatmap('heatmap') || !underCap()) { // no i18n
285
327
  return;
286
328
  }
329
+ var scroller = scrollerOf(event ? event.target : null);
330
+ if (scroller === undefined) {
331
+ return;
332
+ }
333
+ if (scrollTimer !== null && scroller !== scrolling) {
334
+ // another scroller started moving: the gesture on the first one is over
335
+ clearTimeout(scrollTimer);
336
+ endScrollGesture();
337
+ }
287
338
  if (scrollTimer === null) {
339
+ scrolling = scroller;
340
+ var start = startOf(scroller);
288
341
  scrollStart = utils.nowMs();
289
- scrollStartX = lastX;
290
- scrollStartY = lastY;
342
+ scrollStartX = start.x;
343
+ scrollStartY = start.y;
291
344
  }
292
345
  else {
293
346
  clearTimeout(scrollTimer);
@@ -297,13 +350,21 @@ function onScroll() {
297
350
  /** One record for the whole burst, once the page has been still for SCROLL_IDLE_MS. */
298
351
  function endScrollGesture() {
299
352
  scrollTimer = null;
353
+ var scroller = scrolling;
354
+ scrolling = null;
300
355
  try {
301
- var endX = Math.round(window.scrollX || 0);
302
- var endY = Math.round(window.scrollY || 0);
356
+ var end = positionOf(scroller);
357
+ var endX = end.x;
358
+ var endY = end.y;
303
359
  var dx = endX - scrollStartX;
304
360
  var dy = endY - scrollStartY;
305
- lastX = endX;
306
- lastY = endY;
361
+ if (scroller === null) {
362
+ lastX = endX;
363
+ lastY = endY;
364
+ }
365
+ else {
366
+ paneAt.set(scroller, end);
367
+ }
307
368
  if (dx === 0 && dy === 0) {
308
369
  return;
309
370
  }
@@ -312,8 +373,14 @@ function endScrollGesture() {
312
373
  var direction = Math.abs(dy) >= Math.abs(dx)
313
374
  ? (dy > 0 ? 'down-scroll' : 'up-scroll') // no i18n
314
375
  : (dx > 0 ? 'right-scroll' : 'left-scroll'); // no i18n
315
- var height = contentHeight() || 1;
316
- store(Object.assign(common(), {
376
+ // the depth is of what scrolled: the document, or the content pane and its own content
377
+ var height = (scroller === null ? contentHeight() : scroller.scrollHeight) || 1;
378
+ var visible = scroller === null ? (window.innerHeight || 0) : scroller.clientHeight;
379
+ store(Object.assign(common(), scroller === null ? {} : {
380
+ content_height: scroller.scrollHeight,
381
+ scroll_offset_x: endX,
382
+ scroll_offset_y: endY,
383
+ }, {
317
384
  // the server accepts only event|default|buttonclick here; what kind of movement it
318
385
  // was belongs in gesture_type. input_type is left off rather than invented: a wheel
319
386
  // carries no pointer type, and the intended vocabulary has no value for "unknown"
@@ -326,7 +393,7 @@ function endScrollGesture() {
326
393
  coordinate_y: endY,
327
394
  normalized_x: 0,
328
395
  // how far down the page the gesture left them, which is what a scroll map reads
329
- normalized_y: fraction(endY + (window.innerHeight || 0), height),
396
+ normalized_y: fraction(endY + visible, height),
330
397
  velocity: Math.round((distance / duration) * 1000),
331
398
  is_clickable: 0,
332
399
  is_rage_click: 0,
@@ -338,7 +405,7 @@ function endScrollGesture() {
338
405
  }
339
406
  }
340
407
  /** Turns capture on or off. Listeners are passive, so they never delay a click or a scroll. */
341
- function enableHeatmap(status) {
408
+ function trackHeatmap(status) {
342
409
  var wanted = typeof status === 'boolean' ? status : true; // no i18n
343
410
  if (wanted === installed) {
344
411
  return;
@@ -355,10 +422,13 @@ function enableHeatmap(status) {
355
422
  }
356
423
  window.removeEventListener('pointerdown', onPointerDown, true); // no i18n
357
424
  window.removeEventListener('scroll', onScroll, true); // no i18n
425
+ // a gesture still settling when capture stops (a single-page app leaving a heatmap page) is
426
+ // recorded as it stands, not dropped: it was the visitor's last scroll on that page
358
427
  if (scrollTimer !== null) {
359
428
  clearTimeout(scrollTimer);
360
- scrollTimer = null;
429
+ endScrollGesture();
361
430
  }
431
+ scrolling = null;
362
432
  installed = false;
363
433
  logger.Console.log('apptics.heatmap: capture stopped'); // no i18n
364
434
  }
@@ -368,10 +438,11 @@ function resetHeatmapSession() {
368
438
  recentClicks = [];
369
439
  lastX = 0;
370
440
  lastY = 0;
441
+ paneAt = new WeakMap();
371
442
  }
372
443
  // init() and reset() drive capture through these, so neither has to import this module
373
- hooks.hooks.enableHeatmap = enableHeatmap;
444
+ hooks.hooks.trackHeatmap = trackHeatmap;
374
445
  hooks.hooks.resetHeatmap = resetHeatmapSession;
375
446
 
376
- exports.enableHeatmap = enableHeatmap;
377
447
  exports.resetHeatmapSession = resetHeatmapSession;
448
+ exports.trackHeatmap = trackHeatmap;