1 2 3 4 5 6 7 8 9 10 11 12 13 14 15<!DOCTYPE html> 16<html lang="en"> 17 <head> 18 <meta name="mobile-web-app-capable" content="yes" /> 19 <meta name="apple-mobile-web-app-capable" content="yes" /> 20 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 21 <title>Sign In - Whiteboard Fox</title> 22 <meta content='text/html' http-equiv='Content-Type' /> 23 <meta name="google-site-verification" content="FE8cBulH1WLyw4TjchpImuHI_FMqNbOTtc63itR-86o" /> 24 <meta name="description" content="Whiteboard Fox is a simple online whiteboard that allows you to collaborate with others in real time. Share your ideas, brainstorm with your team, and take notes all in one place. Whiteboard Fox is easy to use, and it's free to get started."/> 25 <meta property="og:title" content="Simple Online Whiteboard - Whiteboard Fox" /> 26 27 <meta property="og:description" content="Whiteboard Fox is a simple online whiteboard that allows you to collaborate with others in real time." /> 28 <meta property="og:image" content="https://whiteboardfox.com/images/cogs.jpg"/> 29 30 <meta name="twitter:card" content="Share your ideas, brainstorm with your team, and take notes all in one place. Whiteboard Fox is easy to use, and it's free to get started."/> 31 <meta name="twitter:title" content="Simple Online Whiteboard - Whiteboard Fox"/> 32 <meta name="twitter:description" content="Whiteboard Fox is a simple online whiteboard that allows you to collaborate with others in real time." /> 33 <meta name="twitter:image" content="https://whiteboardfox.com/images/cogs.jpg"/> 34 35 <link href="style.css" rel="Stylesheet" type="text/css" /> 36 <link href="/output.css" rel="stylesheet" type="text/css" /> 37 38 39<link href='https://fonts.googleapis.com/css?family=Hammersmith+One|Roboto:100,300' rel='stylesheet' type='text/css'> 40<link rel="shortcut icon" href="images/icon.png" /> 41 42 43 <!-- The core Firebase JS SDK is always required and must be listed first --> 44
44<script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-app.js"></script>
44 45 46 <!-- Add SDKs for Firebase products that you want to use 47 https://firebase.google.com/docs/web/setup#available-libraries --> 48
48<script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-auth.js"></script>
48 49 50
50<script src="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.js"></script>
50 51 <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" /> 52
52<script async src="https://cdn.fuseplatform.net/publift/tags/2/3299/fuse.js"></script>
vendor: 1 bytes, line 52
52
53<script> 54 55 56 57 58 59 60function createCookie(name,value,days) { 61 if (days) { 62 var date = new Date(); 63 date.setTime(date.getTime()+(days*24*60*60*1000)); 64 var expires = "; expires="+date.toGMTString(); 65 } 66 else var expires = ""; 67 68 document.cookie = name+"="+value+expires+"; path=/; domain=whiteboardfox.com"; 69} 70 71function readCookie(name) { 72 var nameEQ = name + "="; 73 var ca = document.cookie.split(';'); 74 for(var i=0;i < ca.length;i++) { 75 var c = ca[i]; 76 while (c.charAt(0)==' ') c = c.substring(1,c.length); 77 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); 78 } 79 return null; 80} 81function redirectToBusinessIfNeeded() { 82 const hasVisitedBusiness = localStorage.getItem('visited_pro_business') === 'true'; 83 84 const currentPath = window.location.pathname; 85 86 // Not allowed to see following pages if user has visited business page 87 const redirectPaths = ['/', '/pricing.jsp', '/lobby.jsp']; 88 89 if (hasVisitedBusiness && redirectPaths.includes(currentPath)) { 90 window.location.href = '/business.jsp'; 91 } 92} 93redirectToBusinessIfNeeded(); 94 95// http://stackoverflow.com/questions/1822350/what-is-the-javascript-operator-and-how-do-you-use-it 96if (readCookie("bid") == null) { 97 if("en_US".toLowerCase().includes("en") && Math.floor(Math.random() * 100) % 2 == 0) { 98 createCookie("user_type", "NA", 365); 99 } 100 var v = ""; 101 for (var i = 0; i < 18; i++) { 102 v = v + ((Math.random() * 10) >> 0); 103 } 104 createCookie("bid", v, 365 * 2); 105} 106 107</script>
107 108 <!-- Google tag (gtag.js) -->
vendor: 72 bytes, lines 108-109
108 109 <script async src="https://www.googletagmanager.com/gtag/js?id=
109G-1D9TC6VV9C
vendor: 20 bytes, lines 109-110
109"></script> 110
110<script> 111
vendor: 158 bytes, lines 111-115
111window.dataLayer = window.dataLayer || []; 112 function gtag(){dataLayer.push(arguments);} 113 gtag('js', new Date()); 114 115 gtag('config', '
115G-1D9TC6VV9C
vendor: 12 bytes, lines 115-116
115'); 116
116</script>
116 117 </head> 118 119 <body style="height:100%;background-color:white;font-family:Roboto, sans-serif;font-size:20px;font-weight:300;color:#233f98;"> 120 121 122 123 124 125<div id="banner-container" class="top-0 z-50"> 126</div> 127<template id="invite-banner-template"> 128 <div id="invite-banner" class="bg-[#243f98] text-white shadow-md p-2.5"> 129 <div class="flex justify-center items-center gap-2 max-w-5xl mx-auto text-sm"> 130 <div id="avatar-container" class="w-8 h-8"></div> 131 <p class="text-xs" id="invite-msg"></p> 132 <a target="_blank" class="flex gap-2 bg-white/75 p-2 text-black rounded text-xs text-center" id="join-invite-link">Join now</a> 133 </div> 134 </div> 135</template>
136<script> 137 async function addInvitationBannerIfAvailable() { 138 let invitation = await getInvitation(); 139 let inviteBannerTemplate = document.getElementById("invite-banner-template").content; 140 let inviteBannerDiv = inviteBannerTemplate.cloneNode(true); 141 if(invitation.isSuspended) { 142 inviteBannerDiv.querySelector("#invite-msg").innerHTML = "Your account has been suspended. Please contact support for more information."; 143 inviteBannerDiv.querySelector("#join-invite-link").setAttribute("href", "/profile.jsp" ); 144 inviteBannerDiv.querySelector("#join-invite-link").innerText = "Contact Support"; 145 inviteBannerDiv.querySelector("#invite-banner").style.background = "#cb0000"; 146 document.querySelector("#banner-container").appendChild(inviteBannerDiv); 147 return; 148 } 149 if (invitation.inviteType == "GALLERY") { 150 inviteBannerDiv.querySelector("#invite-msg").innerHTML = "Check out posts from the whiteboard you participated in!"; 151 inviteBannerDiv.querySelector("#join-invite-link").setAttribute("href", "/gallery/wb." + invitation.diagramName); 152 inviteBannerDiv.querySelector("#join-invite-link").innerHTML = "View Gallery"; 153 inviteBannerDiv.querySelector("#invite-banner").style.background = "#494949"; 154 } else { 155 if(invitation.userName == undefined) { 156 return; 157 } 158 inviteBannerDiv.querySelector("#invite-msg").innerHTML = getTranslatedInviteMsg(invitation.userName); 159 inviteBannerDiv.querySelector("#avatar-container").innerHTML = invitation.userAvatar; 160 inviteBannerDiv.querySelector("#join-invite-link").setAttribute("href", "/" + invitation.diagramName); 161 } 162 document.querySelector("#banner-container").appendChild(inviteBannerDiv); 163 setTimeout(() => { 164 document.querySelector("#invite-banner").style.display = "none" 165 }, 120000); 166 } 167 168 function getTranslatedInviteMsg(userName) { 169 let msg = `##placeholder## invited you to join their whiteboard`; 170 return msg.replace("##placeholder##", `<a class="underline" href="/gallery/${userName}">${userName}</a>`); 171 } 172 async function getInvitation() { 173 let response = await fetch('/api/getInvitation', { 174 method: "GET" 175 }); 176 let data = await response.json(); 177 return data; 178 } 179 document.addEventListener("DOMContentLoaded", (event) => { 180 addInvitationBannerIfAvailable(); 181 }); 182 183</script>
183 184 <div style="min-height: 100vh;display: flex;flex-direction:column;"> 185 <div style="background-color:#eeeeee;width:100%"> 186 <div style="width:1010px;height:100%;margin: 0 auto;background-color:#eeeeee"> 187 <div style="background-color:#eeeeee;padding:50px;padding:20px 50px 10px 50px;display: flex;align-items: center;justify-content: space-between"> 188 <a href="/" 189 style="font-size:32px;font-weight:300;font-family:'Hammersmith One', sans-serif;word-spacing:-8px;color:#233f98;text-decoration: none;display: flex; align-items: center;"> 190 <img src="images/icon.png" width="64" height="64" style="padding-right:3px;vertical-align:middle;"/> 191 Whiteboard Fox 192 </a> 193 194 <div style="flex-grow:1"></div> 195 196 <a 197 href="/lobby.jsp" 198 style="margin-right: 20px;" 199 class="mainLink" 200 >Lobby</a> 201 <a href="pricing.jsp" class="mainLink">Pricing</a> 202 <div style="width:20px"></div> 203 204 <a href="login.jsp" class="mainLink">Sign In</a> 205 206 207 208 </div> 209 </div> 210 </div> 211 212 213 <div style="background-color:white;width:100%"> 214 215 216 217 218 219 220 221 <div style="background-color:white;padding-top:0"> 222 <div style="width:1010px;height:100%;margin: 0 auto;"> 223 <div style="padding:0 0 10px 50px;"> 224 <div style="text-align:center"> 225 <h1 style="padding:20px 0 10px 0;font-size:58px;font-weight:100">Sign In</h1> 226 <div style="padding-bottom:50px">Select a sign-in method to continue</div> 227 228 229 230 231 232 <div id="firebaseui-auth-container"></div> 233 <div id="loader">Loading...</div> 234 235 <form id="loginForm" method="POST" action="login" style="display:none"> 236 <input type="hidden" name="idToken" id="idTokenInput" /> 237 <input type="hidden" name="name" id="nameInput" /> 238 <input type="hidden" name="redirect" id="redirectInput" /> 239 </form> 240 241
241<script> 242 let params = new URLSearchParams(window.location.search); 243 let redirect = params.get("redirect") || "/"; 244 245 var firebaseConfig = { 246 apiKey: "AIzaSyC8xW9BmOuZJJknjuXLozD-0wfRdExoZMQ", 247 authDomain: "whiteboard-fox-2b52f.firebaseapp.com", 248 databaseURL: "https://whiteboard-fox-2b52f.firebaseio.com", 249 projectId: "whiteboard-fox-2b52f", 250 storageBucket: "whiteboard-fox-2b52f.appspot.com", 251 messagingSenderId: "1033532005844", 252 appId: "1:1033532005844:web:8dbcdda9d9ae91ceda0a41" 253 }; 254 255 // Initialize Firebase 256 firebase.initializeApp(firebaseConfig); 257 258 259 260 var ui = new firebaseui.auth.AuthUI(firebase.auth()); 261 262 var uiConfig = { 263 callbacks: { 264 signInSuccessWithAuthResult: function(authResult, redirectUrl) { 265 document.getElementById('loader').style.display = 'block'; 266 var user = authResult.user; 267 var name = user.displayName; 268 // console.log(JSON.stringify(user)); 269 user.getIdToken().then( function(idToken) { 270 document.getElementById('idTokenInput').value = idToken; 271 document.getElementById('nameInput').value = name; 272 document.getElementById('redirectInput').value = redirect; 273 document.getElementById('loginForm').submit(); 274 }); 275 276 return false; 277 }, 278 uiShown: function() { 279 // The widget is rendered. 280 // Hide the loader. 281 document.getElementById('loader').style.display = 'none'; 282 } 283 }, 284 signInFlow: 'popup', 285 signInSuccessUrl: 'https://' + window.location.host + '/', 286 signInOptions: [ 287 // Leave the lines as is for the providers you want to offer your users. 288 firebase.auth.GoogleAuthProvider.PROVIDER_ID, 289 firebase.auth.EmailAuthProvider.PROVIDER_ID, 290 ], 291 // Terms of service url. 292 tosUrl: 'https://whiteboardfox.com/terms.html', 293 // Privacy policy url. 294 privacyPolicyUrl: 'https://whiteboardfox.com/privacy.html' 295 }; 296 297 ui.start('#firebaseui-auth-container', uiConfig); 298 </script>
298 299 300 301 </div> 302 </div> 303 </div> 304 </div> 305 306 307 308 309 </div> 310 <div style="flex-grow:1"></div> 311 <div style="background-color:#5271bb;"> 312 <div style="width:1010px;height:100%;margin: 0 auto;background-color:#5271bb;color:white"> 313 <div style="padding:10px 50px 10px 50px; font-size:12px;font-weight:300;"> 314 © 2026 Springbok Solutions LLC-FZ · <a href="privacy.html" style="text-decoration: none;color:white">Privacy Policy</a> · <a href="terms.html" style="text-decoration: none;color:white">Terms of Service</a> 315 </div> 316 </div> 317 </div> 318 319</div> 320</body> 321</html>
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.