1document.addEventListener('DOMContentLoaded', function() { 2 const popup = document.createElement('div'); 3 popup.className = 'socialproof'; 4 popup.innerHTML = ` 5 <img id="socialproof-avatar" src="" alt="User"> 6 <div class="socialproof-content"> 7 <strong id="socialproof-name"></strong> <span id="socialproof-action"></span><br> 8 <span id="socialproof-time"></span> 9 </div> 10 <span class="socialproof-close">Ã</span> 11 `; 12 document.body.appendChild(popup); 13 14 const resetBtn = document.createElement('button'); 15 resetBtn.className = 'socialproof-reset'; 16 resetBtn.innerText = 'Enable Popups Again'; 17 document.body.appendChild(resetBtn); 18 19 // Apply position from settings 20 if(socialproofPopupData.position==='bottom-right'){ 21 popup.style.left='auto'; 22 popup.style.right='20px'; 23 } 24 25 const avatar = popup.querySelector('#socialproof-avatar'); 26 const nameEl = popup.querySelector('#socialproof-name'); 27 const actionEl = popup.querySelector('#socialproof-action'); 28 const timeEl = popup.querySelector('#socialproof-time'); 29 const closeEl = popup.querySelector('.socialproof-close'); 30 31 let notifications = []; 32 let queue = []; 33 let lastIndex = -1; 34 let currentNotification = null; 35 let dismissed = localStorage.getItem('tpDismissed') === 'true'; 36 const storedTime = localStorage.getItem('tpDismissedTime'); 37 38 if(dismissed && storedTime){ 39 const elapsed = Date.now() - parseInt(storedTime,10); 40 if(elapsed<24*60*60*1000){ resetBtn.style.display = 'block'; } 41 else { dismissed=false; localStorage.removeItem('tpDismissed'); localStorage.removeItem('tpDismissedTime'); } 42 } 43 44 function timeAgo(timestamp){ 45 const now = new Date(); 46 const t = new Date(timestamp); 47 const diff = Math.floor((now-t)/1000); 48 if(diff<60) return `${diff} seconds ago`; 49 if(diff<3600) return `${Math.floor(diff/60)} minutes ago`; 50 if(diff<86400) return `${Math.floor(diff/3600)} hours ago`; 51 return `${Math.floor(diff/86400)} days ago`; 52 } 53 54 function getNextNotification(){ 55 if(queue.length>0) return queue.shift(); 56 if(notifications.length===0) return null; 57 let idx; do { idx=Math.floor(Math.random()*notifications.length);} 58 while(idx===lastIndex && notifications.length>1); 59 lastIndex=idx; 60 return notifications[idx]; 61 } 62 63 function showPopup(){ 64 if(dismissed) return; 65 const n = getNextNotification(); 66 if(!n) return; 67 currentNotification = n; 68 avatar.src = n.avatar; 69 nameEl.textContent = n.name; 70 actionEl.textContent = n.action; 71 timeEl.textContent = timeAgo(n.timestamp); 72 popup.classList.add('show'); 73 popup.style.borderColor = socialproofPopupData.borderColor; 74 popup.style.backgroundColor = socialproofPopupData.bgColor; 75 popup.style.color = socialproofPopupData.textColor; 76 popup.querySelector('.socialproof-content strong').style.color = socialproofPopupData.accentColor; 77 popup.querySelector('.socialproof-close').style.color = socialproofPopupData.closeColor; 78 setTimeout(hidePopup, socialproofPopupData.duration || 5000); 79 } 80 81 function hidePopup(){ 82 popup.classList.remove('show'); 83 currentNotification = null; 84 if(!dismissed) setTimeout(showPopup,2000); 85 } 86 87 function dismissPopups(){ 88 dismissed=true; 89 localStorage.setItem('tpDismissed','true'); 90 localStorage.setItem('tpDismissedTime',Date.now().toString()); 91 popup.classList.remove('show'); 92 currentNotification=null; 93 resetBtn.style.display='block'; 94 } 95 96 function resetPopups(){ 97 dismissed=false; 98 localStorage.removeItem('tpDismissed'); 99 localStorage.removeItem('tpDismissedTime'); 100 resetBtn.style.display='none'; 101 setTimeout(showPopup,2000); 102 } 103 104 closeEl.addEventListener('click', dismissPopups); 105 resetBtn.addEventListener('click', resetPopups); 106 107 async function fetchNotifications(){ 108 try{ 109 const res = await fetch(socialproofPopupData.apiUrl); 110 const data = await res.json(); 111 if(Array.isArray(data)){ 112 data.forEach(item=>{ 113 const exists = queue.some(q=>q.name===item.name && q.timestamp===item.timestamp); 114 if(!exists) queue.push(item); 115 }); 116 notifications = data; 117 console.log(notifications); 118 } 119 } catch(err){ console.warn(err); } 120 } 121 122 setInterval(()=>{ 123 if(currentNotification && popup.classList.contains('show')){ 124 timeEl.textContent = timeAgo(currentNotification.timestamp); 125 } 126 },1000); 127 128 if(socialproofPopupData.autoPoll){ 129 setInterval(fetchNotifications,30000); 130 } 131 132 if(!dismissed) fetchNotifications().then(()=>setTimeout(showPopup,2000)); 133});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.