@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.
- package/CHANGELOG.md +111 -5
- package/README.md +399 -300
- package/dist/apptics.esm.min.js +2 -2
- package/dist/apptics.esm.min.js.map +1 -1
- package/dist/apptics.min.js +2 -2
- package/dist/apptics.min.js.map +1 -1
- package/dist/chunks/lifecycle-VYr43KcB.min.js +3 -0
- package/dist/chunks/lifecycle-VYr43KcB.min.js.map +1 -0
- package/dist/cjs/auto-init.d.ts +3 -3
- package/dist/cjs/auto-init.js +1 -1
- package/dist/cjs/core/attempts.js +1 -1
- package/dist/cjs/core/batch.js +2 -1
- package/dist/cjs/core/callsite.d.ts +6 -0
- package/dist/cjs/core/callsite.js +25 -3
- package/dist/cjs/core/consent.d.ts +5 -1
- package/dist/cjs/core/consent.js +8 -6
- package/dist/cjs/core/constants.d.ts +35 -10
- package/dist/cjs/core/constants.js +31 -15
- package/dist/cjs/core/db.d.ts +12 -4
- package/dist/cjs/core/db.js +167 -34
- package/dist/cjs/core/debug.js +1 -1
- package/dist/cjs/core/env.js +1 -1
- package/dist/cjs/core/framework-id.d.ts +1 -1
- package/dist/cjs/core/framework-id.js +3 -3
- package/dist/cjs/core/guard.d.ts +9 -0
- package/dist/cjs/core/guard.js +27 -13
- package/dist/cjs/core/hooks.d.ts +2 -4
- package/dist/cjs/core/hooks.js +2 -3
- package/dist/cjs/core/locks.d.ts +9 -0
- package/dist/cjs/core/locks.js +22 -0
- package/dist/cjs/core/logger.d.ts +3 -4
- package/dist/cjs/core/logger.js +4 -40
- package/dist/cjs/core/state.d.ts +3 -2
- package/dist/cjs/core/state.js +2 -2
- package/dist/cjs/core/storage.d.ts +20 -5
- package/dist/cjs/core/storage.js +115 -17
- package/dist/cjs/core/stylesheet.d.ts +8 -0
- package/dist/cjs/core/stylesheet.js +29 -0
- package/dist/cjs/core/transport.d.ts +2 -0
- package/dist/cjs/core/transport.js +19 -4
- package/dist/cjs/core/utils.js +1 -1
- package/dist/cjs/core/validate.js +2 -2
- package/dist/cjs/device/appversion.d.ts +1 -6
- package/dist/cjs/device/appversion.js +13 -1
- package/dist/cjs/device/index.d.ts +11 -0
- package/dist/cjs/device/index.js +120 -20
- package/dist/cjs/engagement/api-rules.d.ts +32 -67
- package/dist/cjs/engagement/api-rules.js +144 -157
- package/dist/cjs/engagement/auto-api.js +2 -2
- package/dist/cjs/engagement/auto-screen.d.ts +2 -0
- package/dist/cjs/engagement/auto-screen.js +67 -3
- package/dist/cjs/engagement/defined-events.js +1 -1
- package/dist/cjs/engagement/send.js +6 -1
- package/dist/cjs/engagement/session.d.ts +12 -3
- package/dist/cjs/engagement/session.js +161 -25
- package/dist/cjs/engagement/track.js +45 -20
- package/dist/cjs/errors/send.js +1 -1
- package/dist/cjs/errors/track.d.ts +1 -1
- package/dist/cjs/errors/track.js +46 -6
- package/dist/cjs/feedback/controls.d.ts +6 -0
- package/dist/cjs/feedback/controls.js +31 -1
- package/dist/cjs/feedback/index.d.ts +8 -7
- package/dist/cjs/feedback/index.js +32 -13
- package/dist/cjs/feedback/logs.d.ts +10 -5
- package/dist/cjs/feedback/logs.js +52 -13
- package/dist/cjs/feedback/quartz.d.ts +18 -0
- package/dist/cjs/feedback/quartz.js +105 -0
- package/dist/cjs/feedback/send.d.ts +3 -0
- package/dist/cjs/feedback/send.js +28 -3
- package/dist/cjs/feedback/styles.d.ts +10 -0
- package/dist/cjs/feedback/styles.js +8 -0
- package/dist/cjs/feedback/template.d.ts +1 -1
- package/dist/cjs/feedback/template.js +12 -12
- package/dist/cjs/feedback/ui.d.ts +14 -6
- package/dist/cjs/feedback/ui.js +126 -48
- package/dist/cjs/heatmap/send.js +1 -1
- package/dist/cjs/heatmap/track.d.ts +1 -1
- package/dist/cjs/heatmap/track.js +87 -16
- package/dist/cjs/index.d.ts +17 -63
- package/dist/cjs/index.js +104 -92
- package/dist/cjs/lifecycle.d.ts +8 -1
- package/dist/cjs/lifecycle.js +258 -62
- package/dist/cjs/remoteconfig/country.d.ts +4 -0
- package/dist/cjs/remoteconfig/country.js +73 -0
- package/dist/cjs/remoteconfig/custom.d.ts +7 -7
- package/dist/cjs/remoteconfig/custom.js +31 -51
- package/dist/cjs/remoteconfig/evaluate.d.ts +3 -3
- package/dist/cjs/remoteconfig/evaluate.js +56 -43
- package/dist/cjs/remoteconfig/fetch.d.ts +3 -3
- package/dist/cjs/remoteconfig/fetch.js +9 -23
- package/dist/cjs/remoteconfig/index.d.ts +10 -8
- package/dist/cjs/remoteconfig/index.js +65 -39
- package/dist/cjs/remoteconfig/store.js +1 -1
- package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
- package/dist/cjs/remoteconfig/tz-countries.js +13 -0
- package/dist/cjs/remotelog/gate.d.ts +2 -11
- package/dist/cjs/remotelog/gate.js +9 -35
- package/dist/cjs/remotelog/index.d.ts +4 -21
- package/dist/cjs/remotelog/logger.d.ts +11 -17
- package/dist/cjs/remotelog/logger.js +30 -58
- package/dist/cjs/remotelog/send.js +10 -10
- package/dist/cjs/remotelogger/index.d.ts +12 -0
- package/dist/cjs/remotelogger/index.js +18 -0
- package/dist/cjs/scheduler.js +2 -2
- package/dist/cjs/types.d.ts +155 -82
- package/dist/cjs/user/index.js +11 -6
- package/dist/esm/auto-init.d.ts +3 -3
- package/dist/esm/auto-init.js +1 -1
- package/dist/esm/core/attempts.js +1 -1
- package/dist/esm/core/batch.js +2 -1
- package/dist/esm/core/callsite.d.ts +6 -0
- package/dist/esm/core/callsite.js +25 -4
- package/dist/esm/core/consent.d.ts +5 -1
- package/dist/esm/core/consent.js +9 -7
- package/dist/esm/core/constants.d.ts +35 -10
- package/dist/esm/core/constants.js +30 -15
- package/dist/esm/core/db.d.ts +12 -4
- package/dist/esm/core/db.js +164 -35
- package/dist/esm/core/debug.js +1 -1
- package/dist/esm/core/env.js +1 -1
- package/dist/esm/core/framework-id.d.ts +1 -1
- package/dist/esm/core/framework-id.js +3 -3
- package/dist/esm/core/guard.d.ts +9 -0
- package/dist/esm/core/guard.js +27 -14
- package/dist/esm/core/hooks.d.ts +2 -4
- package/dist/esm/core/hooks.js +2 -3
- package/dist/esm/core/locks.d.ts +9 -0
- package/dist/esm/core/locks.js +20 -0
- package/dist/esm/core/logger.d.ts +3 -4
- package/dist/esm/core/logger.js +4 -40
- package/dist/esm/core/state.d.ts +3 -2
- package/dist/esm/core/state.js +2 -2
- package/dist/esm/core/storage.d.ts +20 -5
- package/dist/esm/core/storage.js +113 -18
- package/dist/esm/core/stylesheet.d.ts +8 -0
- package/dist/esm/core/stylesheet.js +27 -0
- package/dist/esm/core/transport.d.ts +2 -0
- package/dist/esm/core/transport.js +19 -5
- package/dist/esm/core/utils.js +1 -1
- package/dist/esm/core/validate.js +2 -2
- package/dist/esm/device/appversion.d.ts +1 -6
- package/dist/esm/device/appversion.js +13 -2
- package/dist/esm/device/index.d.ts +11 -0
- package/dist/esm/device/index.js +123 -24
- package/dist/esm/engagement/api-rules.d.ts +32 -67
- package/dist/esm/engagement/api-rules.js +143 -155
- package/dist/esm/engagement/auto-api.js +3 -3
- package/dist/esm/engagement/auto-screen.d.ts +2 -0
- package/dist/esm/engagement/auto-screen.js +67 -4
- package/dist/esm/engagement/defined-events.js +1 -1
- package/dist/esm/engagement/send.js +6 -1
- package/dist/esm/engagement/session.d.ts +12 -3
- package/dist/esm/engagement/session.js +162 -29
- package/dist/esm/engagement/track.js +52 -27
- package/dist/esm/errors/send.js +1 -1
- package/dist/esm/errors/track.d.ts +1 -1
- package/dist/esm/errors/track.js +46 -6
- package/dist/esm/feedback/controls.d.ts +6 -0
- package/dist/esm/feedback/controls.js +31 -2
- package/dist/esm/feedback/index.d.ts +8 -7
- package/dist/esm/feedback/index.js +34 -13
- package/dist/esm/feedback/logs.d.ts +10 -5
- package/dist/esm/feedback/logs.js +54 -15
- package/dist/esm/feedback/quartz.d.ts +18 -0
- package/dist/esm/feedback/quartz.js +99 -0
- package/dist/esm/feedback/send.d.ts +3 -0
- package/dist/esm/feedback/send.js +28 -5
- package/dist/esm/feedback/styles.d.ts +10 -0
- package/dist/esm/feedback/styles.js +4 -0
- package/dist/esm/feedback/template.d.ts +1 -1
- package/dist/esm/feedback/template.js +12 -12
- package/dist/esm/feedback/ui.d.ts +14 -6
- package/dist/esm/feedback/ui.js +126 -49
- package/dist/esm/heatmap/send.js +1 -1
- package/dist/esm/heatmap/track.d.ts +1 -1
- package/dist/esm/heatmap/track.js +87 -16
- package/dist/esm/index.d.ts +17 -63
- package/dist/esm/index.js +108 -80
- package/dist/esm/lifecycle.d.ts +8 -1
- package/dist/esm/lifecycle.js +266 -71
- package/dist/esm/remoteconfig/country.d.ts +4 -0
- package/dist/esm/remoteconfig/country.js +70 -0
- package/dist/esm/remoteconfig/custom.d.ts +7 -7
- package/dist/esm/remoteconfig/custom.js +32 -52
- package/dist/esm/remoteconfig/evaluate.d.ts +3 -3
- package/dist/esm/remoteconfig/evaluate.js +57 -44
- package/dist/esm/remoteconfig/fetch.d.ts +3 -3
- package/dist/esm/remoteconfig/fetch.js +9 -23
- package/dist/esm/remoteconfig/index.d.ts +10 -8
- package/dist/esm/remoteconfig/index.js +66 -40
- package/dist/esm/remoteconfig/store.js +1 -1
- package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
- package/dist/esm/remoteconfig/tz-countries.js +11 -0
- package/dist/esm/remotelog/gate.d.ts +2 -11
- package/dist/esm/remotelog/gate.js +10 -32
- package/dist/esm/remotelog/index.d.ts +4 -21
- package/dist/esm/remotelog/logger.d.ts +11 -17
- package/dist/esm/remotelog/logger.js +32 -60
- package/dist/esm/remotelog/send.js +12 -12
- package/dist/esm/remotelogger/index.d.ts +12 -0
- package/dist/esm/remotelogger/index.js +13 -0
- package/dist/esm/scheduler.js +2 -2
- package/dist/esm/types.d.ts +155 -82
- package/dist/esm/user/index.js +12 -6
- package/dist/feedback.esm.min.js +2 -2
- package/dist/feedback.esm.min.js.map +1 -1
- package/package.json +14 -16
- package/dist/chunks/batch-BU_mTpm1.min.js +0 -3
- package/dist/chunks/batch-BU_mTpm1.min.js.map +0 -1
- package/dist/chunks/logs-Bea5zUW_.min.js +0 -3
- package/dist/chunks/logs-Bea5zUW_.min.js.map +0 -1
- package/dist/cjs/heatmap/index.d.ts +0 -16
- package/dist/cjs/heatmap/index.js +0 -22
- package/dist/cjs/remotelog/index.js +0 -55
- package/dist/esm/heatmap/index.d.ts +0 -16
- package/dist/esm/heatmap/index.js +0 -17
- package/dist/esm/remotelog/index.js +0 -51
- package/dist/heatmap.esm.min.js +0 -3
- package/dist/heatmap.esm.min.js.map +0 -1
- package/dist/style.css +0 -1
|
@@ -1,23 +1,23 @@
|
|
|
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
|
// Feedback modal markup (moved from js/apptics.js).
|
|
3
|
-
const feedbackUIHtml = `<div id="zasdkFeedbackconatiner" class="zasdk-modal-content">
|
|
3
|
+
const feedbackUIHtml = `<div id="zasdkFeedbackconatiner" class="zasdk-modal-content" role="dialog" aria-modal="true" aria-labelledby="zasdkFeedbackTitle">
|
|
4
4
|
<div class="zasdk-header">
|
|
5
|
-
<h2 class="zasdk-title">Share feedback</h2>
|
|
6
|
-
<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>
|
|
5
|
+
<h2 id="zasdkFeedbackTitle" class="zasdk-title">Share feedback</h2>
|
|
6
|
+
<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>
|
|
7
7
|
</div>
|
|
8
8
|
<div class="zasdk-feedback-types" data-type="">
|
|
9
|
-
<div class="zasdk-feedback-type zasdk-selected" data-type="
|
|
10
|
-
<div class="zasdk-iconcnt zasdkfeedback__icon-report">
|
|
11
|
-
<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>
|
|
12
|
-
</div>
|
|
13
|
-
<div>Bug</div>
|
|
14
|
-
</div>
|
|
15
|
-
<div class="zasdk-feedback-type" data-type="feedback">
|
|
9
|
+
<div class="zasdk-feedback-type zasdk-selected" data-type="feedback">
|
|
16
10
|
<div class="zasdk-iconcnt zasdkfeedback__icon-reqest">
|
|
17
11
|
<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>
|
|
18
12
|
</div>
|
|
19
13
|
<div>Feedback</div>
|
|
20
14
|
</div>
|
|
15
|
+
<div class="zasdk-feedback-type" data-type="bug">
|
|
16
|
+
<div class="zasdk-iconcnt zasdkfeedback__icon-report">
|
|
17
|
+
<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>
|
|
18
|
+
</div>
|
|
19
|
+
<div>Bug</div>
|
|
20
|
+
</div>
|
|
21
21
|
<div class="zasdk-feedback-type" data-type="help">
|
|
22
22
|
<div class="zasdk-iconcnt zasdkfeedback__icon-help">
|
|
23
23
|
<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>
|
|
@@ -42,7 +42,7 @@ const feedbackUIHtml = `<div id="zasdkFeedbackconatiner" class="zasdk-modal-cont
|
|
|
42
42
|
<ul id="zasdkEmailList" class="zasdk-select-list"></ul>
|
|
43
43
|
</div>
|
|
44
44
|
</div>
|
|
45
|
-
<label class="zasdkdesclbl" for="zasdkDescription">Add details here<span class="zasdkmadfeld">*</span> <span class="zaleftcharspan"><span class="zaleftcharcnt">5000</span><span class="zaleftchartxt">
|
|
45
|
+
<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>
|
|
46
46
|
<textarea id="zasdkDescription" name="description" placeholder="Please provide more details for us to help you better." reqname="name" maxlength="5000"></textarea>
|
|
47
47
|
<div id="zasdkreccheckcnt" class="zasdkqz-container">
|
|
48
48
|
<div class="zasdkqz-checkbox-wrapper">
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import type { FeedbackType } from '../types.js';
|
|
2
|
-
export declare function sendFeedback(
|
|
3
|
-
export declare function
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
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];
|
package/dist/esm/feedback/ui.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
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
|
import { AP_TRACKING_STATUS } from '../core/constants.js';
|
|
3
3
|
import { _ZAP } from '../core/state.js';
|
|
4
|
-
import { Console } from '../core/logger.js';
|
|
4
|
+
import { Console, warnAlways } from '../core/logger.js';
|
|
5
5
|
import { isEmpty, isEmptyObj } from '../core/utils.js';
|
|
6
6
|
import { opt_in_status } from '../core/consent.js';
|
|
7
7
|
import { timerHtml, feedbackUIHtml } from './template.js';
|
|
8
8
|
import { sendFeedbackData } from './send.js';
|
|
9
|
-
import { wireDrag, wireUserPicker, wireLogControls, logChoice
|
|
9
|
+
import { chooseUserForSend, userChoice, wireDrag, wireUserPicker, wireLogControls, logChoice } from './controls.js';
|
|
10
|
+
import { injectStylesheet } from '../core/stylesheet.js';
|
|
11
|
+
import { recordingDomain, loadQuartz, quartzScriptSource } from './quartz.js';
|
|
12
|
+
import css from './styles.js';
|
|
10
13
|
|
|
11
14
|
// Quartz is an optional page-level SDK. Without it every call is a no-op (fix #5).
|
|
12
15
|
const QUARTZ_NOOP = {
|
|
@@ -46,25 +49,45 @@ function submitFeedback(dataobj) {
|
|
|
46
49
|
return result;
|
|
47
50
|
});
|
|
48
51
|
}
|
|
49
|
-
|
|
52
|
+
/** Whether a value is an options object: a plain object, not a type number or a message string. */
|
|
53
|
+
function isOptions(value) {
|
|
54
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value); // no i18n
|
|
55
|
+
}
|
|
56
|
+
/** Said once: the old one-argument-after-another form of feedbackFormOpen. */
|
|
57
|
+
var saidOpenForm = false;
|
|
58
|
+
function sendFeedback(options) {
|
|
59
|
+
if (options !== undefined && !isOptions(options)) {
|
|
60
|
+
// the old form, sendFeedback(type, message, ...): sending it as it stands would send an
|
|
61
|
+
// empty report, so it is refused, and says what to pass instead
|
|
62
|
+
return Promise.reject(new Error('AppticsFeedback.sendFeedback: takes one options object, as sendFeedback({ type, message, attachments, logFiles, includeDiagnostics, includeLog, isAnonymous })')); // no i18n
|
|
63
|
+
}
|
|
64
|
+
const o = options || {};
|
|
50
65
|
const dataobj = {
|
|
51
|
-
type: !isEmpty(
|
|
52
|
-
message:
|
|
53
|
-
attachment: attachments || null,
|
|
54
|
-
logsFiles:
|
|
66
|
+
type: !isEmpty(o.type) ? o.type : 1,
|
|
67
|
+
message: o.message || '', // no i18n
|
|
68
|
+
attachment: o.attachments || null,
|
|
69
|
+
logsFiles: o.logFiles || null,
|
|
55
70
|
// both flags stay as given: unset lets send.ts decide from what is actually stored
|
|
56
|
-
includeDyninfo:
|
|
57
|
-
includeLog: includeLog,
|
|
71
|
+
includeDyninfo: o.includeDiagnostics,
|
|
72
|
+
includeLog: o.includeLog,
|
|
58
73
|
quartzid: '' // no i18n
|
|
59
74
|
};
|
|
75
|
+
// from the active user, or from nobody with isAnonymous; the form's own choice is put back after
|
|
76
|
+
var restoreUser = chooseUserForSend(o.isAnonymous === true);
|
|
60
77
|
// an app awaiting this must be able to tell its user the feedback did not go: resolving on a
|
|
61
78
|
// failure would have it say "thanks, sent" for a report the server never received
|
|
62
79
|
return submitFeedback(dataobj).then(function (result) {
|
|
80
|
+
restoreUser();
|
|
81
|
+
return result;
|
|
82
|
+
}, function (err) {
|
|
83
|
+
restoreUser();
|
|
84
|
+
throw err;
|
|
85
|
+
}).then(function (result) {
|
|
63
86
|
if (!result) {
|
|
64
|
-
throw new Error('
|
|
87
|
+
throw new Error('AppticsFeedback.sendFeedback: not sent, the browser is offline or Apptics is disabled for this client'); // no i18n
|
|
65
88
|
}
|
|
66
89
|
if (!result.ok) {
|
|
67
|
-
throw new Error('
|
|
90
|
+
throw new Error('AppticsFeedback.sendFeedback: not sent, ' + result.message); // no i18n
|
|
68
91
|
}
|
|
69
92
|
});
|
|
70
93
|
}
|
|
@@ -109,23 +132,54 @@ function newTransfer() {
|
|
|
109
132
|
return null;
|
|
110
133
|
}
|
|
111
134
|
}
|
|
112
|
-
function
|
|
135
|
+
function feedbackFormOpen(options) {
|
|
136
|
+
if (options !== undefined && !isOptions(options) && !saidOpenForm) {
|
|
137
|
+
// the old form, feedbackFormOpen(type, message, ...): the form still opens, with its defaults
|
|
138
|
+
saidOpenForm = true;
|
|
139
|
+
warnAlways('AppticsFeedback.feedbackFormOpen: takes one options object, as feedbackFormOpen({ type, message, includeLog, includeDiagnostics, attachments, logFiles, isAnonymous }); opening it with its defaults'); // no i18n
|
|
140
|
+
}
|
|
141
|
+
const o = isOptions(options) ? options : {};
|
|
113
142
|
const opts = {
|
|
114
|
-
includeLog: includeLog === true,
|
|
115
|
-
includeDyninfo:
|
|
116
|
-
isAnonymous: isAnonymous === true,
|
|
143
|
+
includeLog: o.includeLog === true,
|
|
144
|
+
includeDyninfo: o.includeDiagnostics === true,
|
|
145
|
+
isAnonymous: o.isAnonymous === true,
|
|
117
146
|
};
|
|
118
|
-
if (typeof type === 'number')
|
|
119
|
-
opts.type = type; // no i18n
|
|
120
|
-
if (typeof message === 'string' && message.length > 0)
|
|
121
|
-
opts.message = message; // no i18n
|
|
122
|
-
if (attachments && attachments.length > 0)
|
|
123
|
-
opts.attachments = attachments;
|
|
124
|
-
if (logFiles && logFiles.length > 0)
|
|
125
|
-
opts.logFiles = logFiles;
|
|
147
|
+
if (typeof o.type === 'number')
|
|
148
|
+
opts.type = o.type; // no i18n
|
|
149
|
+
if (typeof o.message === 'string' && o.message.length > 0)
|
|
150
|
+
opts.message = o.message; // no i18n
|
|
151
|
+
if (o.attachments && o.attachments.length > 0)
|
|
152
|
+
opts.attachments = o.attachments;
|
|
153
|
+
if (o.logFiles && o.logFiles.length > 0)
|
|
154
|
+
opts.logFiles = o.logFiles;
|
|
155
|
+
// the form brings its own styles, so an app imports or links no css
|
|
156
|
+
injectStylesheet(css);
|
|
126
157
|
feedback.init(opts);
|
|
127
158
|
}
|
|
128
|
-
|
|
159
|
+
/** The themes the form has: 'auto' follows the visitor's system setting. */
|
|
160
|
+
const FEEDBACK_THEMES = ['light', 'dark', 'auto']; // no i18n
|
|
161
|
+
/**
|
|
162
|
+
* Sets the form's theme, for a page with its own light and dark modes: 'auto' follows the
|
|
163
|
+
* operating system, which is not what such a page shows. Restyles a form or recording timer that
|
|
164
|
+
* is open now, and every one opened after; Apptics.init()'s feedback_theme only sets the first.
|
|
165
|
+
*/
|
|
166
|
+
function setFeedbackTheme(theme) {
|
|
167
|
+
if (FEEDBACK_THEMES.indexOf(theme) === -1) {
|
|
168
|
+
Console.warn('AppticsFeedback.setFeedbackTheme: takes \'light\', \'dark\' or \'auto\', not ' + JSON.stringify(theme)); // no i18n
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
_ZAP._config.feedback_theme = theme;
|
|
172
|
+
if (typeof document === 'undefined') { // no i18n
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
['zasdkFeedbackModal', 'zasdkrectimer'].forEach(function (id) {
|
|
176
|
+
var open = document.getElementById(id);
|
|
177
|
+
if (open) {
|
|
178
|
+
open.setAttribute('data-zasdk-theme', theme); // no i18n
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
function feedbackFormClose() {
|
|
129
183
|
feedback.close();
|
|
130
184
|
}
|
|
131
185
|
const feedback = {
|
|
@@ -156,25 +210,15 @@ const feedback = {
|
|
|
156
210
|
feedback.uploadFileAry = [];
|
|
157
211
|
tempContainer.id = 'zasdkFeedbackModal'; // no i18n
|
|
158
212
|
tempContainer.className = 'zasdk-modal'; // no i18n
|
|
213
|
+
tempContainer.setAttribute('data-zasdk-theme', _ZAP._config.feedback_theme); // no i18n
|
|
159
214
|
tempContainer.innerHTML = feedback.feedbackUIHtml;
|
|
160
215
|
document.body.appendChild(tempContainer);
|
|
161
216
|
var modal = document.getElementById("zasdkFeedbackModal"); // no i18n
|
|
162
|
-
|
|
163
|
-
var
|
|
164
|
-
var
|
|
165
|
-
var
|
|
166
|
-
|
|
167
|
-
"US": "https://quartz.zoho.com", // no i18n
|
|
168
|
-
"EU": "https://quartz.zoho.eu", // no i18n
|
|
169
|
-
"IN": "https://quartz.zoho.in", // no i18n
|
|
170
|
-
"AU": "https://quartz.zoho.com.au", // no i18n
|
|
171
|
-
"CN": "https://quartz.zoho.com.cn", // no i18n
|
|
172
|
-
"CA": "https://quartz.zohocloud.ca", // no i18n
|
|
173
|
-
"JP": "https://quartz.zoho.jp", // no i18n
|
|
174
|
-
"SA": "https://quartz.zoho.sa", // no i18n
|
|
175
|
-
"AE": "https://quartz.zoho.ae" // no i18n
|
|
176
|
-
};
|
|
177
|
-
var qz_dc_key = (!isEmpty(defaultoption.DC) && defaultoption.DC !== '-') ? (quartz_DC[defaultoption.DC] || '') : ''; // no i18n
|
|
217
|
+
// screen recording as the console set it up for this app (getsdkconfig's quartz block)
|
|
218
|
+
var qz = _ZAP._quartz;
|
|
219
|
+
var qz_ws_key = qz.workspace;
|
|
220
|
+
var qz_dp_key = qz.department;
|
|
221
|
+
var qz_dc_key = recordingDomain(qz.domain);
|
|
178
222
|
var closeBtn = modal.querySelector("#appticsfeedbackclose"); // no i18n
|
|
179
223
|
var feedbackTypes = modal.querySelectorAll(".zasdk-feedback-type"); // no i18n
|
|
180
224
|
feedback.fileInput = modal.querySelector("#zasdkFileInput"); // no i18n
|
|
@@ -197,12 +241,21 @@ const feedback = {
|
|
|
197
241
|
document.addEventListener('quartz-feedback-state', feedback.bindQuartzEvent); // no i18n
|
|
198
242
|
document.removeEventListener('quartz-feedback-error', feedback.handleErrorQuartzEvent); // no i18n
|
|
199
243
|
document.addEventListener('quartz-feedback-error', feedback.handleErrorQuartzEvent); // no i18n
|
|
200
|
-
// the consent checkbox and its label only when a recording can actually be made:
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
modal.querySelector("#zasdkreccheckcnt")
|
|
244
|
+
// the consent checkbox and its label only when a recording can actually be made: recording
|
|
245
|
+
// on for the app, its workspace, department and domain, and Quartz on the page. A checkbox
|
|
246
|
+
// that leads only to "unavailable" is not offered. Quartz is loaded here, the first time
|
|
247
|
+
// the form needs it, and the checkbox shows once it has arrived
|
|
248
|
+
var recordingConfigured = qz.enabled && !isEmpty(qz_dc_key) && !isEmpty(qz_ws_key) && !isEmpty(qz_dp_key);
|
|
249
|
+
var recordingBlock = modal.querySelector("#zasdkreccheckcnt"); // no i18n
|
|
250
|
+
recordingBlock.style.display = recordingConfigured && hasQuartz() ? "block" : "none"; // no i18n
|
|
251
|
+
if (recordingConfigured && !hasQuartz()) {
|
|
252
|
+
// quartz_cdn_url, or Zoho's CDN for this serviceUrl when the answer carries none
|
|
253
|
+
loadQuartz(quartzScriptSource(qz.cdnUrl, String(_ZAP._defaultoptions.serviceUrl || ''))).then(function (loaded) {
|
|
254
|
+
if (loaded && recordingBlock.isConnected) {
|
|
255
|
+
recordingBlock.style.display = "block"; // no i18n
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
206
259
|
feedbackbox.addEventListener('transitionend', function (event) {
|
|
207
260
|
if (event.propertyName === 'transform' && feedback.isScaled) { // no i18n
|
|
208
261
|
feedback.toggleWindowAnimation();
|
|
@@ -231,6 +284,14 @@ const feedback = {
|
|
|
231
284
|
closeBtn.onclick = function () {
|
|
232
285
|
feedback.close();
|
|
233
286
|
};
|
|
287
|
+
// keyboard: Enter or Space on the close control, and Escape anywhere, close the form
|
|
288
|
+
closeBtn.onkeydown = function (e) {
|
|
289
|
+
if (e.key === 'Enter' || e.key === ' ') { // no i18n
|
|
290
|
+
e.preventDefault();
|
|
291
|
+
feedback.close();
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
document.addEventListener('keydown', feedback.onEscape); // no i18n
|
|
234
295
|
preivewButton.addEventListener('click', function () {
|
|
235
296
|
quartz().previewVideo();
|
|
236
297
|
});
|
|
@@ -281,6 +342,11 @@ const feedback = {
|
|
|
281
342
|
}
|
|
282
343
|
});
|
|
283
344
|
descriptionField.addEventListener('input', feedback.validateFeedbackField); // no i18n
|
|
345
|
+
// keyboard and screen-reader users land in the form, not behind it
|
|
346
|
+
try {
|
|
347
|
+
descriptionField.focus({ preventScroll: true });
|
|
348
|
+
}
|
|
349
|
+
catch (err) { /* focus is a courtesy */ }
|
|
284
350
|
feedbackTypes.forEach(function (type) {
|
|
285
351
|
type.addEventListener("click", function () {
|
|
286
352
|
feedbackTypes.forEach(function (t) {
|
|
@@ -289,7 +355,7 @@ const feedback = {
|
|
|
289
355
|
this.classList.add("zasdk-selected"); // no i18n
|
|
290
356
|
});
|
|
291
357
|
});
|
|
292
|
-
// what
|
|
358
|
+
// what feedbackFormOpen() was given: select that type, fill the description
|
|
293
359
|
if (typeof feedback._opts.type === 'number') { // no i18n
|
|
294
360
|
var wanted = Object.keys(feedback.typeObj).filter(function (name) {
|
|
295
361
|
return feedback.typeObj[name] === feedback._opts.type;
|
|
@@ -349,6 +415,10 @@ const feedback = {
|
|
|
349
415
|
let counterElem = elem.parentElement ? elem.parentElement.querySelector(".zaleftcharcnt") : null; // no i18n
|
|
350
416
|
if (counterElem) {
|
|
351
417
|
counterElem.textContent = String(maxLength - val.length); // Update remaining count
|
|
418
|
+
var unit = counterElem.parentElement ? counterElem.parentElement.querySelector(".zaleftchartxt") : null; // no i18n
|
|
419
|
+
if (unit) {
|
|
420
|
+
unit.textContent = maxLength - val.length === 1 ? 'character left' : 'characters left'; // no i18n
|
|
421
|
+
}
|
|
352
422
|
}
|
|
353
423
|
});
|
|
354
424
|
},
|
|
@@ -392,6 +462,7 @@ const feedback = {
|
|
|
392
462
|
const tempDiv = document.createElement("div"); // no i18n
|
|
393
463
|
tempDiv.innerHTML = feedback.timerHtml;
|
|
394
464
|
const node = tempDiv.firstElementChild;
|
|
465
|
+
node.setAttribute('data-zasdk-theme', _ZAP._config.feedback_theme); // no i18n
|
|
395
466
|
document.body.appendChild(node);
|
|
396
467
|
var feedbacktimer = document.getElementById("zasdkrectimer"); // no i18n
|
|
397
468
|
feedback.timerDisplay = feedbacktimer.querySelector('#zasdkTimerDisplay'); // no i18n
|
|
@@ -404,8 +475,14 @@ const feedback = {
|
|
|
404
475
|
feedback.toggleWindowAnimation();
|
|
405
476
|
}
|
|
406
477
|
},
|
|
478
|
+
onEscape: function (e) {
|
|
479
|
+
if (e.key === 'Escape') { // no i18n
|
|
480
|
+
feedback.close();
|
|
481
|
+
}
|
|
482
|
+
},
|
|
407
483
|
close: function () {
|
|
408
484
|
var modal = document.getElementById("zasdkFeedbackModal"); // no i18n
|
|
485
|
+
document.removeEventListener('keydown', feedback.onEscape); // no i18n
|
|
409
486
|
document.removeEventListener('quartz-feedback-state', feedback.bindQuartzEvent); // no i18n
|
|
410
487
|
quartz().clearFeedback();
|
|
411
488
|
if (!isEmpty(modal)) {
|
|
@@ -623,4 +700,4 @@ const feedback = {
|
|
|
623
700
|
}
|
|
624
701
|
};
|
|
625
702
|
|
|
626
|
-
export { feedback,
|
|
703
|
+
export { feedback, feedbackFormClose, feedbackFormOpen, sendFeedback, setFeedbackTheme };
|
package/dist/esm/heatmap/send.js
CHANGED
|
@@ -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
|
import { _ZAP } from '../core/state.js';
|
|
3
3
|
import { Console, warnAlways } from '../core/logger.js';
|
|
4
4
|
import { cloneObject } from '../core/utils.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
|
|
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
|
import { AP_LOG_MODULE, AP_CONFIG, AP_TRACKING_STATUS } from '../core/constants.js';
|
|
3
3
|
import { getConfig, _ZAP } from '../core/state.js';
|
|
4
4
|
import { Console, logFailure } from '../core/logger.js';
|
|
@@ -22,6 +22,12 @@ import { noteDebugActivity } from '../core/debug.js';
|
|
|
22
22
|
*/
|
|
23
23
|
/** How long the page must be still before a scroll burst counts as one finished gesture. */
|
|
24
24
|
const SCROLL_IDLE_MS = 150;
|
|
25
|
+
/**
|
|
26
|
+
* How much of the viewport, each way, an element must cover for its scrolling to be the page's.
|
|
27
|
+
* An app whose layout scrolls a content pane instead of the window (most dashboards do) still
|
|
28
|
+
* gets a scroll map; a dropdown list or a small table scrolling on its own is not the page moving.
|
|
29
|
+
*/
|
|
30
|
+
const PAGE_SCROLLER_SHARE = 0.5;
|
|
25
31
|
/** Clicks closer than this in time and space count as one angry repetition. */
|
|
26
32
|
const RAGE_WINDOW_MS = 1000;
|
|
27
33
|
const RAGE_RADIUS_PX = 30;
|
|
@@ -40,6 +46,10 @@ var scrollStart = 0;
|
|
|
40
46
|
var scrollStartX = 0;
|
|
41
47
|
var scrollStartY = 0;
|
|
42
48
|
var scrollTimer = null;
|
|
49
|
+
/** What the gesture in progress scrolls: null for the window, else the page's content pane. */
|
|
50
|
+
var scrolling = null;
|
|
51
|
+
/** Where each content pane was after its last gesture, as lastX / lastY are for the window. */
|
|
52
|
+
var paneAt = new WeakMap();
|
|
43
53
|
/**
|
|
44
54
|
* Where the page was before the current gesture began.
|
|
45
55
|
*
|
|
@@ -122,7 +132,7 @@ function labelFor(node) {
|
|
|
122
132
|
if (!node) {
|
|
123
133
|
return ''; // no i18n
|
|
124
134
|
}
|
|
125
|
-
var attributes = ['data-ap-label', 'apeventaction', 'aria-label', 'name', 'id', 'title']; // no i18n
|
|
135
|
+
var attributes = ['data-ap-label', 'apeventaction', 'data-apeventaction', 'aria-label', 'name', 'id', 'title']; // no i18n
|
|
126
136
|
for (var i = 0; i < attributes.length; i++) {
|
|
127
137
|
var value = node.getAttribute ? node.getAttribute(attributes[i]) : null;
|
|
128
138
|
if (!isEmpty(value)) {
|
|
@@ -278,14 +288,57 @@ function watchForDeadClick(record, target) {
|
|
|
278
288
|
}
|
|
279
289
|
}, DEAD_CLICK_MS);
|
|
280
290
|
}
|
|
281
|
-
|
|
291
|
+
/**
|
|
292
|
+
* What a scroll event moved, as a gesture counts it: null for the window (the event's target is
|
|
293
|
+
* the document), the element when it is big enough to be the page's own scrolling, and undefined
|
|
294
|
+
* for anything smaller, which is not recorded.
|
|
295
|
+
*/
|
|
296
|
+
function scrollerOf(target) {
|
|
297
|
+
var doc = document;
|
|
298
|
+
// the window and the document are not elements: either is the page itself scrolling
|
|
299
|
+
if (!target || target.nodeType !== 1 || target === doc.documentElement || target === doc.body) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
var el = target;
|
|
303
|
+
var big = el.clientHeight >= (window.innerHeight || 0) * PAGE_SCROLLER_SHARE
|
|
304
|
+
&& el.clientWidth >= viewportWidth() * PAGE_SCROLLER_SHARE;
|
|
305
|
+
return big ? el : undefined;
|
|
306
|
+
}
|
|
307
|
+
/** Where a scroller is now. */
|
|
308
|
+
function positionOf(scroller) {
|
|
309
|
+
return scroller === null
|
|
310
|
+
? { x: Math.round(window.scrollX || window.pageXOffset || 0), y: Math.round(window.scrollY || window.pageYOffset || 0) }
|
|
311
|
+
: { x: Math.round(scroller.scrollLeft || 0), y: Math.round(scroller.scrollTop || 0) };
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Where a scroller was before this gesture: what the last one left. A content pane seen for the
|
|
315
|
+
* first time is taken to have been at its top, which is where a pane starts.
|
|
316
|
+
*/
|
|
317
|
+
function startOf(scroller) {
|
|
318
|
+
if (scroller === null) {
|
|
319
|
+
return { x: lastX, y: lastY };
|
|
320
|
+
}
|
|
321
|
+
return paneAt.get(scroller) || { x: 0, y: 0 };
|
|
322
|
+
}
|
|
323
|
+
function onScroll(event) {
|
|
282
324
|
if (!canTrackHeatmap('heatmap') || !underCap()) { // no i18n
|
|
283
325
|
return;
|
|
284
326
|
}
|
|
327
|
+
var scroller = scrollerOf(event ? event.target : null);
|
|
328
|
+
if (scroller === undefined) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (scrollTimer !== null && scroller !== scrolling) {
|
|
332
|
+
// another scroller started moving: the gesture on the first one is over
|
|
333
|
+
clearTimeout(scrollTimer);
|
|
334
|
+
endScrollGesture();
|
|
335
|
+
}
|
|
285
336
|
if (scrollTimer === null) {
|
|
337
|
+
scrolling = scroller;
|
|
338
|
+
var start = startOf(scroller);
|
|
286
339
|
scrollStart = nowMs();
|
|
287
|
-
scrollStartX =
|
|
288
|
-
scrollStartY =
|
|
340
|
+
scrollStartX = start.x;
|
|
341
|
+
scrollStartY = start.y;
|
|
289
342
|
}
|
|
290
343
|
else {
|
|
291
344
|
clearTimeout(scrollTimer);
|
|
@@ -295,13 +348,21 @@ function onScroll() {
|
|
|
295
348
|
/** One record for the whole burst, once the page has been still for SCROLL_IDLE_MS. */
|
|
296
349
|
function endScrollGesture() {
|
|
297
350
|
scrollTimer = null;
|
|
351
|
+
var scroller = scrolling;
|
|
352
|
+
scrolling = null;
|
|
298
353
|
try {
|
|
299
|
-
var
|
|
300
|
-
var
|
|
354
|
+
var end = positionOf(scroller);
|
|
355
|
+
var endX = end.x;
|
|
356
|
+
var endY = end.y;
|
|
301
357
|
var dx = endX - scrollStartX;
|
|
302
358
|
var dy = endY - scrollStartY;
|
|
303
|
-
|
|
304
|
-
|
|
359
|
+
if (scroller === null) {
|
|
360
|
+
lastX = endX;
|
|
361
|
+
lastY = endY;
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
paneAt.set(scroller, end);
|
|
365
|
+
}
|
|
305
366
|
if (dx === 0 && dy === 0) {
|
|
306
367
|
return;
|
|
307
368
|
}
|
|
@@ -310,8 +371,14 @@ function endScrollGesture() {
|
|
|
310
371
|
var direction = Math.abs(dy) >= Math.abs(dx)
|
|
311
372
|
? (dy > 0 ? 'down-scroll' : 'up-scroll') // no i18n
|
|
312
373
|
: (dx > 0 ? 'right-scroll' : 'left-scroll'); // no i18n
|
|
313
|
-
|
|
314
|
-
|
|
374
|
+
// the depth is of what scrolled: the document, or the content pane and its own content
|
|
375
|
+
var height = (scroller === null ? contentHeight() : scroller.scrollHeight) || 1;
|
|
376
|
+
var visible = scroller === null ? (window.innerHeight || 0) : scroller.clientHeight;
|
|
377
|
+
store(Object.assign(common(), scroller === null ? {} : {
|
|
378
|
+
content_height: scroller.scrollHeight,
|
|
379
|
+
scroll_offset_x: endX,
|
|
380
|
+
scroll_offset_y: endY,
|
|
381
|
+
}, {
|
|
315
382
|
// the server accepts only event|default|buttonclick here; what kind of movement it
|
|
316
383
|
// was belongs in gesture_type. input_type is left off rather than invented: a wheel
|
|
317
384
|
// carries no pointer type, and the intended vocabulary has no value for "unknown"
|
|
@@ -324,7 +391,7 @@ function endScrollGesture() {
|
|
|
324
391
|
coordinate_y: endY,
|
|
325
392
|
normalized_x: 0,
|
|
326
393
|
// how far down the page the gesture left them, which is what a scroll map reads
|
|
327
|
-
normalized_y: fraction(endY +
|
|
394
|
+
normalized_y: fraction(endY + visible, height),
|
|
328
395
|
velocity: Math.round((distance / duration) * 1000),
|
|
329
396
|
is_clickable: 0,
|
|
330
397
|
is_rage_click: 0,
|
|
@@ -336,7 +403,7 @@ function endScrollGesture() {
|
|
|
336
403
|
}
|
|
337
404
|
}
|
|
338
405
|
/** Turns capture on or off. Listeners are passive, so they never delay a click or a scroll. */
|
|
339
|
-
function
|
|
406
|
+
function trackHeatmap(status) {
|
|
340
407
|
var wanted = typeof status === 'boolean' ? status : true; // no i18n
|
|
341
408
|
if (wanted === installed) {
|
|
342
409
|
return;
|
|
@@ -353,10 +420,13 @@ function enableHeatmap(status) {
|
|
|
353
420
|
}
|
|
354
421
|
window.removeEventListener('pointerdown', onPointerDown, true); // no i18n
|
|
355
422
|
window.removeEventListener('scroll', onScroll, true); // no i18n
|
|
423
|
+
// a gesture still settling when capture stops (a single-page app leaving a heatmap page) is
|
|
424
|
+
// recorded as it stands, not dropped: it was the visitor's last scroll on that page
|
|
356
425
|
if (scrollTimer !== null) {
|
|
357
426
|
clearTimeout(scrollTimer);
|
|
358
|
-
|
|
427
|
+
endScrollGesture();
|
|
359
428
|
}
|
|
429
|
+
scrolling = null;
|
|
360
430
|
installed = false;
|
|
361
431
|
Console.log('apptics.heatmap: capture stopped'); // no i18n
|
|
362
432
|
}
|
|
@@ -366,9 +436,10 @@ function resetHeatmapSession() {
|
|
|
366
436
|
recentClicks = [];
|
|
367
437
|
lastX = 0;
|
|
368
438
|
lastY = 0;
|
|
439
|
+
paneAt = new WeakMap();
|
|
369
440
|
}
|
|
370
441
|
// init() and reset() drive capture through these, so neither has to import this module
|
|
371
|
-
hooks.
|
|
442
|
+
hooks.trackHeatmap = trackHeatmap;
|
|
372
443
|
hooks.resetHeatmap = resetHeatmapSession;
|
|
373
444
|
|
|
374
|
-
export {
|
|
445
|
+
export { resetHeatmapSession, trackHeatmap };
|