Files
altcha/dist_plugins/analytics.umd.cjs
Daniel Regeci 5c5aa3f712 2.2.4
2025-09-28 07:30:41 +09:00

2 lines
3.4 KiB
JavaScript

(function(s,n){typeof exports=="object"&&typeof module<"u"?n(exports):typeof define=="function"&&define.amd?define(["exports"],n):(s=typeof globalThis<"u"?globalThis:s||self,n(s["[name]"]={}))})(this,function(s){"use strict";new TextEncoder;function n(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch{}}class o{constructor(t){this.context=t}static pluginName;static register(t){typeof globalThis.altchaPlugins!="object"&&(globalThis.altchaPlugins=[]),globalThis.altchaPlugins.includes(t)||globalThis.altchaPlugins.push(t)}destroy(){}onErrorChange(t){}onStateChange(t){}}class r extends o{static pluginName="analytics";#t;#e;#i=this.#s.bind(this);constructor(t){if(super(t),this.#t=this.context.el.closest("form"),this.#t){let e=this.#t.getAttribute("data-beacon-url");const i=this.#t.getAttribute("action");!e&&i&&(e=i+"/beacon"),this.#t.addEventListener("submit",this.#i),this.#e=new h(this.#t,e)}}destroy(){this.#t?.removeEventListener("submit",this.#i),this.#e?.destroy()}onErrorChange(t){this.#e?.trackError(t)}#s(){if(this.#e&&!this.#e.submitTime){this.#e.end();const t=this.#e.dataAsBase64();this.context.dispatch("session",t);const e=document.createElement("input");e.type="hidden",e.name="__session",e.value=t,this.#t?.appendChild(e)}}}class h{constructor(t,e=null){this.elForm=t,this.beaconUrl=e,window.addEventListener("unload",this.#n),this.elForm.addEventListener("change",this.#i),this.elForm.addEventListener("focusin",this.#s)}error=null;loadTime=Date.now();submitTime=null;startTime=null;viewTimeThresholdMs=1500;#t={};#e=null;#i=this.onFormChange.bind(this);#s=this.onFormFocus.bind(this);#n=this.onUnload.bind(this);data(){const t=Object.entries(this.#t);return{correction:t.length&&t.filter(([e,i])=>i>1).length/t.length||0,dropoff:!this.submitTime&&!this.error&&this.#e?this.#e:null,error:this.error,mobile:this.isMobile(),start:this.startTime,submit:this.submitTime,tz:n()}}dataAsBase64(){try{return btoa(JSON.stringify(this.data()))}catch(t){console.error("failed to encode ALTCHA session data to base64",t)}return""}destroy(){window.removeEventListener("unload",this.#n),this.elForm.removeEventListener("change",this.#i),this.elForm.removeEventListener("focusin",this.#s)}end(){this.submitTime||(this.submitTime=Date.now())}getFieldName(t,e=40){const i=t.getAttribute("data-group-label"),l=t.getAttribute("name")||t.getAttribute("aria-label");return((i?i+": ":"")+l).slice(0,e)}isMobile(){const t="userAgentData"in navigator&&navigator.userAgentData?navigator.userAgentData:{};return"mobile"in t?t.mobile===!0:/Mobi/i.test(window.navigator.userAgent)}isInput(t){return["INPUT","SELECT","TEXTAREA"].includes(t.tagName)}onFormFieldChange(t){const e=this.getFieldName(t);e&&this.trackFieldChange(e)}onFormChange(t){const e=t.target;e&&this.isInput(e)&&this.onFormFieldChange(e)}onFormFocus(t){const e=t.target;if(this.startTime||this.start(),e&&this.isInput(e)){const i=this.getFieldName(e);i&&(this.#e=i)}}onUnload(){this.loadTime<=Date.now()-this.viewTimeThresholdMs&&!this.submitTime&&this.sendBeacon()}async sendBeacon(){if(this.beaconUrl&&"sendBeacon"in navigator)try{navigator.sendBeacon(new URL(this.beaconUrl,location.origin),JSON.stringify(this.data()))}catch{}}start(){this.startTime=Date.now()}trackError(t){this.error=t===null?null:String(t)}trackFieldChange(t){this.#t[t]=(this.#t[t]||0)+1}}o.register(r),s.PluginAnalytics=r,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})});