@openreplay/tracker 5.0.2 → 6.0.1-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 +25 -1
- package/cjs/app/index.d.ts +3 -0
- package/cjs/app/index.js +4 -3
- package/cjs/app/messages.gen.d.ts +6 -1
- package/cjs/app/messages.gen.js +56 -5
- package/cjs/app/nodes.d.ts +1 -0
- package/cjs/app/nodes.js +3 -0
- package/cjs/app/observer/observer.js +7 -1
- package/cjs/app/observer/top_observer.js +4 -0
- package/cjs/app/ticker.d.ts +6 -0
- package/cjs/app/ticker.js +6 -0
- package/cjs/common/messages.gen.d.ts +46 -5
- package/cjs/index.d.ts +2 -0
- package/cjs/index.js +4 -2
- package/cjs/modules/img.js +1 -1
- package/cjs/modules/input.d.ts +2 -2
- package/cjs/modules/input.js +61 -39
- package/cjs/modules/mouse.d.ts +23 -1
- package/cjs/modules/mouse.js +43 -9
- package/cjs/modules/network.d.ts +1 -1
- package/cjs/modules/network.js +81 -10
- package/cjs/modules/selection.d.ts +7 -0
- package/cjs/modules/selection.js +37 -0
- package/cjs/modules/timing.js +3 -1
- package/cjs/utils.d.ts +2 -0
- package/cjs/utils.js +20 -1
- package/lib/app/index.d.ts +3 -0
- package/lib/app/index.js +4 -3
- package/lib/app/messages.gen.d.ts +6 -1
- package/lib/app/messages.gen.js +48 -2
- package/lib/app/nodes.d.ts +1 -0
- package/lib/app/nodes.js +3 -0
- package/lib/app/observer/observer.js +8 -2
- package/lib/app/observer/top_observer.js +5 -1
- package/lib/app/ticker.d.ts +6 -0
- package/lib/app/ticker.js +6 -0
- package/lib/common/messages.gen.d.ts +46 -5
- package/lib/common/tsconfig.tsbuildinfo +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +4 -2
- package/lib/modules/img.js +1 -1
- package/lib/modules/input.d.ts +2 -2
- package/lib/modules/input.js +63 -41
- package/lib/modules/mouse.d.ts +23 -1
- package/lib/modules/mouse.js +45 -11
- package/lib/modules/network.d.ts +1 -1
- package/lib/modules/network.js +81 -10
- package/lib/modules/selection.d.ts +7 -0
- package/lib/modules/selection.js +35 -0
- package/lib/modules/timing.js +3 -1
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +17 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
# 6.0.1
|
|
2
|
+
|
|
3
|
+
- fix webworker writer re-init request
|
|
4
|
+
- remove useless logs
|
|
5
|
+
- tune mouse thrashing detection
|
|
6
|
+
- fix iframe handling
|
|
7
|
+
|
|
8
|
+
# 6.0.0
|
|
9
|
+
|
|
10
|
+
**(Compatible with OpenReplay v1.11.0+ only)**
|
|
11
|
+
|
|
12
|
+
- **[breaking]:** Capture mouse thrashing, input hesitation+duration, click hesitation
|
|
13
|
+
- Capture DOM node drop event (>30% nodes removed)
|
|
14
|
+
- Capture iframe network requests
|
|
15
|
+
- Detect cached requests to img, css and js resources; send transferred size
|
|
16
|
+
- added `{ mouse: { disableClickmaps: boolean } }` to disable calculating el. selectors
|
|
17
|
+
- added `{ mouse: { minSelectorDepth?: number; nthThreshold?: number; maxOptimiseTries?: number }` for selector finding optimizations
|
|
18
|
+
|
|
19
|
+
## 5.0.2
|
|
20
|
+
|
|
21
|
+
- fixed inline css loading in specific cases when assets gets around min flush size
|
|
22
|
+
|
|
1
23
|
## 5.0.1
|
|
2
24
|
|
|
3
25
|
- Re-init worker after device sleep/hybernation
|
|
@@ -6,12 +28,14 @@
|
|
|
6
28
|
|
|
7
29
|
## 5.0.0
|
|
8
30
|
|
|
31
|
+
**(Compatible with OpenReplay v1.10.0+ only)**
|
|
32
|
+
|
|
33
|
+
- **[breaking]:** string dictionary to reduce session size
|
|
9
34
|
- Added "tel" to supported input types
|
|
10
35
|
- Added `{ withCurrentTime: true }` to `tracker.getSessionURL` method which will return sessionURL with current session's timestamp
|
|
11
36
|
- Added Network module that captures fetch/xhr by default (with no plugin required)
|
|
12
37
|
- Use `timeOrigin()` instead of `performance.timing.navigationStart` in ResourceTiming messages
|
|
13
38
|
- Added app restart when service worker died after inactivity (mobile safari)
|
|
14
|
-
- **[breaking]** string dictionary to reduce session size
|
|
15
39
|
|
|
16
40
|
## 4.1.8
|
|
17
41
|
|
package/cjs/app/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type { Options as ObserverOptions } from './observer/top_observer.js';
|
|
|
9
9
|
import type { Options as SanitizerOptions } from './sanitizer.js';
|
|
10
10
|
import type { Options as LoggerOptions } from './logger.js';
|
|
11
11
|
import type { Options as SessOptions } from './session.js';
|
|
12
|
+
import type { Options as NetworkOptions } from '../modules/network.js';
|
|
12
13
|
import type { Options as WebworkerOptions } from '../common/interaction.js';
|
|
13
14
|
export interface StartOptions {
|
|
14
15
|
userID?: string;
|
|
@@ -50,6 +51,7 @@ type AppOptions = {
|
|
|
50
51
|
localStorage: Storage | null;
|
|
51
52
|
sessionStorage: Storage | null;
|
|
52
53
|
onStart?: StartCallback;
|
|
54
|
+
network?: NetworkOptions;
|
|
53
55
|
} & WebworkerOptions & SessOptions;
|
|
54
56
|
export type Options = AppOptions & ObserverOptions & SanitizerOptions;
|
|
55
57
|
export declare const DEFAULT_INGEST_POINT = "https://api.openreplay.com/ingest";
|
|
@@ -69,6 +71,7 @@ export default class App {
|
|
|
69
71
|
private readonly stopCallbacks;
|
|
70
72
|
private readonly commitCallbacks;
|
|
71
73
|
private readonly options;
|
|
74
|
+
readonly networkOptions?: NetworkOptions;
|
|
72
75
|
private readonly revID;
|
|
73
76
|
private activityState;
|
|
74
77
|
private readonly version;
|
package/cjs/app/index.js
CHANGED
|
@@ -33,10 +33,11 @@ class App {
|
|
|
33
33
|
this.stopCallbacks = [];
|
|
34
34
|
this.commitCallbacks = [];
|
|
35
35
|
this.activityState = ActivityState.NotActive;
|
|
36
|
-
this.version = '
|
|
36
|
+
this.version = '6.0.1-beta.1'; // TODO: version compatability check inside each plugin.
|
|
37
37
|
this._usingOldFetchPlugin = false;
|
|
38
38
|
this.delay = 0;
|
|
39
39
|
this.projectKey = projectKey;
|
|
40
|
+
this.networkOptions = options.network;
|
|
40
41
|
this.options = Object.assign({
|
|
41
42
|
revID: '',
|
|
42
43
|
node_id: '__openreplay_id',
|
|
@@ -72,12 +73,12 @@ class App {
|
|
|
72
73
|
Object.entries(metadata).forEach(([key, value]) => this.send((0, messages_gen_js_1.Metadata)(key, value)));
|
|
73
74
|
}
|
|
74
75
|
});
|
|
75
|
-
// @
|
|
76
|
+
// @deprecated (use sessionHash on start instead)
|
|
76
77
|
if (sessionToken != null) {
|
|
77
78
|
this.session.applySessionHash(sessionToken);
|
|
78
79
|
}
|
|
79
80
|
try {
|
|
80
|
-
this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i"}authorise(t){this.token=t,this.busy||this.sendNext()}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}sendNext(){const t=this.queue.shift();t?this.sendBatch(t):this.busy=!1}retry(t){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`):(this.attemptsCount++,setTimeout(()=>this.sendBatch(t),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t){this.busy=!0,fetch(this.ingestURL,{body:t,method:"POST",headers:{Authorization:"Bearer "+this.token},keepalive:t.length<65536}).then(i=>{if(401===i.status)return this.busy=!1,void this.onUnauthorised();i.status>=400?this.retry(t):(this.attemptsCount=0,this.sendNext())}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0,this.token=null}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,
|
|
81
|
+
this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i"}authorise(t){this.token=t,this.busy||this.sendNext()}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}sendNext(){const t=this.queue.shift();t?this.sendBatch(t):this.busy=!1}retry(t){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`):(this.attemptsCount++,setTimeout(()=>this.sendBatch(t),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t){this.busy=!0,fetch(this.ingestURL,{body:t,method:"POST",headers:{Authorization:"Bearer "+this.token},keepalive:t.length<65536}).then(i=>{if(401===i.status)return this.busy=!1,void this.onUnauthorised();i.status>=400?this.retry(t):(this.attemptsCount=0,this.sendNext())}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0,this.token=null}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,h=0,r=0;r!==i;){if(n=t.charCodeAt(r),r+=1,n>=55296&&n<=56319){if(r===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(h=t.charCodeAt(r),!(h>=56320&&h<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+h-56320+65536,r+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class s extends class{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}get isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 21:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.string(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 50:return this.uint(t[1])&&this.string(t[2]);case 51:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 57:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 58:return this.int(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 79:return this.string(t[1])&&this.string(t[2]);case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2]);case 112:return this.uint(t[1])&&this.string(t[2])&&this.boolean(t[3])&&this.string(t[4])&&this.int(t[5])&&this.int(t[6]);case 113:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3]);case 114:case 115:return this.uint(t[1]);case 116:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8])&&this.uint(t[9])&&this.boolean(t[10])}}}class e{constructor(){this.idx=1,this.backDict={}}getKey(t){let i=!1;return this.backDict[t]||(i=!0,this.backDict[t]=this.idx++),[this.backDict[t],i]}}class n{constructor(t,i,n,h){this.pageNo=t,this.timestamp=i,this.url=n,this.onBatch=h,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.strDict=new e,this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty)return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(t),this.writeFields(t),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}applyDict(t){const[i,s]=this.strDict.getKey(t);return s&&this.writeMessage([50,i,t]),i}writeMessage(t){0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),12===t[0]&&(t=[51,t[1],this.applyDict(t[2]),this.applyDict(t[3])]),this.writeWithSize(t)||(this.finaliseBatch(),this.writeWithSize(t)||(this.encoder=new s(this.beaconSizeLimit),this.prepare(),this.writeWithSize(t)?this.finaliseBatch():console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder=new s(this.beaconSize),this.prepare()))}finaliseBatch(){this.isEmpty||(this.onBatch(this.encoder.flush()),this.prepare())}clean(){this.encoder.reset()}}var h;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(h||(h={}));let r=null,u=null;function a(){u&&u.finaliseBatch()}function c(){h.Stopping,null!==l&&(clearInterval(l),l=null),u&&(u.clean(),u=null),r&&(r.clean(),r=null),h.NotActive}function o(){postMessage("restart"),c()}h.NotActive;let g,l=null;self.onmessage=({data:i})=>{if(null!=i){if("stop"===i)return a(),void c();if(!Array.isArray(i))return"start"===i.type?(h.Starting,r=new t(i.ingestPoint,()=>{o()},t=>{!function(t){postMessage({type:"failure",reason:t}),c()}(t)},i.connAttemptCount,i.connAttemptGap),u=new n(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===l&&(l=setInterval(a,1e4)),h.Active):"auth"===i.type?r?u?(r.authorise(i.token),void(i.beaconSizeLimit&&u.setBeaconSizeLimit(i.beaconSizeLimit))):(console.debug("WebWorker: writer not initialised. Received auth."),void o()):(console.debug("WebWorker: sender not initialised. Received auth."),void o()):void 0;if(null!==u){const t=u;i.forEach(i=>{55===i[0]&&(i[1]?g=setTimeout(()=>o(),18e5):clearTimeout(g)),t.writeMessage(i)})}u||(postMessage("not_init"),o())}else a()};'], { type: 'text/javascript' })));
|
|
81
82
|
this.worker.onerror = (e) => {
|
|
82
83
|
this._debug('webworker_error', e);
|
|
83
84
|
};
|
|
@@ -39,7 +39,7 @@ export declare function GraphQL(operationKind: string, operationName: string, va
|
|
|
39
39
|
export declare function PerformanceTrack(frames: number, ticks: number, totalJSHeapSize: number, usedJSHeapSize: number): Messages.PerformanceTrack;
|
|
40
40
|
export declare function StringDict(key: number, value: string): Messages.StringDict;
|
|
41
41
|
export declare function SetNodeAttributeDict(id: number, nameKey: number, valueKey: number): Messages.SetNodeAttributeDict;
|
|
42
|
-
export declare function
|
|
42
|
+
export declare function ResourceTimingDeprecated(timestamp: number, duration: number, ttfb: number, headerSize: number, encodedBodySize: number, decodedBodySize: number, url: string, initiator: string): Messages.ResourceTimingDeprecated;
|
|
43
43
|
export declare function ConnectionInformation(downlink: number, type: string): Messages.ConnectionInformation;
|
|
44
44
|
export declare function SetPageVisibility(hidden: boolean): Messages.SetPageVisibility;
|
|
45
45
|
export declare function LoadFontFace(parentID: number, family: string, source: string, descriptors: string): Messages.LoadFontFace;
|
|
@@ -61,3 +61,8 @@ export declare function JSException(name: string, message: string, payload: stri
|
|
|
61
61
|
export declare function Zustand(mutation: string, state: string): Messages.Zustand;
|
|
62
62
|
export declare function BatchMetadata(version: number, pageNo: number, firstIndex: number, timestamp: number, location: string): Messages.BatchMetadata;
|
|
63
63
|
export declare function PartitionedMessage(partNo: number, partTotal: number): Messages.PartitionedMessage;
|
|
64
|
+
export declare function InputChange(id: number, value: string, valueMasked: boolean, label: string, hesitationTime: number, inputDuration: number): Messages.InputChange;
|
|
65
|
+
export declare function SelectionChange(selectionStart: number, selectionEnd: number, selection: string): Messages.SelectionChange;
|
|
66
|
+
export declare function MouseThrashing(timestamp: number): Messages.MouseThrashing;
|
|
67
|
+
export declare function UnbindNodes(totalRemovedPercent: number): Messages.UnbindNodes;
|
|
68
|
+
export declare function ResourceTiming(timestamp: number, duration: number, ttfb: number, headerSize: number, encodedBodySize: number, decodedBodySize: number, url: string, initiator: string, transferredSize: number, cached: boolean): Messages.ResourceTiming;
|
package/cjs/app/messages.gen.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Auto-generated, do not edit
|
|
3
3
|
/* eslint-disable */
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.CSSInsertRuleURLBased = exports.CustomIssue = exports.TechnicalInfo = exports.SetCSSDataURLBased = exports.SetNodeAttributeURLBased = exports.LongTask = exports.SetNodeFocus = exports.LoadFontFace = exports.SetPageVisibility = exports.ConnectionInformation = exports.
|
|
6
|
-
exports.PartitionedMessage = exports.BatchMetadata = exports.Zustand = exports.JSException = exports.AdoptedSSRemoveOwner = exports.AdoptedSSAddOwner = exports.AdoptedSSDeleteRule = exports.AdoptedSSInsertRuleURLBased = exports.AdoptedSSReplaceURLBased = exports.CreateIFrameDocument = exports.MouseClick = void 0;
|
|
5
|
+
exports.CSSInsertRuleURLBased = exports.CustomIssue = exports.TechnicalInfo = exports.SetCSSDataURLBased = exports.SetNodeAttributeURLBased = exports.LongTask = exports.SetNodeFocus = exports.LoadFontFace = exports.SetPageVisibility = exports.ConnectionInformation = exports.ResourceTimingDeprecated = exports.SetNodeAttributeDict = exports.StringDict = exports.PerformanceTrack = exports.GraphQL = exports.NgRx = exports.MobX = exports.Vuex = exports.Redux = exports.StateAction = exports.OTable = exports.Profiler = exports.Fetch = exports.CSSDeleteRule = exports.CSSInsertRule = exports.Metadata = exports.UserAnonymousID = exports.UserID = exports.CustomEvent = exports.PageRenderTiming = exports.PageLoadTiming = exports.ConsoleLog = exports.NetworkRequest = exports.MouseMove = exports.SetInputChecked = exports.SetInputValue = exports.SetInputTarget = exports.SetNodeScroll = exports.SetNodeData = exports.RemoveNodeAttribute = exports.SetNodeAttribute = exports.RemoveNode = exports.MoveNode = exports.CreateTextNode = exports.CreateElementNode = exports.CreateDocument = exports.SetViewportScroll = exports.SetViewportSize = exports.SetPageLocation = exports.Timestamp = void 0;
|
|
6
|
+
exports.ResourceTiming = exports.UnbindNodes = exports.MouseThrashing = exports.SelectionChange = exports.InputChange = exports.PartitionedMessage = exports.BatchMetadata = exports.Zustand = exports.JSException = exports.AdoptedSSRemoveOwner = exports.AdoptedSSAddOwner = exports.AdoptedSSDeleteRule = exports.AdoptedSSInsertRuleURLBased = exports.AdoptedSSReplaceURLBased = exports.CreateIFrameDocument = exports.MouseClick = void 0;
|
|
7
7
|
function Timestamp(timestamp) {
|
|
8
8
|
return [
|
|
9
9
|
0 /* Messages.Type.Timestamp */,
|
|
@@ -347,9 +347,9 @@ function SetNodeAttributeDict(id, nameKey, valueKey) {
|
|
|
347
347
|
];
|
|
348
348
|
}
|
|
349
349
|
exports.SetNodeAttributeDict = SetNodeAttributeDict;
|
|
350
|
-
function
|
|
350
|
+
function ResourceTimingDeprecated(timestamp, duration, ttfb, headerSize, encodedBodySize, decodedBodySize, url, initiator) {
|
|
351
351
|
return [
|
|
352
|
-
53 /* Messages.Type.
|
|
352
|
+
53 /* Messages.Type.ResourceTimingDeprecated */,
|
|
353
353
|
timestamp,
|
|
354
354
|
duration,
|
|
355
355
|
ttfb,
|
|
@@ -360,7 +360,7 @@ function ResourceTiming(timestamp, duration, ttfb, headerSize, encodedBodySize,
|
|
|
360
360
|
initiator,
|
|
361
361
|
];
|
|
362
362
|
}
|
|
363
|
-
exports.
|
|
363
|
+
exports.ResourceTimingDeprecated = ResourceTimingDeprecated;
|
|
364
364
|
function ConnectionInformation(downlink, type) {
|
|
365
365
|
return [
|
|
366
366
|
54 /* Messages.Type.ConnectionInformation */,
|
|
@@ -549,3 +549,54 @@ function PartitionedMessage(partNo, partTotal) {
|
|
|
549
549
|
];
|
|
550
550
|
}
|
|
551
551
|
exports.PartitionedMessage = PartitionedMessage;
|
|
552
|
+
function InputChange(id, value, valueMasked, label, hesitationTime, inputDuration) {
|
|
553
|
+
return [
|
|
554
|
+
112 /* Messages.Type.InputChange */,
|
|
555
|
+
id,
|
|
556
|
+
value,
|
|
557
|
+
valueMasked,
|
|
558
|
+
label,
|
|
559
|
+
hesitationTime,
|
|
560
|
+
inputDuration,
|
|
561
|
+
];
|
|
562
|
+
}
|
|
563
|
+
exports.InputChange = InputChange;
|
|
564
|
+
function SelectionChange(selectionStart, selectionEnd, selection) {
|
|
565
|
+
return [
|
|
566
|
+
113 /* Messages.Type.SelectionChange */,
|
|
567
|
+
selectionStart,
|
|
568
|
+
selectionEnd,
|
|
569
|
+
selection,
|
|
570
|
+
];
|
|
571
|
+
}
|
|
572
|
+
exports.SelectionChange = SelectionChange;
|
|
573
|
+
function MouseThrashing(timestamp) {
|
|
574
|
+
return [
|
|
575
|
+
114 /* Messages.Type.MouseThrashing */,
|
|
576
|
+
timestamp,
|
|
577
|
+
];
|
|
578
|
+
}
|
|
579
|
+
exports.MouseThrashing = MouseThrashing;
|
|
580
|
+
function UnbindNodes(totalRemovedPercent) {
|
|
581
|
+
return [
|
|
582
|
+
115 /* Messages.Type.UnbindNodes */,
|
|
583
|
+
totalRemovedPercent,
|
|
584
|
+
];
|
|
585
|
+
}
|
|
586
|
+
exports.UnbindNodes = UnbindNodes;
|
|
587
|
+
function ResourceTiming(timestamp, duration, ttfb, headerSize, encodedBodySize, decodedBodySize, url, initiator, transferredSize, cached) {
|
|
588
|
+
return [
|
|
589
|
+
116 /* Messages.Type.ResourceTiming */,
|
|
590
|
+
timestamp,
|
|
591
|
+
duration,
|
|
592
|
+
ttfb,
|
|
593
|
+
headerSize,
|
|
594
|
+
encodedBodySize,
|
|
595
|
+
decodedBodySize,
|
|
596
|
+
url,
|
|
597
|
+
initiator,
|
|
598
|
+
transferredSize,
|
|
599
|
+
cached,
|
|
600
|
+
];
|
|
601
|
+
}
|
|
602
|
+
exports.ResourceTiming = ResourceTiming;
|
package/cjs/app/nodes.d.ts
CHANGED
package/cjs/app/nodes.js
CHANGED
|
@@ -193,10 +193,16 @@ class Observer {
|
|
|
193
193
|
},
|
|
194
194
|
// @ts-ignore
|
|
195
195
|
false);
|
|
196
|
+
let removed = 0;
|
|
197
|
+
const totalBeforeRemove = this.app.nodes.getNodeCount();
|
|
196
198
|
while (walker.nextNode()) {
|
|
199
|
+
removed += 1;
|
|
197
200
|
this.app.nodes.unregisterNode(walker.currentNode);
|
|
198
201
|
}
|
|
199
|
-
|
|
202
|
+
const removedPercent = Math.floor((removed / totalBeforeRemove) * 100);
|
|
203
|
+
if (removedPercent > 30) {
|
|
204
|
+
this.app.send((0, messages_gen_js_1.UnbindNodes)(removedPercent));
|
|
205
|
+
}
|
|
200
206
|
}
|
|
201
207
|
}
|
|
202
208
|
// A top-consumption function on the infinite lists test. (~1% of performance resources)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const observer_js_1 = require("./observer.js");
|
|
4
4
|
const guards_js_1 = require("../guards.js");
|
|
5
|
+
const network_js_1 = require("../../modules/network.js");
|
|
5
6
|
const iframe_observer_js_1 = require("./iframe_observer.js");
|
|
6
7
|
const shadow_root_observer_js_1 = require("./shadow_root_observer.js");
|
|
7
8
|
const iframe_offsets_js_1 = require("./iframe_offsets.js");
|
|
@@ -51,6 +52,8 @@ class TopObserver extends observer_js_1.default {
|
|
|
51
52
|
//log
|
|
52
53
|
return;
|
|
53
54
|
}
|
|
55
|
+
if (!(0, utils_js_1.canAccessIframe)(iframe))
|
|
56
|
+
return;
|
|
54
57
|
const currentWin = iframe.contentWindow;
|
|
55
58
|
const currentDoc = iframe.contentDocument;
|
|
56
59
|
if (currentDoc && currentDoc !== doc) {
|
|
@@ -67,6 +70,7 @@ class TopObserver extends observer_js_1.default {
|
|
|
67
70
|
//TODO: more explicit logic
|
|
68
71
|
) {
|
|
69
72
|
this.contextsSet.add(currentWin);
|
|
73
|
+
(0, network_js_1.default)(this.app, this.app.networkOptions, currentWin);
|
|
70
74
|
//@ts-ignore https://github.com/microsoft/TypeScript/issues/41684
|
|
71
75
|
this.contextCallbacks.forEach((cb) => cb(currentWin));
|
|
72
76
|
}
|
package/cjs/app/ticker.d.ts
CHANGED
|
@@ -5,6 +5,12 @@ export default class Ticker {
|
|
|
5
5
|
private timer;
|
|
6
6
|
private readonly callbacks;
|
|
7
7
|
constructor(app: App);
|
|
8
|
+
/**
|
|
9
|
+
* @param {Callback} callback - repeated cb
|
|
10
|
+
* @param {number} n - number of turn skips; ticker have a 30 ms cycle
|
|
11
|
+
* @param {boolean} useSafe - using safe wrapper to check if app is active
|
|
12
|
+
* @param {object} thisArg - link to <this>
|
|
13
|
+
* */
|
|
8
14
|
attach(callback: Callback, n?: number, useSafe?: boolean, thisArg?: any): void;
|
|
9
15
|
start(): void;
|
|
10
16
|
stop(): void;
|
package/cjs/app/ticker.js
CHANGED
|
@@ -15,6 +15,12 @@ class Ticker {
|
|
|
15
15
|
this.timer = null;
|
|
16
16
|
this.callbacks = [];
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* @param {Callback} callback - repeated cb
|
|
20
|
+
* @param {number} n - number of turn skips; ticker have a 30 ms cycle
|
|
21
|
+
* @param {boolean} useSafe - using safe wrapper to check if app is active
|
|
22
|
+
* @param {object} thisArg - link to <this>
|
|
23
|
+
* */
|
|
18
24
|
attach(callback, n = 0, useSafe = true, thisArg) {
|
|
19
25
|
if (thisArg) {
|
|
20
26
|
callback = callback.bind(thisArg);
|
|
@@ -38,7 +38,7 @@ export declare const enum Type {
|
|
|
38
38
|
PerformanceTrack = 49,
|
|
39
39
|
StringDict = 50,
|
|
40
40
|
SetNodeAttributeDict = 51,
|
|
41
|
-
|
|
41
|
+
ResourceTimingDeprecated = 53,
|
|
42
42
|
ConnectionInformation = 54,
|
|
43
43
|
SetPageVisibility = 55,
|
|
44
44
|
LoadFontFace = 57,
|
|
@@ -59,7 +59,12 @@ export declare const enum Type {
|
|
|
59
59
|
JSException = 78,
|
|
60
60
|
Zustand = 79,
|
|
61
61
|
BatchMetadata = 81,
|
|
62
|
-
PartitionedMessage = 82
|
|
62
|
+
PartitionedMessage = 82,
|
|
63
|
+
InputChange = 112,
|
|
64
|
+
SelectionChange = 113,
|
|
65
|
+
MouseThrashing = 114,
|
|
66
|
+
UnbindNodes = 115,
|
|
67
|
+
ResourceTiming = 116
|
|
63
68
|
}
|
|
64
69
|
export type Timestamp = [
|
|
65
70
|
Type.Timestamp,
|
|
@@ -287,8 +292,8 @@ export type SetNodeAttributeDict = [
|
|
|
287
292
|
number,
|
|
288
293
|
number
|
|
289
294
|
];
|
|
290
|
-
export type
|
|
291
|
-
Type.
|
|
295
|
+
export type ResourceTimingDeprecated = [
|
|
296
|
+
Type.ResourceTimingDeprecated,
|
|
292
297
|
number,
|
|
293
298
|
number,
|
|
294
299
|
number,
|
|
@@ -423,5 +428,41 @@ export type PartitionedMessage = [
|
|
|
423
428
|
number,
|
|
424
429
|
number
|
|
425
430
|
];
|
|
426
|
-
type
|
|
431
|
+
export type InputChange = [
|
|
432
|
+
Type.InputChange,
|
|
433
|
+
number,
|
|
434
|
+
string,
|
|
435
|
+
boolean,
|
|
436
|
+
string,
|
|
437
|
+
number,
|
|
438
|
+
number
|
|
439
|
+
];
|
|
440
|
+
export type SelectionChange = [
|
|
441
|
+
Type.SelectionChange,
|
|
442
|
+
number,
|
|
443
|
+
number,
|
|
444
|
+
string
|
|
445
|
+
];
|
|
446
|
+
export type MouseThrashing = [
|
|
447
|
+
Type.MouseThrashing,
|
|
448
|
+
number
|
|
449
|
+
];
|
|
450
|
+
export type UnbindNodes = [
|
|
451
|
+
Type.UnbindNodes,
|
|
452
|
+
number
|
|
453
|
+
];
|
|
454
|
+
export type ResourceTiming = [
|
|
455
|
+
Type.ResourceTiming,
|
|
456
|
+
number,
|
|
457
|
+
number,
|
|
458
|
+
number,
|
|
459
|
+
number,
|
|
460
|
+
number,
|
|
461
|
+
number,
|
|
462
|
+
string,
|
|
463
|
+
string,
|
|
464
|
+
number,
|
|
465
|
+
boolean
|
|
466
|
+
];
|
|
467
|
+
type Message = Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | NetworkRequest | ConsoleLog | PageLoadTiming | PageRenderTiming | CustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | StringDict | SetNodeAttributeDict | ResourceTimingDeprecated | ConnectionInformation | SetPageVisibility | LoadFontFace | SetNodeFocus | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | JSException | Zustand | BatchMetadata | PartitionedMessage | InputChange | SelectionChange | MouseThrashing | UnbindNodes | ResourceTiming;
|
|
427
468
|
export default Message;
|
package/cjs/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type { Options as InputOptions } from './modules/input.js';
|
|
|
10
10
|
import type { Options as PerformanceOptions } from './modules/performance.js';
|
|
11
11
|
import type { Options as TimingOptions } from './modules/timing.js';
|
|
12
12
|
import type { Options as NetworkOptions } from './modules/network.js';
|
|
13
|
+
import type { MouseHandlerOptions } from './modules/mouse.js';
|
|
13
14
|
import type { StartOptions } from './app/index.js';
|
|
14
15
|
import type { StartPromiseReturn } from './app/index.js';
|
|
15
16
|
export type Options = Partial<AppOptions & ConsoleOptions & ExceptionOptions & InputOptions & PerformanceOptions & TimingOptions> & {
|
|
@@ -19,6 +20,7 @@ export type Options = Partial<AppOptions & ConsoleOptions & ExceptionOptions & I
|
|
|
19
20
|
respectDoNotTrack?: boolean;
|
|
20
21
|
autoResetOnWindowOpen?: boolean;
|
|
21
22
|
network?: NetworkOptions;
|
|
23
|
+
mouse?: MouseHandlerOptions;
|
|
22
24
|
__DISABLE_SECURE_MODE?: boolean;
|
|
23
25
|
};
|
|
24
26
|
export default class API {
|
package/cjs/index.js
CHANGED
|
@@ -24,6 +24,7 @@ const focus_js_1 = require("./modules/focus.js");
|
|
|
24
24
|
const fonts_js_1 = require("./modules/fonts.js");
|
|
25
25
|
const network_js_1 = require("./modules/network.js");
|
|
26
26
|
const constructedStyleSheets_js_1 = require("./modules/constructedStyleSheets.js");
|
|
27
|
+
const selection_js_1 = require("./modules/selection.js");
|
|
27
28
|
const utils_js_1 = require("./utils.js");
|
|
28
29
|
const DOCS_SETUP = '/installation/javascript-sdk';
|
|
29
30
|
function processOptions(obj) {
|
|
@@ -109,13 +110,14 @@ class API {
|
|
|
109
110
|
(0, exception_js_1.default)(app, options);
|
|
110
111
|
(0, img_js_1.default)(app);
|
|
111
112
|
(0, input_js_1.default)(app, options);
|
|
112
|
-
(0, mouse_js_1.default)(app);
|
|
113
|
+
(0, mouse_js_1.default)(app, options.mouse);
|
|
113
114
|
(0, timing_js_1.default)(app, options);
|
|
114
115
|
(0, performance_js_1.default)(app, options);
|
|
115
116
|
(0, scroll_js_1.default)(app);
|
|
116
117
|
(0, focus_js_1.default)(app);
|
|
117
118
|
(0, fonts_js_1.default)(app);
|
|
118
119
|
(0, network_js_1.default)(app, options.network);
|
|
120
|
+
(0, selection_js_1.default)(app);
|
|
119
121
|
window.__OPENREPLAY__ = this;
|
|
120
122
|
if (options.autoResetOnWindowOpen) {
|
|
121
123
|
const wOpen = window.open;
|
|
@@ -140,7 +142,7 @@ class API {
|
|
|
140
142
|
// no-cors issue only with text/plain or not-set Content-Type
|
|
141
143
|
// req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
|
142
144
|
req.send(JSON.stringify({
|
|
143
|
-
trackerVersion: '
|
|
145
|
+
trackerVersion: '6.0.1-beta.1',
|
|
144
146
|
projectKey: options.projectKey,
|
|
145
147
|
doNotTrack,
|
|
146
148
|
// TODO: add precise reason (an exact API missing)
|
package/cjs/modules/img.js
CHANGED
|
@@ -55,7 +55,7 @@ function default_1(app) {
|
|
|
55
55
|
const sendImgError = app.safe(function (img) {
|
|
56
56
|
const resolvedSrc = resolveURL(img.src || ''); // Src type is null sometimes. - is it true?
|
|
57
57
|
if ((0, utils_js_1.isURL)(resolvedSrc)) {
|
|
58
|
-
app.send((0, messages_gen_js_1.ResourceTiming)(app.timestamp(), 0, 0, 0, 0, 0, resolvedSrc, 'img'));
|
|
58
|
+
app.send((0, messages_gen_js_1.ResourceTiming)(app.timestamp(), 0, 0, 0, 0, 0, resolvedSrc, 'img', 0, false));
|
|
59
59
|
}
|
|
60
60
|
});
|
|
61
61
|
const sendImgAttrs = app.safe(function (img) {
|
package/cjs/modules/input.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type App from '../app/index.js';
|
|
2
|
-
type
|
|
3
|
-
export declare function getInputLabel(node:
|
|
2
|
+
type TextFieldElement = HTMLInputElement | HTMLTextAreaElement;
|
|
3
|
+
export declare function getInputLabel(node: TextFieldElement): string;
|
|
4
4
|
export declare const enum InputMode {
|
|
5
5
|
Plain = 0,
|
|
6
6
|
Obscured = 1,
|
package/cjs/modules/input.js
CHANGED
|
@@ -5,7 +5,7 @@ const utils_js_1 = require("../utils.js");
|
|
|
5
5
|
const guards_js_1 = require("../app/guards.js");
|
|
6
6
|
const messages_gen_js_1 = require("../app/messages.gen.js");
|
|
7
7
|
const INPUT_TYPES = ['text', 'password', 'email', 'search', 'number', 'range', 'date', 'tel'];
|
|
8
|
-
function
|
|
8
|
+
function isTextFieldElement(node) {
|
|
9
9
|
if ((0, guards_js_1.hasTag)(node, 'textarea')) {
|
|
10
10
|
return true;
|
|
11
11
|
}
|
|
@@ -14,7 +14,7 @@ function isTextEditable(node) {
|
|
|
14
14
|
}
|
|
15
15
|
return INPUT_TYPES.includes(node.type);
|
|
16
16
|
}
|
|
17
|
-
function
|
|
17
|
+
function isCheckbox(node) {
|
|
18
18
|
if (!(0, guards_js_1.hasTag)(node, 'input')) {
|
|
19
19
|
return false;
|
|
20
20
|
}
|
|
@@ -71,13 +71,7 @@ function default_1(app, opts) {
|
|
|
71
71
|
defaultInputMode: 1 /* InputMode.Obscured */,
|
|
72
72
|
obscureInputDates: false,
|
|
73
73
|
}, opts);
|
|
74
|
-
function
|
|
75
|
-
const label = getInputLabel(node);
|
|
76
|
-
if (label !== '') {
|
|
77
|
-
app.send((0, messages_gen_js_1.SetInputTarget)(id, label));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function sendInputValue(id, node) {
|
|
74
|
+
function getInputValue(id, node) {
|
|
81
75
|
let value = node.value;
|
|
82
76
|
let inputMode = options.defaultInputMode;
|
|
83
77
|
if (node.type === 'password' || app.sanitizer.isHidden(id)) {
|
|
@@ -101,61 +95,89 @@ function default_1(app, opts) {
|
|
|
101
95
|
value = '';
|
|
102
96
|
break;
|
|
103
97
|
}
|
|
98
|
+
return { value, mask };
|
|
99
|
+
}
|
|
100
|
+
function sendInputValue(id, node) {
|
|
101
|
+
const { value, mask } = getInputValue(id, node);
|
|
104
102
|
app.send((0, messages_gen_js_1.SetInputValue)(id, value, mask));
|
|
105
103
|
}
|
|
106
104
|
const inputValues = new Map();
|
|
107
|
-
const
|
|
108
|
-
const registeredTargets = new Set();
|
|
105
|
+
const checkboxValues = new Map();
|
|
109
106
|
app.attachStopCallback(() => {
|
|
110
107
|
inputValues.clear();
|
|
111
|
-
|
|
112
|
-
registeredTargets.clear();
|
|
108
|
+
checkboxValues.clear();
|
|
113
109
|
});
|
|
110
|
+
function trackInputValue(id, node) {
|
|
111
|
+
if (inputValues.get(id) === node.value) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
inputValues.set(id, node.value);
|
|
115
|
+
sendInputValue(id, node);
|
|
116
|
+
}
|
|
117
|
+
function trackCheckboxValue(id, value) {
|
|
118
|
+
if (checkboxValues.get(id) === value) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
checkboxValues.set(id, value);
|
|
122
|
+
app.send((0, messages_gen_js_1.SetInputChecked)(id, value));
|
|
123
|
+
}
|
|
124
|
+
// The only way (to our knowledge) to track all kinds of input changes, including those made by JS
|
|
114
125
|
app.ticker.attach(() => {
|
|
115
126
|
inputValues.forEach((value, id) => {
|
|
116
127
|
const node = app.nodes.getNode(id);
|
|
117
128
|
if (!node)
|
|
118
129
|
return inputValues.delete(id);
|
|
119
|
-
|
|
120
|
-
inputValues.set(id, node.value);
|
|
121
|
-
if (!registeredTargets.has(id)) {
|
|
122
|
-
registeredTargets.add(id);
|
|
123
|
-
sendInputTarget(id, node);
|
|
124
|
-
}
|
|
125
|
-
sendInputValue(id, node);
|
|
126
|
-
}
|
|
130
|
+
trackInputValue(id, node);
|
|
127
131
|
});
|
|
128
|
-
|
|
132
|
+
checkboxValues.forEach((checked, id) => {
|
|
129
133
|
const node = app.nodes.getNode(id);
|
|
130
134
|
if (!node)
|
|
131
|
-
return
|
|
132
|
-
|
|
133
|
-
checkableValues.set(id, node.checked);
|
|
134
|
-
app.send((0, messages_gen_js_1.SetInputChecked)(id, node.checked));
|
|
135
|
-
}
|
|
135
|
+
return checkboxValues.delete(id);
|
|
136
|
+
trackCheckboxValue(id, node.checked);
|
|
136
137
|
});
|
|
137
|
-
});
|
|
138
|
-
|
|
138
|
+
}, 3);
|
|
139
|
+
function sendInputChange(id, node, hesitationTime, inputTime) {
|
|
140
|
+
const { value, mask } = getInputValue(id, node);
|
|
141
|
+
const label = getInputLabel(node);
|
|
142
|
+
app.send((0, messages_gen_js_1.InputChange)(id, value, mask !== 0, label, hesitationTime, inputTime));
|
|
143
|
+
}
|
|
139
144
|
app.nodes.attachNodeCallback(app.safe((node) => {
|
|
140
145
|
const id = app.nodes.getID(node);
|
|
141
146
|
if (id === undefined) {
|
|
142
147
|
return;
|
|
143
148
|
}
|
|
144
|
-
// TODO: support multiple select (?): use selectedOptions;
|
|
149
|
+
// TODO: support multiple select (?): use selectedOptions;
|
|
145
150
|
if ((0, guards_js_1.hasTag)(node, 'select')) {
|
|
146
151
|
sendInputValue(id, node);
|
|
147
|
-
app.
|
|
148
|
-
sendInputValue(id, node);
|
|
149
|
-
});
|
|
152
|
+
app.nodes.attachNodeListener(node, 'change', () => sendInputValue(id, node));
|
|
150
153
|
}
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
if (isTextFieldElement(node)) {
|
|
155
|
+
trackInputValue(id, node);
|
|
156
|
+
let nodeFocusTime = 0;
|
|
157
|
+
let nodeHesitationTime = 0;
|
|
158
|
+
let inputTime = 0;
|
|
159
|
+
const onFocus = () => {
|
|
160
|
+
nodeFocusTime = (0, utils_js_1.now)();
|
|
161
|
+
};
|
|
162
|
+
const onInput = () => {
|
|
163
|
+
if (nodeHesitationTime === 0) {
|
|
164
|
+
nodeHesitationTime = (0, utils_js_1.now)() - nodeFocusTime;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
const onChange = () => {
|
|
168
|
+
inputTime = (0, utils_js_1.now)() - nodeFocusTime;
|
|
169
|
+
sendInputChange(id, node, nodeHesitationTime, inputTime);
|
|
170
|
+
nodeHesitationTime = 0;
|
|
171
|
+
inputTime = 0;
|
|
172
|
+
};
|
|
173
|
+
app.nodes.attachNodeListener(node, 'focus', onFocus);
|
|
174
|
+
app.nodes.attachNodeListener(node, 'input', onInput);
|
|
175
|
+
app.nodes.attachNodeListener(node, 'change', onChange);
|
|
154
176
|
return;
|
|
155
177
|
}
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
app.
|
|
178
|
+
if (isCheckbox(node)) {
|
|
179
|
+
trackCheckboxValue(id, node.checked);
|
|
180
|
+
app.nodes.attachNodeListener(node, 'change', () => trackCheckboxValue(id, node.checked));
|
|
159
181
|
return;
|
|
160
182
|
}
|
|
161
183
|
}));
|