1const MODAL_TEMPLATES = { 2 login: ` 3 <div id="appleid-signin" 4 data-color="black" 5 data-border="true" 6 data-type="continue" 7 style="display: none;"> 8 </div> 9 <div aria-hidden="true" aria-labelledby="examplesigninModalLabel2" class="modal fade" id="examplesigninModal" 10 tabindex="-1"> 11 <div class="modal-dialog modal-dialog-centered"> 12 <div class="modal-content light"> 13 <div class="modal-body"> 14 <button aria-label="Close" class="btn-close" data-bs-dismiss="modal" type="button"> 15 <img draggable="false" alt="close-icon" class="img-fluid" src="/static/images/close-icon-light.svg" /> 16 </button> 17 <div class="modal-info"> 18 <div class="section-small-title light"> 19 <h3> 20 Log In 21 </h3> 22 </div> 23 <div class="apple-button-container" id="login-button-container"> 24 <div class="apple-loading-spinner"></div> 25 </div> 26 <div class="google-button"> 27 <a class="google-btn light" href="/login/google"> 28 Continue with Google 29 </a> 30 </div> 31 <div class="left-right-border light google-login-seperator"> 32 <p> 33 OR 34 </p> 35 </div> 36 <form class="form commen-form" id="login-form" novalidate=""> 37 <div class="form-group"> 38 <input class="form-control light" id="loginEmail" placeholder="Email" type="email" /> 39 <img draggable="false" alt="alertimg" class="img-fluid alertimg" src="/static/images/alert-circle.svg" /> 40 <div class="error-content"> 41 <p> 42 Please enter a valid email address. 43 </p> 44 </div> 45 </div> 46 <div class="form-group"> 47 <input class="form-control light password" id="loginPassword" placeholder="Password" type="password" /> 48 <img draggable="false" alt="eyeimg" class="img-fluid eyepassword togglePassword-light" 49 src="/static/images/Eye-light.svg" /> 50 <img draggable="false" alt="alertimg" class="img-fluid alertimg" src="/static/images/alert-circle.svg" /> 51 <div class="error-content"> 52 <p> 53 This field cannot be empty. 54 </p> 55 </div> 56 </div> 57 <input id="login-turnstileToken" name="login-turnstileToken" type="hidden" /> 58 <div class="forgot-password light"> 59 <a data-bs-target="#exampleforgotpasswordModal" data-bs-toggle="modal" href="#"> 60 Forgot 61 your password? 62 </a> 63 </div> 64 <div class="continue-button"> 65 <button class="login-btn continue-btn" type="submit"> 66 Continue 67 </button> 68 <span class="error-text"> 69 Error text 70 </span> 71 <svg class="spinner" viewbox="0 0 50 50"> 72 <circle class="path" cx="25" cy="25" fill="none" r="20" stroke-width="5"> 73 </circle> 74 </svg> 75 </div> 76 <div class="sign-up-info account light"> 77 <p> 78 Don't have an account? 79 <a class="signup-click" data-bs-target="#exampleModal" data-bs-toggle="modal" 80 from-source="login-screen" href="#"> 81 Sign up 82 </a> 83 now and start having time on your 84 quizzes, homework and exams! 85 </p> 86 </div> 87 </form> 88 </div> 89 </div> 90 </div> 91 </div> 92</div> 93`, 94 signup: ` 95 <div aria-hidden="true" aria-labelledby="exampleModalLabel" class="modal fade" id="exampleModal" tabindex="-1"> 96 <div class="modal-dialog modal-dialog-centered"> 97 <div class="modal-content light"> 98 <div class="modal-body"> 99 <button aria-label="Close" class="btn-close" data-bs-dismiss="modal" type="button"> 100 <img draggable="false" alt="close-icon" class="img-fluid" src="/static/images/close-icon-light.svg" /> 101 </button> 102 <div class="modal-info"> 103 <div class="section-small-title light"> 104 <h3> 105 Sign Up 106 </h3> 107 </div> 108 <div class="apple-button-container" id="signup-button-container"> 109 <div class="apple-loading-spinner"></div> 110 </div> 111 <div class="google-button"> 112 <a class="google-btn light" href="/login/google"> 113 Continue with Google 114 </a> 115 </div> 116 <div class="left-right-border light google-login-seperator"> 117 <p> 118 OR 119 </p> 120 </div> 121 <form class="form commen-form" id="signup-form" novalidate=""> 122 <div class="form-group"> 123 <input class="form-control light" 124 id="signupEmail1" 125 name="email" 126 placeholder="Email*" 127 type="email" 128 autocomplete="email" />
129 <img draggable="false" alt="alertimg" class="img-fluid alertimg" src="/static/images/alert-circle.svg" /> 130 <div class="error-content"> 131 <p> 132 Please enter a valid email address 133 </p> 134 </div> 135 </div> 136 <div class="form-group"> 137 <input class="form-control light" 138 id="signupEmail2" 139 name="email_confirm" 140 placeholder="Confirm email*" 141 type="email" 142 autocomplete="email" /> 143 <img draggable="false" alt="alertimg" class="img-fluid alertimg" src="/static/images/alert-circle.svg" /> 144 <div class="error-content"> 145 <p> 146 Emails do not match 147 </p> 148 </div> 149 </div> 150 <div class="form-group"> 151 <div class="input-group"> 152 <select class="form-control light phone-code-select" 153 id="phoneCode" 154 name="phone_country_code" 155 autocomplete="tel-country-code"> 156 <option value="+1">+1</option> 157 <option value="+44">+44</option> 158 <option value="+91">+91</option> 159 <option value="+7">+7</option> 160 <option value="+20">+20</option> 161 <option value="+27">+27</option> 162 <option value="+30">+30</option> 163 <option value="+31">+31</option> 164 <option value="+32">+32</option> 165 <option value="+33">+33</option> 166 <option value="+34">+34</option> 167 <option value="+36">+36</option> 168 <option value="+39">+39</option> 169 <option value="+40">+40</option> 170 <option value="+41">+41</option> 171 <option value="+43">+43</option> 172 <option value="+45">+45</option> 173 <option value="+46">+46</option> 174 <option value="+47">+47</option> 175 <option value="+48">+48</option> 176 <option value="+49">+49</option> 177 <option value="+51">+51</option> 178 <option value="+52">+52</option> 179 <option value="+53">+53</option> 180 <option value="+54">+54</option> 181 <option value="+55">+55</option> 182 <option value="+56">+56</option> 183 <option value="+57">+57</option> 184 <option value="+58">+58</option> 185 <option value="+60">+60</option> 186 <option value="+61">+61</option> 187 <option value="+62">+62</option> 188 <option value="+63">+63</option> 189 <option value="+64">+64</option> 190 <option value="+65">+65</option> 191 <option value="+66">+66</option> 192 <option value="+81">+81</option> 193 <option value="+82">+82</option> 194 <option value="+84">+84</option> 195 <option value="+86">+86</option> 196 <option value="+90">+90</option> 197 <option value="+92">+92</option> 198 <option value="+93">+93</option> 199 <option value="+94">+94</option> 200 <option value="+95">+95</option> 201 <option value="+98">+98</option> 202 <option value="+212">+212</option> 203 <option value="+213">+213</option> 204 <option value="+216">+216</option> 205 <option value="+218">+218</option> 206 <option value="+220">+220</option> 207 <option value="+221">+221</option> 208 <option value="+222">+222</option> 209 <option value="+223">+223</option> 210 <option value="+224">+224</option> 211 <option value="+225">+225</option> 212 <option value="+226">+226</option> 213 <option value="+227">+227</option> 214 <option value="+228">+228</option> 215 <option value="+229">+229</option> 216 <option value="+230">+230</option> 217 <option value="+231">+231</option> 218 <option value="+232">+232</option> 219 <option value="+233">+233</option> 220 <option value="+234">+234</option> 221 <option value="+235">+235</option> 222 <option value="+236">+236</option> 223 <option value="+237">+237</option> 224 <option value="+238">+238</option> 225 <option value="+239">+239</option> 226 <option value="+240">+240</option> 227 <option value="+241">+241</option> 228 <option value="+242">+242</option> 229 <option value="+243">+243</option> 230 <option value="+244">+244</option> 231 <option value="+245">+245</option> 232 <option value="+246">+246</option> 233 <option value="+248">+248</option> 234 <option value="+249">+249</option> 235 <option value="+250">+250</option> 236 <option value="+251">+251</option> 237 <option value="+252">+252</option> 238 <option value="+253">+253</option> 239 <option value="+254">+254</option> 240 <option value="+255">+255</option> 241 <option value="+256">+256</option> 242 <option value="+257">+257</option> 243 <option value="+258">+258</option> 244 <option value="+260">+260</option> 245 <option value="+261">+261</option> 246 <option value="+262">
246+262</option> 247 <option value="+263">+263</option> 248 <option value="+264">+264</option> 249 <option value="+265">+265</option> 250 <option value="+266">+266</option> 251 <option value="+267">+267</option> 252 <option value="+268">+268</option> 253 <option value="+269">+269</option> 254 <option value="+290">+290</option> 255 <option value="+291">+291</option> 256 <option value="+297">+297</option> 257 <option value="+298">+298</option> 258 <option value="+299">+299</option> 259 <option value="+350">+350</option> 260 <option value="+351">+351</option> 261 <option value="+352">+352</option> 262 <option value="+353">+353</option> 263 <option value="+354">+354</option> 264 <option value="+355">+355</option> 265 <option value="+356">+356</option> 266 <option value="+357">+357</option> 267 <option value="+358">+358</option> 268 <option value="+359">+359</option> 269 <option value="+370">+370</option> 270 <option value="+371">+371</option> 271 <option value="+372">+372</option> 272 <option value="+373">+373</option> 273 <option value="+374">+374</option> 274 <option value="+375">+375</option> 275 <option value="+376">+376</option> 276 <option value="+377">+377</option> 277 <option value="+378">+378</option> 278 <option value="+380">+380</option> 279 <option value="+381">+381</option> 280 <option value="+382">+382</option> 281 <option value="+383">+383</option> 282 <option value="+385">+385</option> 283 <option value="+386">+386</option> 284 <option value="+387">+387</option> 285 <option value="+389">+389</option> 286 <option value="+420">+420</option> 287 <option value="+421">+421</option> 288 <option value="+423">+423</option> 289 <option value="+500">+500</option> 290 <option value="+501">+501</option> 291 <option value="+502">+502</option> 292 <option value="+503">+503</option> 293 <option value="+504">+504</option> 294 <option value="+505">+505</option> 295 <option value="+506">+506</option> 296 <option value="+507">+507</option> 297 <option value="+508">+508</option> 298 <option value="+509">+509</option> 299 <option value="+590">+590</option> 300 <option value="+591">+591</option> 301 <option value="+592">+592</option> 302 <option value="+593">+593</option> 303 <option value="+594">+594</option> 304 <option value="+595">+595</option> 305 <option value="+596">+596</option> 306 <option value="+597">+597</option> 307 <option value="+598">+598</option> 308 <option value="+599">+599</option> 309 <option value="+670">+670</option> 310 <option value="+672">+672</option> 311 <option value="+673">+673</option> 312 <option value="+674">+674</option> 313 <option value="+675">+675</option> 314 <option value="+676">+676</option> 315 <option value="+677">+677</option> 316 <option value="+678">+678</option> 317 <option value="+679">+679</option> 318 <option value="+680">+680</option> 319 <option value="+681">+681</option> 320 <option value="+682">+682</option> 321 <option value="+683">+683</option> 322 <option value="+685">+685</option> 323 <option value="+686">+686</option> 324 <option value="+687">+687</option> 325 <option value="+688">+688</option> 326 <option value="+689">+689</option> 327 <option value="+690">+690</option> 328 <option value="+691">+691</option> 329 <option value="+692">+692</option> 330 <option value="+800">+800</option> 331 <option value="+808">+808</option> 332 <option value="+850">+850</option> 333 <option value="+852">+852</option> 334 <option value="+853">+853</option> 335 <option value="+855">+855</option> 336 <option value="+856">+856</option> 337 <option value="+870">+870</option> 338 <option value="+878">+878</option> 339 <option value="+880">+880</option> 340 <option value="+881">+881</option> 341 <option value="+882">+882</option> 342 <option value="+883">+883</option>
343 <option value="+886">+886</option> 344 <option value="+888">+888</option> 345 <option value="+960">+960</option> 346 <option value="+961">+961</option> 347 <option value="+962">+962</option> 348 <option value="+963">+963</option> 349 <option value="+964">+964</option> 350 <option value="+965">+965</option> 351 <option value="+966">+966</option> 352 <option value="+967">+967</option> 353 <option value="+968">+968</option> 354 <option value="+970">+970</option> 355 <option value="+971">+971</option> 356 <option value="+972">+972</option> 357 <option value="+973">+973</option> 358 <option value="+974">+974</option> 359 <option value="+975">+975</option> 360 <option value="+976">+976</option> 361 <option value="+977">+977</option> 362 <option value="+978">+978</option> 363 <option value="+979">+979</option> 364 <option value="+992">+992</option> 365 <option value="+993">+993</option> 366 <option value="+994">+994</option> 367 <option value="+995">+995</option> 368 <option value="+996">+996</option> 369 <option value="+998">+998</option> 370 </select> 371 <input class="form-control light phone-number-input" 372 id="phoneInput" 373 name="phone" 374 placeholder="Phone number" 375 type="tel" 376 autocomplete="tel-national" /> 377 </div> 378 </div> 379 <div class="form-group"> 380 <input class="form-control light password" id="signupPassword" placeholder="Password*" 381 type="password" /> 382 <img draggable="false" alt="eyeimg" class="img-fluid eyepassword togglePassword-light" 383 src="/static/images/Eye-light.svg" /> 384 <img draggable="false" alt="alertimg" class="img-fluid alertimg" src="/static/images/alert-circle.svg" /> 385 <div class="error-content"> 386 <p> 387 Please enter a valid password 388 </p> 389 </div> 390 </div> 391 <div class="form-group" style="display: none;"> 392 <input class="form-control light" id="signupReferralCode" placeholder="Referral code" type="text" /> 393 <img draggable="false" alt="alertimg" class="img-fluid alertimg" src="/static/images/alert-circle.svg" /> 394 <div class="error-content"> 395 <p> 396 This code is expired 397 </p> 398 </div> 399 </div> 400 <input id="signup-turnstileToken" name="signup-turnstileToken" type="hidden" /> 401 <div class="continue-button"> 402 <button class="signup-btn continue-btn" type="submit"> 403 Continue 404 </button> 405 <span class="error-text"> 406 Error text 407 </span> 408 <svg class="spinner" viewbox="0 0 50 50"> 409 <circle class="path" cx="25" cy="25" fill="none" r="20" stroke-width="5"> 410 </circle> 411 </svg> 412 </div> 413 <div class="account light"> 414 <p> 415 Already have an account? 416 <a class="login-click" data-bs-target="#examplesigninModal" data-bs-toggle="modal" 417 from-source="signup-screen" href="#"> 418 Log in 419 </a> 420 </p> 421 </div> 422 <div class="last-info light"> 423 <p> 424 By proceeding, you agree to the 425 <a href="/terms" target="_blank"> 426 Terms of Service 427 </a> 428 <br /> 429 and 430 <a href="/privacy" target="_blank"> 431 Privacy Policy. 432 </a> 433 </p> 434 </div> 435 </form> 436 </div> 437 </div> 438 </div> 439 </div> 440</div> 441`, 442 forgotPassword: ` 443 <div aria-hidden="true" aria-labelledby="exampleforgotpasswordModalLabel3" class="modal fade forgot-password-modal" 444 id="exampleforgotpasswordModal" tabindex="-1"> 445 <div class="modal-dialog modal-dialog-centered"> 446 <div class="modal-content light"> 447 <div class="modal-body"> 448 <button aria-label="Close" class="btn-close" data-bs-dismiss="modal" type="button"> 449 <img draggable="false" alt="close-icon" class="img-fluid" src="/static/images/close-icon-light.svg" /> 450 </button> 451 <div class="modal-info"> 452 <div class="section-small-title light text-center"> 453 <img src="/static/images/mun/lock.svg" draggable="false" alt="lock" class="img-fluid lock-img" /> 454 <h3> 455 Reset your Mindko Account Password 456 </h3> 457 <p class="m-subtitle">Enter your Email address below and weâll send you a link to reset your password.</p> 458 </div> 459 <form class="form commen-form" id="reset-form" novalidate=""> 460 <div class="form-group"> 461 <input class="form-control light" id="resetEmail" placeholder="Your email" type="email" />
462 <img draggable="false" alt="alertimg" class="img-fluid alertimg" src="/static/images/alert-circle.svg" /> 463 <div class="error-content"> 464 <p> 465 Please enter a valid email address. 466 </p> 467 </div> 468 </div> 469 <input id="reset-turnstileToken" name="reset-turnstileToken" type="hidden" /> 470 <div class="continue-button"> 471 <button class="reset-btn continue-btn" type="submit"> 472 Continue 473 </button> 474 <span class="error-text"> 475 Error text 476 </span> 477 <svg class="spinner" viewbox="0 0 50 50"> 478 <circle class="path" cx="25" cy="25" fill="none" r="20" stroke-width="5"> 479 </circle> 480 </svg> 481 </div> 482 </form> 483 </div> 484 </div> 485 </div> 486 </div> 487</div> 488`, 489 student: ` 490 <div class="modal fade student-satisfaction-modal" id="studentModal" tabindex="-1" aria-labelledby="studentModalLabel" 491 aria-hidden="true"> 492 <div class="modal-dialog modal-dialog-centered"> 493 <div class="modal-content light"> 494 <div class="modal-body"> 495 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"> 496 <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 25 25" fill="none"> 497 <path 498 d="M19.5896 18.9698C19.6593 19.0395 19.7146 19.1222 19.7523 19.2132C19.79 19.3043 19.8094 19.4019 19.8094 19.5004C19.8094 19.599 19.79 19.6965 19.7523 19.7876C19.7146 19.8786 19.6593 19.9614 19.5896 20.031C19.52 20.1007 19.4372 20.156 19.3462 20.1937C19.2551 20.2314 19.1576 20.2508 19.059 20.2508C18.9605 20.2508 18.8629 20.2314 18.7718 20.1937C18.6808 20.156 18.5981 20.1007 18.5284 20.031L12.309 13.8107L6.08964 20.031C5.94891 20.1718 5.75803 20.2508 5.55901 20.2508C5.35999 20.2508 5.16912 20.1718 5.02839 20.031C4.88766 19.8903 4.80859 19.6994 4.80859 19.5004C4.80859 19.3014 4.88766 19.1105 5.02839 18.9698L11.2487 12.7504L5.02839 6.53104C4.88766 6.39031 4.80859 6.19944 4.80859 6.00042C4.80859 5.80139 4.88766 5.61052 5.02839 5.46979C5.16912 5.32906 5.35999 5.25 5.55901 5.25C5.75803 5.25 5.94891 5.32906 6.08964 5.46979L12.309 11.6901L18.5284 5.46979C18.6691 5.32906 18.86 5.25 19.059 5.25C19.258 5.25 19.4489 5.32906 19.5896 5.46979C19.7304 5.61052 19.8094 5.80139 19.8094 6.00042C19.8094 6.19944 19.7304 6.39031 19.5896 6.53104L13.3693 12.7504L19.5896 18.9698Z" 499 fill="#182141" /> 500 </svg> 501 </button> 502 <div class="modal-info"> 503 <div style="position: relative;"> 504 <video src="" playsinline preload="none"></video> 505 <div class="loading-overlay"> 506 <div class="testimonial-video-spinner"></div> 507 </div> 508 </div> 509 <div class="modal-footer"> 510 <img draggable="false" class="institution-img" src="" alt="University logo"> 511 <div class="details"> 512 <p class="student-name"></p> 513 <p class="location"></p> 514 </div> 515 </div> 516 </div> 517 </div> 518 </div> 519 </div> 520</div> 521`, 522 specialOffer: ` 523<div class="modal fade special-offer-modal" id="examplespecialofferModal" tabindex="-1" 524 aria-labelledby="examplespecialofferModalLabel6" aria-hidden="true"> 525 <div class="modal-dialog modal-dialog-centered"> 526 <div class="modal-content"> 527 <div class="modal-body" style="height: auto;"> 528 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"> 529 <img draggable="false" src="/static/images/close-icon.svg" alt="close-icon" class="img-fluid"> 530 </button> 531 <div class="pricing-wrapper "> 532 <img draggable="false" class="pricing-shape" src="/static/images/mun/pricing-shape.svg" alt="pricing shape"> 533 <div class="footer-valid"> 534 <img draggable="false" src="/static/images/mun/clock.svg" alt="clock icon"> 535 Offer valid until <span class="offer-date"></span> 536 </div> 537 <h2 class="title">3 days FREE</h2> 538 <div class="subtitle">Unlimited access</div> 539 540 <ul class="list"> 541 <li><img draggable="false" src="/static/images/mun/check-circle.svg" alt="check circle"> 542 <div>Solve <span>unlimited questions</span></div> 543 </li> 544 <li><img draggable="false" src="/static/images/mun/check-circle.svg" alt="check circle"> 545 <div><span>Auto-selects</span> the correct answer</div> 546 </li> 547 <li><img draggable="false" src="/static/images/mun/check-circle.svg" alt="check circle"> 548 <div><span>
548Works anywhere</span></div> 549 </li> 550 <li><img draggable="false" src="/static/images/mun/check-circle.svg" alt="check circle"> 551 <div><span>Undetected</span> by universities</div> 552 </li> 553 <li><img draggable="false" src="/static/images/mun/check-circle.svg" alt="check circle"> 554 <div><span>Accurate</span> step-by-step solutions</div> 555 </li> 556 <li><img draggable="false" src="/static/images/mun/check-circle.svg" alt="check circle"> 557 <div>Works on <span>graph & image questions</span></div> 558 </li> 559 </ul> 560 561 <button data-bs-toggle="modal" from-source="pricing" data-bs-target="#exampleModal" type="button" 562 class="cmn-btn btn-whtie w-100">Get Started</button> 563 564 <div class="bottom-content"> 565 <p>Cancel anytime | Renews at $19.99/month</p> 566 <ul class="d-flex gap-3 gap-sm-4 payment-list justify-content-center"> 567 <li><img draggable="false" loading="lazy" src="/static/images/mun/payment1.png" alt="visa"></li> 568 <li><img draggable="false" loading="lazy" src="/static/images/mun/payment2.png" alt="mastercard"></li> 569 <li><img draggable="false" loading="lazy" src="/static/images/mun/payment3.png" alt="amex"></li> 570 <li><img draggable="false" loading="lazy" src="/static/images/mun/payment4.png" alt="discover"></li> 571 <li><img draggable="false" loading="lazy" src="/static/images/mun/payment5.png" alt="paypal"></li> 572 <li><img draggable="false" loading="lazy" src="/static/images/mun/payment6.png" alt="apple pay"></li> 573 <li><img draggable="false" loading="lazy" src="/static/images/mun/payment7.png" alt="g-pay"></li> 574 </ul> 575 </div> 576 </div> 577 </div> 578 </div> 579 </div> 580</div> 581`, 582 payment: ` 583<div class="fullscreen-overlay"></div> 584`, 585}; 586 587// Initialize modals when needed 588document.addEventListener("DOMContentLoaded", () => { 589 // Expose the OS scrollbar width as --ct-scrollbar-width so fixed, centered 590 // chrome (the floating .header-area nav) can stay aligned when Bootstrap's 591 // modal scroll-lock removes the page scrollbar. Bootstrap pads the <body> 592 // by this width to keep body content from shifting, but a position:fixed + 593 // margin-inline:auto element isn't covered by that padding and would drift. 594 // Resolves to 0 for overlay scrollbars (no shift, so no compensation). 595 const sbProbe = document.createElement("div"); 596 sbProbe.style.cssText = 597 "position:absolute;top:-9999px;width:100px;height:100px;overflow:scroll;visibility:hidden;"; 598 document.body.appendChild(sbProbe); 599 document.documentElement.style.setProperty( 600 "--ct-scrollbar-width", 601 sbProbe.offsetWidth - sbProbe.clientWidth + "px" 602 ); 603 sbProbe.remove(); 604 605 // Create a container for all modals if it doesn't exist 606 let modalContainer = document.getElementById("modal-container"); 607 if (!modalContainer) { 608 modalContainer = document.createElement("div"); 609 modalContainer.id = "modal-container"; 610 document.body.appendChild(modalContainer); 611 } 612 613 // Pre-render all modals once 614 Object.entries(MODAL_TEMPLATES).forEach(([key, template]) => { 615 modalContainer.insertAdjacentHTML("beforeend", template); 616 }); 617 618 // Add focus management for modals 619 const modals = document.querySelectorAll(".modal"); 620 modals.forEach((modal) => { 621 // Store the element that had focus before modal was opened 622 let previousActiveElement; 623 624 modal.addEventListener("show.bs.modal", () => { 625 previousActiveElement = document.activeElement; 626 }); 627 628 modal.addEventListener("shown.bs.modal", () => { 629 // Focus the first input element in the modal 630 const firstInput = modal.querySelector( 631 'input:not([type="hidden"])' 632 ); 633 if (firstInput) { 634 firstInput.focus(); 635 // If it's a text-like input, also select its content for easy overwriting 636 if ( 637 ["text", "email", "tel", "password"].includes( 638 firstInput.type 639 ) 640 ) { 641 firstInput.select(); 642 } 643 } 644 }); 645 646 modal.addEventListener("hide.bs.modal", () => { 647 // Remove focus from any element inside modal before it closes 648 const focusedElement = document.activeElement; 649 if (modal.contains(focusedElement)) { 650 focusedElement.blur(); 651 } 652 }); 653 654 modal.addEventListener("hidden.bs.modal", () => {
655 // Return focus to the element that had focus before modal was opened 656 if (previousActiveElement) { 657 previousActiveElement.focus(); 658 } 659 }); 660 }); 661 662 let currentModal = null; 663 let appleSignInInitialized = false; 664 665 initializeAppleSignIn(); 666 667 // Handle modal events 668 const loginModal = document.getElementById("examplesigninModal"); 669 const signupModal = document.getElementById("exampleModal"); 670 const appleButton = document.getElementById("appleid-signin"); 671 672 // Remove button from DOM initially 673 appleButton.remove(); 674 675 loginModal.addEventListener("show.bs.modal", function () { 676 if (currentModal) { 677 const modal = bootstrap.Modal.getInstance( 678 document.getElementById(currentModal) 679 ); 680 modal.hide(); 681 } 682 currentModal = "examplesigninModal"; 683 const container = loginModal.querySelector("#login-button-container"); 684 if (!container.contains(appleButton)) { 685 container.appendChild(appleButton); 686 setTimeout(reinitializeAppleButton, 100); 687 } 688 }); 689 690 signupModal.addEventListener("show.bs.modal", function () { 691 if (currentModal) { 692 const modal = bootstrap.Modal.getInstance( 693 document.getElementById(currentModal) 694 ); 695 modal.hide(); 696 } 697 currentModal = "exampleModal"; 698 const container = signupModal.querySelector("#signup-button-container"); 699 if (!container.contains(appleButton)) { 700 container.appendChild(appleButton); 701 setTimeout(reinitializeAppleButton, 100); 702 } 703 }); 704 705 // Watch for clicks on Apple button 706 document.addEventListener("click", function (event) { 707 const button = event.target.closest("#appleid-signin"); 708 if (button) { 709 const container = button.closest(".apple-button-container"); 710 const mode = 711 currentModal === "examplesigninModal" ? "login" : "signup"; 712 713 if (container) { 714 container.classList.add("loading"); 715 console.log("Button clicked:", mode); 716 717 setTimeout(() => { 718 container.classList.remove("loading"); 719 }, 5000); 720 } 721 } 722 }); 723 724 document.addEventListener("AppleIDSignInOnFailure", (error) => { 725 document 726 .querySelectorAll(".apple-button-container") 727 .forEach((container) => { 728 container.classList.remove("loading"); 729 }); 730 console.error("Apple Sign In Failed:", error); 731 }); 732 733 async function initializeAppleSignIn() { 734 try { 735 // Check if we already have a state in cookies 736 const cookies = document.cookie.split(";"); 737 let stateFromCookie = null; 738 for (let cookie of cookies) { 739 const [name, value] = cookie.trim().split("="); 740 if (name === "apple_auth_state") { 741 stateFromCookie = value; 742 break; 743 } 744 } 745 746 // If no state in cookies, fetch new one 747 if (!stateFromCookie) { 748 // Show loading state 749 const currentContainer = document.querySelector( 750 `#${currentModal} .apple-button-container` 751 ); 752 if (currentContainer) { 753 currentContainer.classList.add("loading"); 754 } 755 756 try { 757 const response = await fetch("/api/apple-auth-state"); 758 const data = await response.json(); 759 stateFromCookie = data.state; 760 } finally { 761 // Remove loading state regardless of success/failure 762 if (currentContainer) { 763 currentContainer.classList.remove("loading"); 764 } 765 } 766 } 767 768 // Update meta tag 769 const metaState = document.createElement("meta"); 770 metaState.name = "appleid-signin-state"; 771 metaState.content = stateFromCookie; 772 document.head.appendChild(metaState); 773 774 // Initialize Apple Sign In 775 AppleID.auth.init({ 776 clientId: "io.collegetools.webapp", 777 scope: "name email", 778 redirectURI: "https://www.mindko.com/login/apple/authorized", 779 state: stateFromCookie, 780 }); 781 782 appleSignInInitialized = true; 783 } catch (error) { 784 console.error("Error initializing Apple Sign In:", error); 785 } 786 } 787 788 function reinitializeAppleButton() { 789 if (!appleSignInInitialized) return; 790 791 // Force re-render of Apple button 792 const button = document.getElementById("appleid-signin"); 793 if (button) { 794 button.innerHTML = ""; 795 AppleID.auth.init({ 796 clientId: "io.collegetools.webapp", 797 scope: "name email", 798 redirectURI: "https://www.mindko.com/login/apple/authorized", 799 }); 800 } 801 } 802});
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.