Mercurial Hosting > linkmystyle
comparison src/site.js @ 0:8f4df159f06b
start public repo
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 11 Jul 2025 20:57:49 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:8f4df159f06b |
---|---|
1 'use strict'; | |
2 | |
3 function ajax(url,postData,context) { | |
4 let request = new XMLHttpRequest(); | |
5 let method = postData ? 'POST' : 'GET'; | |
6 request.open( method, url ); | |
7 if( postData ) | |
8 request.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' ); | |
9 request.onload = function() { | |
10 if( request.status !== 200 ) { | |
11 let err = 'ajax failed: ' + request.status; | |
12 if( request.responseText ) { | |
13 err += '\n' + request.responseText.trim(); | |
14 document.write('<pre>'+request.responseText+'</pre>'); | |
15 } | |
16 err += '\nurl = ' + url; | |
17 err += '\npage = ' + window.location; | |
18 ajax( '/error_log.js', 'err='+encodeURIComponent(err) ); | |
19 return; | |
20 } | |
21 try { | |
22 eval( request.responseText ); | |
23 } catch(e) { | |
24 console.log( request.responseText ); | |
25 window.err = '\najax-url = ' + url; | |
26 throw e; | |
27 } | |
28 }; | |
29 request.send(postData); | |
30 } | |
31 | |
32 window.onerror = function(msg, url, line, col, error) { | |
33 if( !url ) | |
34 return; | |
35 let err = msg; | |
36 err += '\nurl = ' + url; | |
37 if( url != window.location ) | |
38 err += '\npage = ' + window.location; | |
39 err += '\nline = '+line; | |
40 if( col ) | |
41 err += '\ncolumn = ' + col; | |
42 if( error ) { | |
43 if( error.stack ) | |
44 err += '\nstack = ' + error.stack; | |
45 if( error.cause ) | |
46 err += '\ncause= ' + error.cause; | |
47 if( error.fileName ) | |
48 err += '\nfileName= ' + error.fileName; | |
49 } | |
50 if( window.err ) { | |
51 err += window.err; | |
52 window.err = null; | |
53 } | |
54 ajax( '/error_log.js', 'err='+encodeURIComponent(err) ); | |
55 }; | |
56 | |
57 window.onunhandledrejection = function(event) { | |
58 //console.log(event); | |
59 let reason = event.reason; | |
60 let err = reason && reason.message || reason || JSON.stringify(event); | |
61 if( reason && reason.stack ) | |
62 err += '\nstack = ' + reason.stack; | |
63 ajax( '/error_log.js', 'err='+encodeURIComponent(err) ); | |
64 }; | |
65 | |
66 let isProduction = location.hostname==='linkmy.style'; | |
67 | |
68 let cookies; | |
69 function setCookies() { | |
70 cookies = {}; | |
71 if( document.cookie !== '' ) { | |
72 let a = document.cookie.split('; '); | |
73 for( let i=0; i<a.length; i++ ) { | |
74 let s = a[i]; | |
75 let j = s.indexOf('='); | |
76 if( j !== -1 ) { | |
77 let name = s.substring(0,j); | |
78 let value = s.substring(j+1); | |
79 cookies[name] = decodeURIComponent(value); | |
80 } | |
81 } | |
82 } | |
83 } | |
84 setCookies(); | |
85 | |
86 document.cookie = 'testcookie=x; Max-Age=1;'; | |
87 document.cookie = ''; | |
88 let hasCookies = document.cookie.includes('testcookie'); | |
89 | |
90 // Mixpanel | |
91 const MIXPANEL_CUSTOM_LIB_URL = "https://mp.linkmy.style/lib.min.js"; | |
92 | |
93 (function (f, b) { if (!b.__SV) { var e, g, i, h; window.mixpanel = b; b._i = []; b.init = function (e, f, c) { function g(a, d) { var b = d.split("."); 2 == b.length && ((a = a[b[0]]), (d = b[1])); a[d] = function () { a.push([d].concat(Array.prototype.slice.call(arguments, 0))); }; } var a = b; "undefined" !== typeof c ? (a = b[c] = []) : (c = "mixpanel"); a.people = a.people || []; a.toString = function (a) { var d = "mixpanel"; "mixpanel" !== c && (d += "." + c); a || (d += " (stub)"); return d; }; a.people.toString = function () { return a.toString(1) + ".people (stub)"; }; i = "disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking start_batch_senders people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove".split( " "); for (h = 0; h < i.length; h++) g(a, i[h]); var j = "set set_once union unset remove delete".split(" "); a.get_group = function () { function b(c) { d[c] = function () { call2_args = arguments; call2 = [c].concat(Array.prototype.slice.call(call2_args, 0)); a.push([e, call2]); }; } for ( var d = {}, e = ["get_group"].concat( Array.prototype.slice.call(arguments, 0)), c = 0; c < j.length; c++) b(j[c]); return d; }; b._i.push([e, f, c]); }; b.__SV = 1.2; e = f.createElement("script"); e.type = "text/javascript"; e.async = !0; e.src = "undefined" !== typeof MIXPANEL_CUSTOM_LIB_URL ? MIXPANEL_CUSTOM_LIB_URL : "file:" === f.location.protocol && "//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//) ? "https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js" : "//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js"; g = f.getElementsByTagName("script")[0]; g.parentNode.insertBefore(e, g); } })(document, window.mixpanel || []); | |
94 | |
95 let mpConfig = { | |
96 debug: !isProduction, | |
97 persistence: 'localStorage', | |
98 api_host: 'https://mp.linkmy.style', | |
99 }; | |
100 let mixpanelProps = {}; | |
101 { | |
102 if( isProduction ) { | |
103 mixpanel.init('404d4c479de9c3070252e692375e82ca',mpConfig,'ours'); | |
104 } else { // test | |
105 mixpanel.init('bd2099a22e4118350a46b5b360d8c4da',mpConfig,'ours'); | |
106 } | |
107 if( !hasCookies || location.pathname.match(/^\/private\//) ) { | |
108 mixpanel.ours.disable(); | |
109 } else { | |
110 let props = mixpanelProps; | |
111 if( navigator.userAgent.includes('Instagram') ) { | |
112 props.App = 'Instagram'; | |
113 } else if( navigator.userAgent.includes('BytedanceWebview') ) { | |
114 props.App = 'TikTok'; | |
115 } | |
116 props.LoggedIn = !!cookies.user; | |
117 if( typeof(URLSearchParams) === 'function' ) { | |
118 let searchParams = new URLSearchParams(location.search); | |
119 if( Symbol.iterator in searchParams ) { | |
120 for (let p of searchParams) { | |
121 props[p[0]] = p[1]; | |
122 } | |
123 } | |
124 } | |
125 props.Path = window.Path || location.pathname; | |
126 if( !window.Owner ) { | |
127 mixpanel.ours.track( 'Page View', props ); | |
128 } else { | |
129 props.Owner = window.Owner; | |
130 props.Page = window.Page; | |
131 if( isProduction ) { | |
132 mixpanel.init('2bb632e9309b175ef67b7df382a43aee',mpConfig,'rpt'); | |
133 } else { // test | |
134 mixpanel.init('4acad1a74dfe7dba21e30da2642b9f78',mpConfig,'rpt'); | |
135 } | |
136 if( Math.random() > 0.01 ) | |
137 mixpanel.rpt.disable(); | |
138 mixpanel.rpt.track( 'Page View', props ); | |
139 window.addEventListener( 'load', function() { | |
140 let links = document.querySelectorAll('a[link]'); | |
141 for( let i=0; i<links.length; i++ ) { | |
142 let link = links[i]; | |
143 link.addEventListener( 'click', function(event) { | |
144 props.Link = event.target.textContent; | |
145 mixpanel.rpt.track( 'Click', props, {send_immediately:true} ); | |
146 } ); | |
147 } | |
148 } ); | |
149 if( window.OwnerMpId ) { | |
150 mixpanel.init(window.OwnerMpId,mpConfig,'owner'); | |
151 let props = { Page: window.Page }; | |
152 mixpanel.owner.track( 'Page View', props ); | |
153 window.addEventListener( 'load', function() { | |
154 let links = document.querySelectorAll('a[link]'); | |
155 for( let i=0; i<links.length; i++ ) { | |
156 let link = links[i]; | |
157 link.addEventListener( 'click', function(event) { | |
158 props.Link = event.target.textContent; | |
159 mixpanel.owner.track( 'Click', props, {send_immediately:true} ); | |
160 } ); | |
161 } | |
162 } ); | |
163 } | |
164 } | |
165 } | |
166 } | |
167 | |
168 | |
169 // Facebook | |
170 let fbId = isProduction ? '667025338202310' : '1504114567086568'; | |
171 let fbOptions = {}; | |
172 if( window.UserEmail ) | |
173 fbOptions.em = window.UserEmail.trim().toLowerCase(); | |
174 if( cookies.user ) | |
175 fbOptions.external_id = cookies.user; | |
176 //console.log(fbOptions); | |
177 | |
178 !function(f,b,e,v,n,t,s) | |
179 {if(f.fbq)return;n=f.fbq=function(){n.callMethod? | |
180 n.callMethod.apply(n,arguments):n.queue.push(arguments)}; | |
181 if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; | |
182 n.queue=[];t=b.createElement(e);t.async=!0; | |
183 t.src=v;s=b.getElementsByTagName(e)[0]; | |
184 s.parentNode.insertBefore(t,s)}(window, document,'script', | |
185 'https://connect.facebook.net/en_US/fbevents.js'); | |
186 fbq('init', fbId, fbOptions); | |
187 | |
188 let fbEvents = null; | |
189 | |
190 function fbSendEvents() { | |
191 //console.log(fbEvents); | |
192 let eventID = Math.random().toString(); | |
193 let options = {eventID:eventID}; | |
194 let url = `/facebook.js?event_id=${eventID}`; | |
195 for( let event of fbEvents ) { | |
196 let name = event.name; | |
197 let props = event.properties; | |
198 fbq( event.action, name, props, options ); | |
199 url += `&event_name=${name}`; | |
200 if( props ) | |
201 url += `&${name}=${encodeURIComponent(JSON.stringify(props))}`; | |
202 } | |
203 ajax(url); | |
204 fbEvents = null; | |
205 } | |
206 | |
207 function fbTrack(action,name,properties) { | |
208 if( !fbEvents ) { | |
209 fbEvents = []; | |
210 setTimeout(fbSendEvents); | |
211 } | |
212 fbEvents.push({ | |
213 action: action, | |
214 name: name, | |
215 properties: properties, | |
216 }); | |
217 } | |
218 | |
219 | |
220 function mainSelectHashtag(hashtag) { | |
221 let style = document.querySelector('style[hashtag]'); | |
222 if( hashtags[hashtag] ) { | |
223 style.innerHTML = ` | |
224 div[pics] > span { | |
225 display: none; | |
226 } | |
227 div[pics] > span.${hashtag} { | |
228 display: block; | |
229 } | |
230 ` ; | |
231 history.replaceState(null,null, `#${hashtag}` ); | |
232 } else { | |
233 style.innerHTML = ''; | |
234 history.replaceState(null,null, location.pathname + location.search ); | |
235 } | |
236 } | |
237 | |
238 function mainInit() { | |
239 let hash = location.hash; | |
240 if( hash ) { | |
241 hash = hash.slice(1); // remove '#' | |
242 if( hashtags[hash] ) { | |
243 let select = document.querySelector('[hashtags] select'); | |
244 select.value = hash; | |
245 mainSelectHashtag(hash); | |
246 } else { | |
247 history.replaceState(null,null, location.pathname + location.search ); | |
248 } | |
249 } | |
250 } |