1getMyCookie = function (name) { 2 var value = document.cookie.split(/;\s*/).find((row) => row.startsWith(name)); 3 if (value) { 4 return decodeURIComponent(value.split("=")[1]); 5 } 6 return ""; 7}; 8 9 10let curr_page_url = window.location.href; 11let curr_content_id = window.location.hostname.replace(/[^\/]*:\/\//, "").replace(/^www\./, "").replace(/(.*)\.[^\.]+$/, "$1") + "_" + document.location.pathname.replace(/^\//, "").replaceAll(/\//g, "_").replace(/\.html?$/, ""); 12let curr_user_login_token = (new URLSearchParams(window.location.search).get("token") || getMyCookie("login_token")); 13var curr_user_actv_sts = 0; 14var page_key =Math.floor(Date.now() + Math.random()); 15//alert(document.readyState); 16if(document.readyState === 'loading') { 17 localStorage.setItem("page_key", page_key); 18// alert(page_key); 19} 20 21Date.prototype.today = function () { 22 return this.getFullYear() +"-"+(((this.getMonth()+1) < 10)?"0":"") + (this.getMonth()+1) +"-"+ ((this.getDate() < 10)?"0":"") + this.getDate() ; 23} 24 25// For the time now 26Date.prototype.timeNow = function () { 27 return ((this.getHours() < 10)?"0":"") + this.getHours() +":"+ ((this.getMinutes() < 10)?"0":"") + this.getMinutes() +":"+ ((this.getSeconds() < 10)?"0":"") + this.getSeconds(); 28} 29 30jQuery.ajax({ 31 type: 'POST', 32 dataType : 'json', 33 url: `https://www.eslfast.com/membership/api/valid-token/${curr_user_login_token}` 34}).done(function (res) { 35 //update_active_on_page(curr_page_url, curr_content_id, curr_user_login_token); 36 37 if ((res.token_key != '') /*&& (res.memb_status == 1)*/) { 38 curr_user_actv_sts = 1; 39 if(res.memb_status != 1){ 40 console.log('Adblock detected or not1'); 41 startAntiAdblock(); 42 } 43 setInterval(function () { 44// let curr_date = new Date().today(); 45// let datetime = new Date().today() + " " + new Date().timeNow(); 46// console.log(datetime); 47 update_active_on_page(curr_page_url, curr_content_id, curr_user_login_token); 48 }, 130000); 49 }else{ 50 51 console.log('Adblock detected or not2'); 52 startAntiAdblock(); 53 } 54}).fail(function (jqXHR, textStatus) { 55 console.log('Adblock detected or not3'); 56 startAntiAdblock(); 57}); 58update_active_on_page = (curr_page_url, curr_content_id, curr_user_login_token) => { 59 let curr_date = new Date().today(); 60 let curr_datetime = new Date().today() + " " + new Date().timeNow(); 61 jQuery.ajax({ 62 type: 'POST', 63 dataType : 'json', 64 data:{curr_page_url:curr_page_url, curr_content_id:curr_content_id, curr_user_login_token:curr_user_login_token,curr_date: curr_date, curr_datetime:curr_datetime, page_key:page_key}, 65 url: `https://www.eslfast.com/membership/api/time-spend-course/` 66 }).done(function (res) { 67 68 }).fail(function (jqXHR, textStatus) { 69 70 }); 71} 72// Every 3 min 1reward 73let rewardTimer = null; 74let confirmTimer = null; 75 76let lastActivity = Date.now(); 77let popupShowing = false; 78let rewardStopped = false; 79 80// User activity events 81[ 82 "mousemove", 83 "mousedown", 84 "click", 85 "scroll", 86 "keydown", 87 "touchstart" 88].forEach(function (event) { 89 document.addEventListener(event, function () { 90 lastActivity = Date.now(); 91 }, true); 92}); 93 94// User switches tab 95document.addEventListener("visibilitychange", function () { 96 if (!document.hidden) { 97 lastActivity = Date.now(); 98 } 99}); 100 101// Start reward timer 102rewardTimer = setInterval(checkReward, 180000); // Every 3 min 103 104function checkReward() { 105 106 if (rewardStopped) 107 return; 108 109 // inactive for 7 min 110 let inactiveTime = Date.now() - lastActivity; 111 112 if (inactiveTime >= 420000) { 113 114 if (!popupShowing) { 115 askUserActive(); 116 } 117 118 return; 119 } 120 121 every3minReward( 122 curr_page_url, 123 curr_content_id, 124 curr_user_login_token 125 ); 126} 127 128function askUserActive() { 129 if(curr_user_actv_sts == 0){ 130 return; 131 } 132 popupShowing = true; 133 134 showDialog({ 135 title: "Activity Check", 136 message: "You've been inactive for a while.<br><br>Click <b>Continue</b> to keep earning rewards.", 137 okText: "Continue", 138 showCancel: true, 139 140 onOk: function () { 141 142 popupShowing = false;
143 144 lastActivity = Date.now(); 145 146 every3minReward( 147 curr_page_url, 148 curr_content_id, 149 curr_user_login_token 150 ); 151 }, 152 153 onCancel: function () { 154 155 popupShowing = false; 156 157 stopRewardSystem(); 158 } 159 }); 160 161} 162 163function stopRewardSystem() { 164 165 rewardStopped = true; 166 167 clearInterval(rewardTimer); 168 169 showDialog({ 170 title: "Reward Stopped", 171 message: "Reward tracking has been stopped because no activity was detected.", 172 okText: "Close", 173 showCancel: false 174 }); 175} 176 177function every3minReward(curr_page_url, curr_content_id, curr_user_login_token) { 178 179 let curr_date = new Date().today(); 180 181 $.ajax({ 182 type: "POST", 183 dataType: "json", 184 url: "https://www.eslfast.com/membership/api/everyThreeMinReward/", 185 data: { 186 curr_page_url, 187 curr_content_id, 188 curr_user_login_token, 189 curr_date, 190 page_key 191 } 192 }) 193 .done(function(res){ 194 195 if(res.status === "error"){ 196 197 const storageKey = "every3minRewardErrorShown"; 198 const now = Date.now(); 199 200 // 10 minutes 201 const showAgainAfter = 120 * 60 * 1000; 202 203 const lastShown = localStorage.getItem(storageKey); 204 205 // Show only if never shown OR 10 minutes have passed 206 if (!lastShown || (now - parseInt(lastShown)) >= showAgainAfter) { 207 showInvalidLoginPopup( 208 res.msg + 209 `<div> 210 <a href="https://www.eslfast.com/" 211 style="display:inline-block;padding:12px 24px;background:#ff4d4d;color:#fff;text-decoration:none;border-radius:10px;font-weight:bold;"> 212 Sign In Now 213 </a> 214 </div>` 215 ); 216 // Save current time 217 localStorage.setItem(storageKey, now); 218 } 219 } 220 221 }); 222} 223 224function showDialog(options = {}) { 225 226 // Remove old dialog if exists 227 const old = document.getElementById("customDialog"); 228 if (old) old.remove(); 229 230 const dialog = document.createElement("div"); 231 dialog.id = "customDialog"; 232 233 dialog.innerHTML = ` 234 <div class="dialog-overlay"></div> 235 236 <div class="dialog-box"> 237 238 <div class="dialog-title">${options.title || "Message"}</div> 239 240 <div class="dialog-body"> 241 ${options.message || ""} 242 </div> 243 244 <div class="dialog-footer"> 245 ${ 246 options.showCancel !== false 247 ? `<button class="dialog-btn dialog-cancel">Cancel</button>` 248 : "" 249 } 250 251 <button class="dialog-btn dialog-ok"> 252 ${options.okText || "OK"} 253 </button> 254 </div> 255 256 </div> 257 `; 258 259 document.body.appendChild(dialog); 260 261 if (!document.getElementById("dialogStyle")) { 262 263 const style = document.createElement("style"); 264 265 style.id = "dialogStyle"; 266 267 style.innerHTML = ` 268 #customDialog{ 269 position:fixed; 270 inset:0; 271 z-index:999999; 272 } 273 274 .dialog-overlay{ 275 position:absolute; 276 inset:0; 277 background:rgba(0,0,0,.45); 278 } 279 280 .dialog-box{ 281 position:absolute; 282 left:50%; 283 top:50%; 284 transform:translate(-50%,-50%); 285 width:380px; 286 max-width:90%; 287 background:#fff; 288 border-radius:10px; 289 overflow:hidden; 290 font-family:Arial,sans-serif; 291 box-shadow:0 10px 30px rgba(0,0,0,.3); 292 } 293 294 .dialog-title{ 295 padding:15px; 296 font-size:18px; 297 font-weight:bold; 298 border-bottom:1px solid #ddd; 299 } 300 301 .dialog-body{ 302 padding:20px; 303 line-height:1.5; 304 } 305 306 .dialog-footer{ 307 padding:15px; 308 text-align:right; 309 border-top:1px solid #ddd; 310 } 311 312 .dialog-btn{ 313 padding:8px 20px; 314 margin-left:10px; 315 cursor:pointer; 316 border:none; 317 border-radius:5px; 318 } 319 320 .dialog-ok{ 321 background:#0d6efd; 322 color:#fff; 323 } 324 325 .dialog-cancel{ 326 background:#6c757d; 327 color:#fff; 328 } 329 `; 330 331 document.head.appendChild(style); 332 } 333 334 dialog.querySelector(".dialog-ok").onclick = function () { 335 336 dialog.remove(); 337 338 if (typeof options.onOk === "function") 339 options.onOk(); 340 }; 341 342 const cancel = dialog.querySelector(".dialog-cancel"); 343 344 if (cancel) { 345 cancel.onclick = function () { 346 347 dialog.remove(); 348 349 if (typeof options.onCancel === "function") 350 options.onCancel(); 351 }; 352 } 353} 354//------ 355 356//const chat_socket = 'https://socket.eslfast.com/'; 357//const socket = io(chat_socket, { 358// query: { userId: curr_user_login_token, pageId: curr_content_id } 359// }); 360// 361//socket.emit('joinRoom', curr_content_id); 362// 363//socket.on('userOnline', (data) => { 364// const { userId, pageId } = data; 365// alert(`User ${userId} is now online ${pageId}`); 366//});
367//socket.on('userOffline', (data) => { 368// const { userId, pageId } = data; 369// alert(`User ${userId} is now offline ${pageId} `); 370//}); 371 372 function completePageTask(point = 5){ 373 // alert('vv : '+ curr_user_actv_sts); 374 let curr_datetime = new Date().today() + " " + new Date().timeNow(); 375 if(curr_user_actv_sts == 1){ 376 jQuery.ajax({ 377 type: 'POST', 378 dataType : 'json', 379 data:{curr_page_url:curr_page_url, 380 curr_content_id:curr_content_id, 381 curr_user_login_token:curr_user_login_token, 382 curr_datetime:curr_datetime, 383 page_key:page_key, 384 point:point 385 }, 386 url: `https://www.eslfast.com/membership/api/page-task-complete/` 387 }).done(function (res) { 388 if(res.status=="success"){ 389 showLessonCompleteAnimation(res.total_point, point); 390 //If promte 391 if(res.promot_status == 1){ 392 setTimeout(function() { 393 let parentDivxc = $('.lesson-complete-popup').parent('div'); 394 if (parentDivxc.length) { 395 parentDivxc.remove(); 396 } 397 const audiox = new Audio('https://www.eslfast.com/js/sound/applause_sound.mp3'); 398 audiox.play().catch(err => { 399 console.warn('Audio permission denied:', err.message); 400 }); 401 402 let prom_txt = `${res.medal_tire} unlocked! Your excellence is now officially tiered .<img src='https://www.eslfast.com/js/img/Medal_Tier_${res.medal_tire}.png' width='50' />`; 403 showLessonCompleteAnimationText(prom_txt); 404 }, 1000); 405 } 406 }else{ 407 if (res && typeof res === 'object' && 'msg' in res) { 408 if(res.msg == "Already completed"){ 409 showAlreadyCompletedPopup(); 410 deleteCookieIfPresent('pageQuestionAnswer'); 411 }else{ 412 showInvalidLoginPopup(res.msg); 413 } 414 }else{ 415 showTryAgainPopup(); 416 } 417 } 418 }).fail(function (jqXHR, textStatus) { 419 420 }); 421 } 422 } 423 424 //point for dictation 425 function completeDictPageTask(point = 5){ 426 // alert('vv : '+ curr_user_actv_sts); 427 let curr_datetime = new Date().today() + " " + new Date().timeNow(); 428 // if(curr_user_actv_sts == 1){ 429 jQuery.ajax({ 430 type: 'POST', 431 dataType : 'json', 432 data:{curr_page_url:curr_page_url, 433 curr_content_id:curr_content_id, 434 curr_user_login_token:curr_user_login_token, 435 curr_datetime:curr_datetime, 436 page_key:page_key, 437 point:point 438 }, 439 url: `https://www.eslfast.com/membership/api/page-task-complete/` 440 }).done(function (res) { 441 if(res.status=="success"){ 442 showLessonCompleteAnimation(res.total_point, point); 443 //If promte 444 if(res.promot_status == 1){ 445 setTimeout(function() { 446 let parentDivxc = $('.lesson-complete-popup').closest('div'); 447 if (parentDivxc.length) { 448 parentDivxc.remove(); 449 } 450 const audiox = new Audio('https://www.eslfast.com/js/sound/applause_sound.mp3'); 451 audiox.play().catch(err => { 452 console.warn('Audio permission denied:', err.message); 453 }); 454 455// let prom_txt = `${res.medal_tire} unlocked! Your excellence is now officially tiered .<img src='https://www.eslfast.com/js/img/Medal_Tier_${res.medal_tire}.png' width='50' />`; 456// showLessonCompleteAnimationText(prom_txt); 457 showTierPromotionPopup(res.medal_tire); 458 }, 1000); 459 } 460 }else{ 461 if (res && typeof res === 'object' && 'msg' in res) { 462 if(res.msg == "Already completed"){ 463 showAlreadyCompletedPopup(); 464 deleteCookieIfPresent('pageQuestionAnswer'); 465 }else{ 466 showInvalidLoginPopup(res.msg); 467 } 468 }else{ 469 showTryAgainPopup(); 470 } 471 } 472 }).fail(function (jqXHR, textStatus) { 473 474 }); 475 // } 476 } 477 478 479 480function showLessonCompleteAnimation(total_point, curr_point = 5) { 481 // Try to play audio 482 const audio = new Audio('https://www.eslfast.com/js/sound/sound1.mp3'); 483 audio.play().catch(err => { 484 console.warn('Audio permission denied:', err.message); 485 }); 486 487 // Random praise phrase 488 const phrases = ["Great Job!", "Well Done!", "Awesome!", "Amazing!", "Excellent!", "Great!"]; 489 const randomPhrase = phrases[Math.floor(Math.random() * phrases.length)]; 490 491 // Create overlay
492 const overlay = document.createElement('div'); 493 Object.assign(overlay.style, { 494 position: 'fixed', 495 top: 0, 496 left: 0, 497 width: '100vw', 498 height: '100vh', 499 backgroundColor: 'rgba(0,0,0,0.5)', 500 display: 'flex', 501 alignItems: 'center', 502 justifyContent: 'center', 503 zIndex: 9999, 504 padding: '20px', 505 }); 506 507 // Create popup 508 const popup = document.createElement('div'); 509 popup.className = 'lesson-complete-popup'; 510 Object.assign(popup.style, { 511 background: 'linear-gradient(135deg, #fff8dc, #e0ffe0)', 512 borderRadius: '20px', 513 padding: '30px 20px', 514 boxShadow: '0 0 30px rgba(0,0,0,0.3)', 515 textAlign: 'center', 516 position: 'relative', 517 animation: 'bounceIn 0.8s ease-out, glowPulse 3s infinite alternate', 518 maxWidth: '90%', 519 width: '400px', 520 fontFamily: 'Segoe UI, sans-serif', 521 color: '#1a1a1a', 522 overflow: 'hidden', 523 }); 524 525 // Character Image 526 const character = document.createElement('img'); 527 character.src = 'https://www.eslfast.com/js/img/susan3.jpg'; 528 Object.assign(character.style, { 529 width: '100px', 530 borderRadius: '50%', 531 animation: 'floatSwing 3s ease-in-out infinite', 532 marginBottom: '15px', 533 display: 'block', 534 marginLeft: 'auto', 535 marginRight: 'auto' 536 }); 537 538 // Heading 539 const heading = document.createElement('h2'); 540 heading.innerText = 'ð Completed!'; 541 Object.assign(heading.style, { 542 marginBottom: '15px', 543 fontSize: '28px', 544 color: '#006400', 545 textAlign: 'center', 546 }); 547 548 // Random praise 549 const praise = document.createElement('p'); 550 praise.innerText = randomPhrase; 551 Object.assign(praise.style, { 552 fontSize: '22px', 553 color: '#222', 554 fontWeight: 'bold', 555 marginBottom: '20px', 556 textAlign: 'center', 557 }); 558 559 // Subtext 560 const subtext = document.createElement('p'); 561 subtext.innerHTML = `<div style="text-align:center;"> 562 ${curr_point > 0 ? `Youâve earned <strong>â¡${curr_point} points</strong>` : ''} 563 ${total_point > 0 ? `<br>and <strong>${total_point} total points</strong> so far!` : ''} 564</div>`; 565 Object.assign(subtext.style, { 566 fontSize: '18px', 567 color: '#333', 568 marginBottom: '20px', 569 textAlign: 'center', 570 }); 571 572 // Close button 573 const closeBtn = document.createElement('div'); 574 closeBtn.innerHTML = '×'; 575 Object.assign(closeBtn.style, { 576 position: 'absolute', 577 top: '0px', 578 right: '7px', 579 fontSize: '26px', 580 color: '#666', 581 cursor: 'pointer', 582 border: '1px dotted', 583 padding: '0px 8px 0px 8px' 584 }); 585 closeBtn.onclick = () => overlay.remove(); 586 587 // Append elements 588 popup.appendChild(closeBtn); 589 popup.appendChild(character); 590 popup.appendChild(heading); 591 popup.appendChild(praise); 592 popup.appendChild(subtext); 593 overlay.appendChild(popup); 594 document.body.appendChild(overlay); 595 596 // Confetti animation 597 for (let i = 0; i < 50; i++) { 598 const confetti = document.createElement('div'); 599 Object.assign(confetti.style, { 600 position: 'fixed', 601 top: '50%', 602 left: '50%', 603 width: '8px', 604 height: '8px', 605 backgroundColor: `hsl(${Math.random()*360}, 100%, 50%)`, 606 borderRadius: '50%', 607 transform: `translate(-50%, -50%)`, 608 animation: `confettiFly ${1 + Math.random()*1.5}s ease-out forwards`, 609 zIndex: 10000 610 }); 611 confetti.style.setProperty('--x', `${(Math.random() - 0.5) * 400}px`); 612 confetti.style.setProperty('--y', `${(Math.random() - 0.5) * 400}px`); 613 document.body.appendChild(confetti); 614 setTimeout(() => confetti.remove(), 3000); 615 } 616 617 // Style animations 618 const style = document.createElement('style'); 619 style.textContent = ` 620 @keyframes bounceIn { 621 0% { transform: scale(0.7); opacity: 0; } 622 80% { transform: scale(1.1); opacity: 1; } 623 100% { transform: scale(1); } 624 } 625 @keyframes floatSwing { 626 0%, 100% { transform: translateY(0) rotate(0deg); } 627 50% { transform: translateY(-10px) rotate(3deg); } 628 } 629 @keyframes glowPulse { 630 0% { box-shadow: 0 0 10px #aaffaa; } 631 100% { box-shadow: 0 0 30px #55ff55; } 632 } 633 @keyframes confettiFly { 634 to { 635 transform: translate(calc(-50% + var(--x)), calc(-50% + var(--y))) rotate(720deg); 636 opacity: 0; 637 } 638 } 639 640 /* Responsive */ 641 @media (max-width: 768px) { 642 .lesson-complete-popup { 643 width: 90% !important; 644 padding: 20px 15px !important; 645 } 646 } 647 648 @media (max-width: 480px) { 649 .lesson-complete-popup { 650 width: 95% !important; 651 font-size: 16px !important; 652 } 653 } 654 `; 655 document.head.appendChild(style); 656} 657 658function showLessonCompleteAnimationText(txt_msg) { 659 // Try to play audio 660 const audio = new Audio('https://www.eslfast.com/js/sound/sound1.mp3'); 661 audio.play().catch(err => { 662 console.warn('Audio permission denied:', err.message); 663 }); 664 665 // Random praise phrase 666 const phrases = ["Great Job!", "Well Done!", "Awesome!", "Amazing!", "Excellent!", "Great!"]; 667 const randomPhrase = phrases[Math.floor(Math.random() * phrases.length)]; 668 669 // Create overlay
670 const overlay = document.createElement('div'); 671 Object.assign(overlay.style, { 672 position: 'fixed', 673 top: 0, 674 left: 0, 675 width: '100vw', 676 height: '100vh', 677 backgroundColor: 'rgba(0,0,0,0.5)', 678 display: 'flex', 679 alignItems: 'center', 680 justifyContent: 'center', 681 zIndex: 9999, 682 padding: '20px', 683 }); 684 685 // Create popup 686 const popup = document.createElement('div'); 687 popup.className = 'lesson-complete-popup'; 688 Object.assign(popup.style, { 689 background: 'linear-gradient(135deg, #fff8dc, #e0ffe0)', 690 borderRadius: '20px', 691 padding: '30px 20px', 692 boxShadow: '0 0 30px rgba(0,0,0,0.3)', 693 textAlign: 'center', 694 position: 'relative', 695 animation: 'bounceIn 0.8s ease-out, glowPulse 3s infinite alternate', 696 maxWidth: '90%', 697 width: '400px', 698 fontFamily: 'Segoe UI, sans-serif', 699 color: '#1a1a1a', 700 overflow: 'hidden', 701 }); 702 703 // Character Image 704 const character = document.createElement('img'); 705 character.src = 'https://www.eslfast.com/js/img/susan3.jpg'; 706 Object.assign(character.style, { 707 width: '100px', 708 borderRadius: '50%', 709 animation: 'floatSwing 3s ease-in-out infinite', 710 marginBottom: '15px', 711 display: 'block', 712 marginLeft: 'auto', 713 marginRight: 'auto' 714 }); 715 716 // Heading 717 const heading = document.createElement('h2'); 718 heading.innerText = 'ð Completed!'; 719 Object.assign(heading.style, { 720 marginBottom: '15px', 721 fontSize: '28px', 722 color: '#006400', 723 textAlign: 'center', 724 }); 725 726 // Random praise 727 const praise = document.createElement('p'); 728 praise.innerText = randomPhrase; 729 Object.assign(praise.style, { 730 fontSize: '22px', 731 color: '#222', 732 fontWeight: 'bold', 733 marginBottom: '20px', 734 textAlign: 'center', 735 }); 736 737 // Subtext 738 const subtext = document.createElement('p'); 739 subtext.innerHTML = `<div style="text-align:center;">${txt_msg}</div>`; 740 Object.assign(subtext.style, { 741 fontSize: '18px', 742 color: '#333', 743 marginBottom: '20px', 744 textAlign: 'center', 745 }); 746 747 // Close button 748 const closeBtn = document.createElement('div'); 749 closeBtn.innerHTML = '×'; 750 Object.assign(closeBtn.style, { 751 position: 'absolute', 752 top: '0px', 753 right: '7px', 754 fontSize: '26px', 755 color: '#666', 756 cursor: 'pointer', 757 border: '1px dotted', 758 padding: '0px 8px 0px 8px' 759 }); 760 closeBtn.onclick = () => overlay.remove(); 761 762 // Append elements 763 popup.appendChild(closeBtn); 764 popup.appendChild(character); 765 popup.appendChild(heading); 766 popup.appendChild(praise); 767 popup.appendChild(subtext); 768 overlay.appendChild(popup); 769 document.body.appendChild(overlay); 770 771 // Confetti animation 772 for (let i = 0; i < 50; i++) { 773 const confetti = document.createElement('div'); 774 Object.assign(confetti.style, { 775 position: 'fixed', 776 top: '50%', 777 left: '50%', 778 width: '8px', 779 height: '8px', 780 backgroundColor: `hsl(${Math.random()*360}, 100%, 50%)`, 781 borderRadius: '50%', 782 transform: `translate(-50%, -50%)`, 783 animation: `confettiFly ${1 + Math.random()*1.5}s ease-out forwards`, 784 zIndex: 10000 785 }); 786 confetti.style.setProperty('--x', `${(Math.random() - 0.5) * 400}px`); 787 confetti.style.setProperty('--y', `${(Math.random() - 0.5) * 400}px`); 788 document.body.appendChild(confetti); 789 setTimeout(() => confetti.remove(), 3000); 790 } 791 792 // Style animations 793 const style = document.createElement('style'); 794 style.textContent = ` 795 @keyframes bounceIn { 796 0% { transform: scale(0.7); opacity: 0; } 797 80% { transform: scale(1.1); opacity: 1; } 798 100% { transform: scale(1); } 799 } 800 @keyframes floatSwing { 801 0%, 100% { transform: translateY(0) rotate(0deg); } 802 50% { transform: translateY(-10px) rotate(3deg); } 803 } 804 @keyframes glowPulse { 805 0% { box-shadow: 0 0 10px #aaffaa; } 806 100% { box-shadow: 0 0 30px #55ff55; } 807 } 808 @keyframes confettiFly { 809 to { 810 transform: translate(calc(-50% + var(--x)), calc(-50% + var(--y))) rotate(720deg); 811 opacity: 0; 812 } 813 } 814 815 /* Responsive */ 816 @media (max-width: 768px) { 817 .lesson-complete-popup { 818 width: 90% !important; 819 padding: 20px 15px !important; 820 } 821 } 822 823 @media (max-width: 480px) { 824 .lesson-complete-popup { 825 width: 95% !important; 826 font-size: 16px !important; 827 } 828 } 829 `; 830 document.head.appendChild(style); 831} 832 833function showAlreadyCompletedPopup() { 834 // Play audio 835 // const audio = new Audio('https://www.eslfast.com/js/sound/sound2.mp3'); 836 // audio.play().catch(err => { 837 // console.warn('Audio blocked:', err.message); 838 // }); 839 840 // Create overlay
841 const overlay = document.createElement('div'); 842 Object.assign(overlay.style, { 843 position: 'fixed', 844 top: '0', 845 left: '0', 846 width: '100vw', 847 height: '100vh', 848 backgroundColor: 'rgba(0,0,0,0.5)', 849 display: 'flex', 850 alignItems: 'center', 851 justifyContent: 'center', 852 zIndex: '9999', 853 padding: '20px', 854 }); 855 856 // Create popup box 857 const popup = document.createElement('div'); 858 popup.className = 'already-complete-popup'; 859 Object.assign(popup.style, { 860 background: 'linear-gradient(135deg, #003030, #004040)', 861 borderRadius: '20px', 862 padding: '30px 20px', 863 boxShadow: '0 0 30px rgba(0,0,0,0.4)', 864 position: 'relative', 865 animation: 'slideBounce 0.8s ease-out', 866 maxWidth: '90%', 867 width: '400px', 868 color: '#ffffff', 869 textAlign: 'center', 870 display: 'flex', 871 flexDirection: 'column', 872 alignItems: 'center', 873 fontFamily: 'Segoe UI, sans-serif', 874 }); 875 876 // Icon 877 const mascot = document.createElement('div'); 878 mascot.innerText = 'â '; 879 Object.assign(mascot.style, { 880 fontSize: '50px', 881 animation: 'pulseGlow 1.5s infinite', 882 marginBottom: '15px', 883 textAlign: 'center' 884 }); 885 886 // Title 887 const title = document.createElement('h2'); 888 title.innerText = 'Already Completed!'; 889 Object.assign(title.style, { 890 fontSize: '26px', 891 color: '#00ffaa', 892 marginBottom: '10px', 893 textAlign: 'center' 894 }); 895 896 // Message 897 const message = document.createElement('p'); 898 message.innerHTML = 'Youâve already finished this activity.<br>No need to do it again!'; 899 Object.assign(message.style, { 900 fontSize: '18px', 901 color: '#eeeeee', 902 marginBottom: '15px', 903 lineHeight: '1.5', 904 textAlign: 'center' 905 }); 906 907 // Close Button 908 const closeBtn = document.createElement('div'); 909 closeBtn.innerHTML = '×'; 910 Object.assign(closeBtn.style, { 911 position: 'absolute', 912 top: '0px', 913 right: '7px', 914 fontSize: '26px', 915 color: '#00ffaa', 916 cursor: 'pointer', 917 textAlign: 'center', 918 }); 919 closeBtn.onclick = () => overlay.remove(); 920 921 // Assemble popup 922 popup.appendChild(closeBtn); 923 popup.appendChild(mascot); 924 popup.appendChild(title); 925 popup.appendChild(message); 926 overlay.appendChild(popup); 927 document.body.appendChild(overlay); 928 929 // Animations and responsive styles 930 const style = document.createElement('style'); 931 style.textContent = ` 932 @keyframes pulseGlow { 933 0% { transform: scale(1); text-shadow: 0 0 5px #00ffaa; } 934 50% { transform: scale(1.15); text-shadow: 0 0 15px #00ffaa; } 935 100% { transform: scale(1); text-shadow: 0 0 5px #00ffaa; } 936 } 937 938 @keyframes slideBounce { 939 0% { transform: translateY(-100px); opacity: 0; } 940 70% { transform: translateY(10px); opacity: 1; } 941 100% { transform: translateY(0); } 942 } 943 944 @media (max-width: 768px) { 945 .already-complete-popup { 946 width: 90% !important; 947 padding: 20px 15px !important; 948 } 949 } 950 951 @media (max-width: 480px) { 952 .already-complete-popup { 953 width: 95% !important; 954 font-size: 16px !important; 955 } 956 } 957 `; 958 document.head.appendChild(style); 959} 960 961function showTryAgainPopup(Output_txt = '', point = 0) { 962 // Create overlay 963 const overlay = document.createElement('div'); 964 Object.assign(overlay.style, { 965 position: 'fixed', 966 top: '0', 967 left: '0', 968 width: '100vw', 969 height: '100vh', 970 backgroundColor: 'rgba(0,0,0,0.6)', 971 display: 'flex', 972 alignItems: 'center', 973 justifyContent: 'center', 974 zIndex: '9999', 975 padding: '20px' 976 }); 977 978 // Create popup 979 const popup = document.createElement('div'); 980 popup.className = 'try-again-popup'; 981 Object.assign(popup.style, { 982 background: 'linear-gradient(135deg, #400202, #300000)', 983 borderRadius: '20px', 984 padding: '30px 20px', 985 boxShadow: '0 0 25px rgba(0,0,0,0.4)', 986 maxWidth: '90%', 987 width: '400px', 988 color: '#ffffff', 989 textAlign: 'center', 990 fontFamily: 'Segoe UI, sans-serif', 991 animation: 'slideBounce 0.8s ease-out', 992 position: 'relative' 993 }); 994 995 // Animated Mascot Image 996 const mascot = document.createElement('div'); 997 mascot.innerHTML = `<img src="https://www.eslfast.com/js/img/susan3.jpg" style="width: 80px;">`; 998 Object.assign(mascot.style, { 999 animation: 'shake 1s infinite', 1000 marginBottom: '15px', 1001 textAlign: 'center' 1002 }); 1003 1004 // Title 1005 const title = document.createElement('h2'); 1006 title.textContent = 'You made some mistakes.'; 1007 Object.assign(title.style, { 1008 fontSize: '24px', 1009 color: '#ff6666', 1010 marginBottom: '10px', 1011 textAlign: 'center' 1012 }); 1013 1014 // Dynamic output 1015 const messageOutput = document.createElement('div'); 1016 messageOutput.innerHTML = Output_txt; 1017 Object.assign(messageOutput.style, { 1018 fontSize: '16px', 1019 color: '#ffffff', 1020 marginBottom: '10px', 1021 lineHeight: '1.5', 1022 textAlign: 'center' 1023 }); 1024 1025 // Subtitle 1026 const subtitle = document.createElement('div'); 1027 subtitle.textContent = `Try again! Youâll earn ${point>0?point:''} points when you get it 100% correct.`; 1028 Object.assign(subtitle.style, { 1029 fontSize: '16px', 1030 color: '#ffffff', 1031 marginBottom: '15px', 1032 lineHeight: '1.5', 1033 textAlign: 'center' 1034 }); 1035 1036 // Close button 1037 const closeBtn = document.createElement('div'); 1038 closeBtn.innerHTML = '×'; 1039 Object.assign(closeBtn.style, { 1040 position: 'absolute', 1041 top: '0px', 1042 right: '7px', 1043 fontSize: '26px', 1044 color: '#ff6666', 1045 cursor: 'pointer', 1046 1047 }); 1048 closeBtn.onclick = () => overlay.remove(); 1049 1050 // Assemble 1051 popup.appendChild(closeBtn); 1052 popup.appendChild(mascot); 1053 popup.appendChild(title); 1054 popup.appendChild(messageOutput); 1055 popup.appendChild(subtitle);
1056 overlay.appendChild(popup); 1057 document.body.appendChild(overlay); 1058 1059 // Styles & animations 1060 const style = document.createElement('style'); 1061 style.innerHTML = ` 1062 @keyframes shake { 1063 0% { transform: rotate(0); } 1064 25% { transform: rotate(-10deg); } 1065 50% { transform: rotate(10deg); } 1066 75% { transform: rotate(-5deg); } 1067 100% { transform: rotate(0); } 1068 } 1069 1070 @keyframes slideBounce { 1071 0% { transform: translateY(-80px); opacity: 0; } 1072 70% { transform: translateY(10px); opacity: 1; } 1073 100% { transform: translateY(0); } 1074 } 1075 1076 @media (max-width: 768px) { 1077 .try-again-popup { 1078 width: 90% !important; 1079 padding: 20px 15px !important; 1080 } 1081 } 1082 1083 @media (max-width: 480px) { 1084 .try-again-popup { 1085 width: 95% !important; 1086 font-size: 16px !important; 1087 } 1088 } 1089 `; 1090 document.head.appendChild(style); 1091} 1092 1093function checkAndSetTodayRewardCookie() { 1094 // Get today's date in YYYY-MM-DD format 1095 const today = new Date().toISOString().split('T')[0]; 1096 1097 // Function to get cookie value by name 1098 function getCookie(name) { 1099 const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); 1100 return match ? match[2] : null; 1101 } 1102 1103 // Check if cookie exists and matches today's date 1104 const cookieValue = getCookie("today_reward"); 1105 if (cookieValue === today) { 1106 console.log("Today's reward already claimed."); 1107 return true; // Already present 1108 } 1109 1110 1111 jQuery.ajax({ 1112 type: 'POST', 1113 dataType : 'json', 1114 data:{ 1115 curr_user_login_token:curr_user_login_token 1116 }, 1117 url: `https://www.eslfast.com/membership/api/get-user-yesterday-reward/` 1118 }).done(function (res) { 1119 if(res.status=="success"){ 1120 // Set the cookie with today's date (expires in 1 day) 1121 document.cookie = `today_reward=${today}; path=/; expires=${new Date(Date.now() + 86400000).toUTCString()}`; 1122 console.log("Today's reward set."); 1123 let total_point = res.total_point; 1124 let fnl_txt = "<span style='font-size: 30px;'>"+res.point+"</span><br>Your total score so far: <span style='font-size: 22px;'>"+total_point+"</span>"; 1125 if(res.point <= 0){ 1126 if(total_point > 0){ 1127 let fnl_ptt = parseInt(total_point)-5; 1128 fnl_txt = "<span style='font-size: 30px;'>"+res.point+"</span><br>Your total score so far: "+total_point+" - 5 = <span style='font-size: 22px;'>"+(fnl_ptt > 0 ? fnl_ptt : 0)+"</span><br>You must study at least 15 minutes daily to keep your points."; 1129 }else{ 1130 fnl_txt = "<span style='font-size: 30px;'>"+res.point+"</span><br>Your total score so far: <span style='font-size: 22px;'>"+total_point+"</span><br>You must study at least 15 minutes daily to keep your points."; 1131 } 1132 } 1133 dailyrewardpopup(fnl_txt) 1134 return false; // Was not present, now set 1135 } 1136 }).fail(function (jqXHR, textStatus) { 1137 1138 }); 1139} 1140 1141 checkAndSetTodayRewardCookie(); 1142 setInterval(function () { 1143 checkAndSetTodayRewardCookie(); 1144 }, 600000); 1145 1146function dailyrewardpopup(txt_msg) { 1147 // Try to play audio 1148 // const audio = new Audio('https://www.eslfast.com/js/sound/sound1.mp3'); 1149 // audio.play().catch(err => { 1150 // console.warn('Audio permission denied:', err.message); 1151 // }); 1152 1153 // Random praise phrase 1154 const phrases = ["Great Job!", "Well Done!", "Awesome!", "Amazing!", "Excellent!", "Great!"]; 1155 const randomPhrase = phrases[Math.floor(Math.random() * phrases.length)]; 1156 1157 // Create overlay 1158 const overlay = document.createElement('div'); 1159 Object.assign(overlay.style, { 1160 position: 'fixed', 1161 top: 0, 1162 left: 0, 1163 width: '100vw', 1164 height: '100vh', 1165 backgroundColor: 'rgba(0,0,0,0.5)', 1166 display: 'flex', 1167 alignItems: 'center', 1168 justifyContent: 'center', 1169 zIndex: 9999, 1170 padding: '20px', 1171 }); 1172 1173 // Create popup 1174 const popup = document.createElement('div'); 1175 popup.className = 'lesson-complete-popup'; 1176 Object.assign(popup.style, { 1177 background: 'linear-gradient(135deg, #fff8dc, #e0ffe0)', 1178 borderRadius: '20px', 1179 padding: '30px 20px',
1180 boxShadow: '0 0 30px rgba(0,0,0,0.3)', 1181 textAlign: 'center', 1182 position: 'relative', 1183 animation: 'bounceIn 0.8s ease-out, glowPulse 3s infinite alternate', 1184 maxWidth: '90%', 1185 width: '400px', 1186 fontFamily: 'Segoe UI, sans-serif', 1187 color: '#1a1a1a', 1188 overflow: 'hidden', 1189 }); 1190 1191 // Character Image 1192 const character = document.createElement('img'); 1193 character.src = 'https://www.eslfast.com/js/img/susan3.jpg'; 1194 Object.assign(character.style, { 1195 width: '100px', 1196 borderRadius: '50%', 1197 animation: 'floatSwing 3s ease-in-out infinite', 1198 marginBottom: '15px', 1199 display: 'block', 1200 marginLeft: 'auto', 1201 marginRight: 'auto' 1202 }); 1203 1204 // Heading 1205 const heading = document.createElement('h2'); 1206 heading.innerText = 'Yesterday Time Spent Reward'; 1207 Object.assign(heading.style, { 1208 marginBottom: '15px', 1209 fontSize: '28px', 1210 color: '#006400', 1211 textAlign: 'center', 1212 }); 1213 1214 // Subtext 1215 const subtext = document.createElement('p'); 1216 subtext.innerHTML = `<div style="text-align:center;"><b>${txt_msg}</b></div>`; 1217 Object.assign(subtext.style, { 1218 fontSize: '18px', 1219 color: '#333', 1220 marginBottom: '20px', 1221 textAlign: 'center', 1222 }); 1223 1224 // Close button 1225 const closeBtn = document.createElement('div'); 1226 closeBtn.innerHTML = '×'; 1227 Object.assign(closeBtn.style, { 1228 position: 'absolute', 1229 top: '0px', 1230 right: '7px', 1231 fontSize: '26px', 1232 color: '#666', 1233 cursor: 'pointer', 1234 border: '1px dotted', 1235 padding: '0px 8px 0px 8px' 1236 }); 1237 closeBtn.onclick = () => overlay.remove(); 1238 1239 // Append elements 1240 popup.appendChild(closeBtn); 1241 popup.appendChild(character); 1242 popup.appendChild(heading); 1243 popup.appendChild(subtext); 1244 overlay.appendChild(popup); 1245 document.body.appendChild(overlay); 1246 1247 // Confetti animation 1248 for (let i = 0; i < 50; i++) { 1249 const confetti = document.createElement('div'); 1250 Object.assign(confetti.style, { 1251 position: 'fixed', 1252 top: '50%', 1253 left: '50%', 1254 width: '8px', 1255 height: '8px', 1256 backgroundColor: `hsl(${Math.random()*360}, 100%, 50%)`, 1257 borderRadius: '50%', 1258 transform: `translate(-50%, -50%)`, 1259 animation: `confettiFly ${1 + Math.random()*1.5}s ease-out forwards`, 1260 zIndex: 10000 1261 }); 1262 confetti.style.setProperty('--x', `${(Math.random() - 0.5) * 400}px`); 1263 confetti.style.setProperty('--y', `${(Math.random() - 0.5) * 400}px`); 1264 document.body.appendChild(confetti); 1265 setTimeout(() => confetti.remove(), 3000); 1266 } 1267 1268 // Style animations 1269 const style = document.createElement('style'); 1270 style.textContent = ` 1271 @keyframes bounceIn { 1272 0% { transform: scale(0.7); opacity: 0; } 1273 80% { transform: scale(1.1); opacity: 1; } 1274 100% { transform: scale(1); } 1275 } 1276 @keyframes floatSwing { 1277 0%, 100% { transform: translateY(0) rotate(0deg); } 1278 50% { transform: translateY(-10px) rotate(3deg); } 1279 } 1280 @keyframes glowPulse { 1281 0% { box-shadow: 0 0 10px #aaffaa; } 1282 100% { box-shadow: 0 0 30px #55ff55; } 1283 } 1284 @keyframes confettiFly { 1285 to { 1286 transform: translate(calc(-50% + var(--x)), calc(-50% + var(--y))) rotate(720deg); 1287 opacity: 0; 1288 } 1289 } 1290 1291 /* Responsive */ 1292 @media (max-width: 768px) { 1293 .lesson-complete-popup { 1294 width: 90% !important; 1295 padding: 20px 15px !important; 1296 } 1297 } 1298 1299 @media (max-width: 480px) { 1300 .lesson-complete-popup { 1301 width: 95% !important; 1302 font-size: 16px !important; 1303 } 1304 } 1305 `; 1306 document.head.appendChild(style); 1307} 1308 1309function showInvalidLoginPopup(Output_txt = '') { 1310 // Create overlay 1311 const overlay = document.createElement('div'); 1312 Object.assign(overlay.style, { 1313 position: 'fixed', 1314 top: '0', 1315 left: '0', 1316 width: '100vw', 1317 height: '100vh', 1318 backgroundColor: 'rgba(0,0,0,0.6)', 1319 display: 'flex', 1320 alignItems: 'center', 1321 justifyContent: 'center', 1322 zIndex: '9999', 1323 padding: '20px' 1324 }); 1325 1326 // Create popup 1327 const popup = document.createElement('div'); 1328 popup.className = 'try-again-popup'; 1329 Object.assign(popup.style, { 1330 background: 'linear-gradient(135deg, #400202, #300000)', 1331 borderRadius: '20px', 1332 padding: '30px 20px', 1333 boxShadow: '0 0 25px rgba(0,0,0,0.4)', 1334 maxWidth: '90%', 1335 width: '400px', 1336 color: '#ffffff', 1337 textAlign: 'center', 1338 fontFamily: 'Segoe UI, sans-serif', 1339 animation: 'slideBounce 0.8s ease-out', 1340 position: 'relative' 1341 }); 1342 1343 // Animated Mascot Image 1344 const mascot = document.createElement('div'); 1345 mascot.innerHTML = `<img src="https://www.eslfast.com/js/img/susan3.jpg" style="width: 80px;">`; 1346 Object.assign(mascot.style, { 1347 animation: 'shake 1s infinite', 1348 marginBottom: '15px', 1349 textAlign: 'center' 1350 }); 1351 1352 // Dynamic output 1353 const messageOutput = document.createElement('div'); 1354 messageOutput.innerHTML = Output_txt; 1355 Object.assign(messageOutput.style, { 1356 fontSize: '16px', 1357 color: '#ffffff', 1358 marginBottom: '10px', 1359 lineHeight: '1.5', 1360 textAlign: 'center' 1361 }); 1362 1363 // Close button 1364 const closeBtn = document.createElement('div'); 1365 closeBtn.innerHTML = '×'; 1366 Object.assign(closeBtn.style, { 1367 position: 'absolute', 1368 top: '0px', 1369 right: '7px', 1370 fontSize: '26px', 1371 color: '#ff6666', 1372 cursor: 'pointer', 1373 1374 }); 1375 closeBtn.onclick = () => overlay.remove(); 1376 1377 // Assemble 1378 popup.appendChild(closeBtn); 1379 popup.appendChild(mascot); 1380 popup.appendChild(messageOutput);
1381 overlay.appendChild(popup); 1382 document.body.appendChild(overlay); 1383 1384 // Styles & animations 1385 const style = document.createElement('style'); 1386 style.innerHTML = ` 1387 @keyframes shake { 1388 0% { transform: rotate(0); } 1389 25% { transform: rotate(-10deg); } 1390 50% { transform: rotate(10deg); } 1391 75% { transform: rotate(-5deg); } 1392 100% { transform: rotate(0); } 1393 } 1394 1395 @keyframes slideBounce { 1396 0% { transform: translateY(-80px); opacity: 0; } 1397 70% { transform: translateY(10px); opacity: 1; } 1398 100% { transform: translateY(0); } 1399 } 1400 1401 @media (max-width: 768px) { 1402 .try-again-popup { 1403 width: 90% !important; 1404 padding: 20px 15px !important; 1405 } 1406 } 1407 1408 @media (max-width: 480px) { 1409 .try-again-popup { 1410 width: 95% !important; 1411 font-size: 16px !important; 1412 } 1413 } 1414 `; 1415 document.head.appendChild(style); 1416} 1417 1418 1419function showTierPromotionPopup(newTier, rewardPoints = 0) { 1420 // Play celebration sound 1421// const audio = new Audio('https://www.eslfast.com/js/sound/sound1.mp3'); 1422// audio.play().catch(err => console.warn('Audio blocked:', err.message)); 1423 1424 // Tier color themes 1425 const tierColors = { 1426 Bronze: '#cd7f32', 1427 Silver: '#c0c0c0', 1428 Gold: '#ffd700' 1429 }; 1430 1431 // Get new tier color 1432 const newTierColor = tierColors[newTier] || '#88e188'; 1433 1434 // Random congratulatory phrases 1435 const phrases = [ 1436 "You're moving up!", 1437 "Fantastic Progress!", 1438 "Promotion Unlocked!", 1439 "Keep Shining!", 1440 "Level Up!", 1441 "Well Deserved!" 1442 ]; 1443 const randomPhrase = phrases[Math.floor(Math.random() * phrases.length)]; 1444 1445 // Create overlay 1446 const overlay = document.createElement('div'); 1447 Object.assign(overlay.style, { 1448 position: 'fixed', 1449 top: 0, 1450 left: 0, 1451 width: '100vw', 1452 height: '100vh', 1453 backgroundColor: 'rgba(0,0,0,0.5)', 1454 display: 'flex', 1455 alignItems: 'center', 1456 justifyContent: 'center', 1457 zIndex: 9999, 1458 padding: '20px', 1459 }); 1460 1461 // Create popup 1462 const popup = document.createElement('div'); 1463 popup.className = 'tier-promotion-popup'; 1464 Object.assign(popup.style, { 1465 background: `linear-gradient(135deg, #ffffff, ${newTierColor}33)`, 1466 borderRadius: '20px', 1467 padding: '35px 25px', 1468 boxShadow: `0 0 25px ${newTierColor}`, 1469 textAlign: 'center', 1470 position: 'relative', 1471 animation: 'bounceIn 0.8s ease-out, tierGlow 2.5s infinite alternate', 1472 maxWidth: '90%', 1473 width: '420px', 1474 fontFamily: 'Segoe UI, sans-serif', 1475 color: '#1a1a1a', 1476 overflow: 'hidden', 1477 }); 1478 1479 // Medal / Tier Image 1480 const tierIcon = document.createElement('img'); 1481 tierIcon.src = 'https://www.eslfast.com/js/img/Medal_Tier_'+newTier+'.png'; // trophy icon 1482 Object.assign(tierIcon.style, { 1483 width: '90px', 1484 display: 'block', 1485 margin: '0 auto 15px auto', 1486 animation: 'floatSwing 3s ease-in-out infinite' 1487 }); 1488 1489 // Heading 1490 const heading = document.createElement('h2'); 1491 heading.innerText = 'ð Tier Promotion!'; 1492 Object.assign(heading.style, { 1493 fontSize: '28px', 1494 color: newTierColor, 1495 marginBottom: '10px' 1496 }); 1497 1498 // Random phrase 1499 const praise = document.createElement('p'); 1500 praise.innerText = randomPhrase; 1501 Object.assign(praise.style, { 1502 fontSize: '22px', 1503 color: '#333', 1504 fontWeight: 'bold', 1505 marginBottom: '15px', 1506 }); 1507 1508 // Tier details 1509 const tierDetails = document.createElement('div'); 1510 tierDetails.innerHTML = ` 1511 <p style="font-size: 18px; margin-bottom: 15px;"> 1512 1513 </p> 1514 ${rewardPoints > 0 ? `<p style="font-size:17px; color:#222;">Bonus Reward: <strong>â¡${rewardPoints} Points!</strong></p>` : ''} 1515 `; 1516 1517 // Close button 1518 const closeBtn = document.createElement('div'); 1519 closeBtn.innerHTML = '×'; 1520 Object.assign(closeBtn.style, { 1521 position: 'absolute', 1522 top: '0px', 1523 right: '7px', 1524 fontSize: '26px', 1525 color: '#555', 1526 cursor: 'pointer', 1527 border: '1px dotted', 1528 padding: '0px 8px 0px 8px' 1529 }); 1530 closeBtn.onclick = () => overlay.remove(); 1531 1532 // Append all 1533 popup.appendChild(closeBtn); 1534 popup.appendChild(tierIcon); 1535 popup.appendChild(heading); 1536 popup.appendChild(praise); 1537 popup.appendChild(tierDetails);
1538 overlay.appendChild(popup); 1539 document.body.appendChild(overlay); 1540 1541 // Confetti burst 1542 for (let i = 0; i < 60; i++) { 1543 const confetti = document.createElement('div'); 1544 Object.assign(confetti.style, { 1545 position: 'fixed', 1546 top: '50%', 1547 left: '50%', 1548 width: '8px', 1549 height: '8px', 1550 backgroundColor: `hsl(${Math.random() * 360}, 100%, 50%)`, 1551 borderRadius: '50%', 1552 transform: `translate(-50%, -50%)`, 1553 animation: `confettiFly ${1 + Math.random() * 1.5}s ease-out forwards`, 1554 zIndex: 10000 1555 }); 1556 confetti.style.setProperty('--x', `${(Math.random() - 0.5) * 400}px`); 1557 confetti.style.setProperty('--y', `${(Math.random() - 0.5) * 400}px`); 1558 document.body.appendChild(confetti); 1559 setTimeout(() => confetti.remove(), 3000); 1560 } 1561 1562 // Animations 1563 const style = document.createElement('style'); 1564 style.textContent = ` 1565 @keyframes bounceIn { 1566 0% { transform: scale(0.7); opacity: 0; } 1567 80% { transform: scale(1.1); opacity: 1; } 1568 100% { transform: scale(1); } 1569 } 1570 @keyframes floatSwing { 1571 0%, 100% { transform: translateY(0) rotate(0deg); } 1572 50% { transform: translateY(-10px) rotate(3deg); } 1573 } 1574 @keyframes tierGlow { 1575 0% { box-shadow: 0 0 15px ${newTierColor}55; } 1576 100% { box-shadow: 0 0 35px ${newTierColor}; } 1577 } 1578 @keyframes confettiFly { 1579 to { 1580 transform: translate(calc(-50% + var(--x)), calc(-50% + var(--y))) rotate(720deg); 1581 opacity: 0; 1582 } 1583 } 1584 1585 @media (max-width: 768px) {
1586 .tier-promotion-popup { 1587 width: 90% !important; 1588 padding: 20px 15px !important; 1589 } 1590 } 1591 @media (max-width: 480px) { 1592 .tier-promotion-popup { 1593 width: 95% !important; 1594 font-size: 16px !important; 1595 } 1596 } 1597 `; 1598 document.head.appendChild(style); 1599} 1600 1601$('.chat a.chat-icon').click(function(){ 1602 jQuery.ajax({ 1603 type: 'POST', 1604 dataType : 'json', 1605 url: `https://www.eslfast.com/membership/api/valid-token/${curr_user_login_token}` 1606 }).done(function (res) { 1607 1608 if ((res.token_key != '')) { 1609 window.location.href = `https://www.eslfast.com/membership/talk-to-tutor`; 1610 }else{ 1611 window.location.href = `https://www.eslfast.com/Chatbot_Tutor/notice.htm`; 1612 // alert('Your login session has expired. Please log in again to access the chat feature.'); 1613 } 1614 }).fail(function (jqXHR, textStatus) { 1615 1616 }); 1617 return false; 1618}); 1619 1620console.log(curr_page_url); 1621console.log(curr_content_id); 1622console.log(curr_user_login_token); 1623 1624function startAntiAdblock() { 1625 1626 console.log('Starting anti-adblock detection...'); 1627 1628 if (window.antiAdblockStarted) { 1629 return; 1630 } 1631 1632 window.antiAdblockStarted = true; 1633 1634 // Show fullscreen loader immediately 1635 // showAdblockCheckingLoader(); 1636 1637 // Wait until DOM is ready 1638 setTimeout(function () { 1639 1640 checkAdblockBait(); 1641 1642 }, 500); 1643} 1644 1645 1646// ====================================================== 1647// STEP 1: BAIT CHECK 1648// ====================================================== 1649 1650function checkAdblockBait() { 1651 1652 console.log('STEP 1: Checking adblock bait...'); 1653 1654 const bait = document.createElement('div'); 1655 1656 bait.id = 'adblock-test-' + Date.now(); 1657 1658 bait.className = 1659 'ad ads adsbox adbox ad-banner advertisement ' + 1660 'advert banner-ad pub_300x250 text-ad'; 1661 1662 bait.innerHTML = ' '; 1663 1664 /* 1665 * IMPORTANT: 1666 * 1667 * Do NOT set width/height to 0. 1668 * Do NOT use display:none. 1669 * Do NOT use opacity:0. 1670 * 1671 * We want the browser/adblocker to decide 1672 * what happens to the element. 1673 */ 1674 1675 bait.style.cssText = ` 1676 position: absolute !important; 1677 left: -10000px !important; 1678 top: -10000px !important; 1679 width: 300px !important; 1680 height: 250px !important; 1681 line-height: 250px !important; 1682 overflow: hidden !important; 1683 `; 1684 1685 document.body.appendChild(bait); 1686 1687 setTimeout(function () { 1688 1689 if (!document.body.contains(bait)) { 1690 1691 console.log('ð« Bait was removed'); 1692 1693 bait.remove(); 1694 1695 /* 1696 * Don't immediately show popup. 1697 * 1698 * Verify with another test. 1699 */ 1700 1701 checkSecondBait(); 1702 1703 return; 1704 } 1705 1706 const style = window.getComputedStyle(bait); 1707 1708 const baitBlocked = 1709 bait.offsetWidth === 0 || 1710 bait.offsetHeight === 0 || 1711 style.display === 'none' || 1712 style.visibility === 'hidden'; 1713 1714 console.log('Bait result:', { 1715 exists: document.body.contains(bait), 1716 width: bait.offsetWidth, 1717 height: bait.offsetHeight, 1718 display: style.display, 1719 visibility: style.visibility, 1720 blocked: baitBlocked 1721 }); 1722 1723 bait.remove(); 1724 1725 if (baitBlocked) { 1726 1727 console.log('â ï¸ First bait indicates blocker'); 1728 1729 checkSecondBait(); 1730 1731 } else { 1732 1733 console.log('â First bait passed'); 1734 1735 checkActualAds(); 1736 } 1737 1738 }, 1500); 1739} 1740 1741 1742// ====================================================== 1743// STEP 2: SECOND BAIT CHECK 1744// ====================================================== 1745 1746function checkSecondBait() { 1747 1748 console.log('STEP 2: Confirming adblock detection...'); 1749 1750 const bait = document.createElement('div'); 1751 1752 bait.className = 1753 'adsbygoogle adsbox adunit advertisement ' + 1754 'google-ad ad-container'; 1755 1756 bait.innerHTML = ' '; 1757 1758 bait.style.cssText = ` 1759 position: absolute !important; 1760 left: -10000px !important; 1761 top: -10000px !important; 1762 width: 320px !important; 1763 height: 100px !important; 1764 overflow: hidden !important; 1765 `; 1766 1767 document.body.appendChild(bait); 1768 1769 setTimeout(function () { 1770 1771 let blocked = false;
1772 1773 if (!document.body.contains(bait)) { 1774 1775 blocked = true; 1776 1777 console.log('ð« Second bait was removed'); 1778 1779 } else { 1780 1781 const style = window.getComputedStyle(bait); 1782 1783 blocked = 1784 bait.offsetWidth === 0 || 1785 bait.offsetHeight === 0 || 1786 style.display === 'none' || 1787 style.visibility === 'hidden'; 1788 1789 console.log('Second bait result:', { 1790 width: bait.offsetWidth, 1791 height: bait.offsetHeight, 1792 display: style.display, 1793 visibility: style.visibility, 1794 blocked: blocked 1795 }); 1796 } 1797 1798 bait.remove(); 1799 1800 /* 1801 * Only after TWO bait tests indicate blocking 1802 * do we show the popup. 1803 */ 1804 1805 if (blocked) { 1806 1807 console.log( 1808 'ð« Ad blocker confirmed by two bait checks' 1809 ); 1810 1811 // hideAdblockCheckingLoader(); 1812 1813 showAntiAdblockMessage(); 1814 1815 } else { 1816 1817 console.log( 1818 'â Bait checks passed' 1819 ); 1820 1821 checkActualAds(); 1822 } 1823 1824 }, 1500); 1825} 1826 1827 1828// ====================================================== 1829// STEP 3: ACTUAL ADSENSE CHECK 1830// ====================================================== 1831 1832function checkActualAds() { 1833 1834 console.log('STEP 3: Checking actual AdSense...'); 1835 1836 setTimeout(function () { 1837 1838 const ads = 1839 document.querySelectorAll('ins.adsbygoogle'); 1840 1841 console.log( 1842 'AdSense elements found:', 1843 ads.length 1844 ); 1845 1846 /* 1847 * IMPORTANT: 1848 * 1849 * Missing AdSense elements are NOT considered 1850 * an ad blocker. 1851 */ 1852 1853 if (ads.length === 0) { 1854 1855 console.log( 1856 'No AdSense elements. ' + 1857 'Not treating as blocker.' 1858 ); 1859 1860 // hideAdblockCheckingLoader(); 1861 1862 return; 1863 } 1864 1865 let hiddenAd = false; 1866 1867 ads.forEach(function (ad, index) { 1868 1869 const style = 1870 window.getComputedStyle(ad); 1871 1872 const status = 1873 ad.getAttribute('data-ad-status'); 1874 1875 console.log( 1876 'AdSense #' + index, 1877 { 1878 status: status, 1879 width: ad.offsetWidth, 1880 height: ad.offsetHeight, 1881 display: style.display, 1882 visibility: style.visibility 1883 } 1884 ); 1885 1886 /* 1887 * ONLY detect if the actual AdSense 1888 * element is explicitly hidden. 1889 */ 1890 1891 if ( 1892 style.display === 'none' || 1893 style.visibility === 'hidden' 1894 ) { 1895 1896 hiddenAd = true; 1897 } 1898 1899 }); 1900 1901 1902 if (hiddenAd) { 1903 1904 console.log( 1905 'â ï¸ Actual AdSense element is hidden' 1906 ); 1907 1908 /* 1909 * Do NOT immediately block the user. 1910 * 1911 * A hidden ad can have other causes. 1912 * 1913 * Keep the page accessible. 1914 */ 1915 1916 // hideAdblockCheckingLoader(); 1917 1918 return; 1919 } 1920 1921 1922 console.log( 1923 'â Ad blocker not detected' 1924 ); 1925 1926 hideAdblockCheckingLoader(); 1927 1928 }, 3000); 1929} 1930 1931 1932// ====================================================== 1933// FULLSCREEN LOADER 1934// ====================================================== 1935 1936function showAdblockCheckingLoader() { 1937 1938 if ($('#adblock-check-loader').length) { 1939 return; 1940 } 1941 1942 $('body').append(` 1943 1944 <div id="adblock-check-loader"> 1945 1946 <div class="adblock-loader-content"> 1947 1948 <div class="adblock-spinner"></div> 1949 1950 <div class="adblock-loader-text"> 1951 Checking your browser... 1952 </div> 1953 1954 </div> 1955 1956 </div> 1957 1958 <style> 1959 1960 #adblock-check-loader { 1961 1962 position: fixed; 1963 inset: 0; 1964 1965 width: 100%; 1966 height: 100%; 1967 1968 background: #ffffff; 1969 1970 z-index: 2147483646; 1971 1972 display: flex; 1973 1974 align-items: center; 1975 justify-content: center; 1976 1977 text-align: center; 1978 1979 font-family: 1980 Arial, 1981 Helvetica, 1982 sans-serif; 1983 } 1984 1985 1986 .adblock-loader-content { 1987 1988 width: 90%; 1989 max-width: 400px; 1990 1991 padding: 20px; 1992 } 1993 1994 1995 .adblock-spinner { 1996 1997 width: 42px; 1998 height: 42px; 1999 2000 margin: 0 auto 18px; 2001 2002 border: 4px solid #e5e5e5; 2003 2004 border-top: 2005 4px solid #006d77; 2006 2007 border-radius: 50%; 2008 2009 animation: 2010 adblock-spin 2011 .8s linear infinite; 2012 } 2013 2014 2015 .adblock-loader-text { 2016 2017 font-size: 16px; 2018 2019 line-height: 1.5; 2020 2021 color: #555; 2022 } 2023 2024 2025 @keyframes adblock-spin { 2026 2027 from { 2028 transform: rotate(0deg); 2029 } 2030 2031 to { 2032 transform: rotate(360deg); 2033 } 2034 2035 } 2036 2037 2038 @media (max-width: 480px) { 2039 2040 .adblock-spinner { 2041 2042 width: 36px; 2043 height: 36px; 2044 2045 border-width: 3px; 2046 } 2047 2048 .adblock-loader-text { 2049 font-size: 14px; 2050 } 2051 2052 } 2053 2054 </style> 2055 2056 `); 2057 2058 $('body').css( 2059 'overflow', 2060 'hidden' 2061 ); 2062} 2063 2064 2065// ====================================================== 2066// HIDE LOADER 2067// ====================================================== 2068 2069function hideAdblockCheckingLoader() { 2070 2071 $('#adblock-check-loader').remove(); 2072 2073 if (!$('#anti-adblock-message').length) { 2074 2075 $('body').css( 2076 'overflow', 2077 '' 2078 ); 2079 } 2080} 2081 2082 2083// ====================================================== 2084// ANTI-ADBLOCK MESSAGE 2085// ====================================================== 2086 2087function showAntiAdblockMessage() { 2088 2089 if ($('#anti-adblock-message').length) { 2090 return; 2091 } 2092 2093 $('body').append(` 2094 2095 <div id="anti-adblock-message"> 2096 2097 <div class="anti-adblock-box"> 2098 2099 <div class="anti-adblock-icon"> 2100 â ï¸ 2101 </div> 2102 2103 <h3> 2104 Ad Blocker Detected 2105 </h3> 2106 2107 <p> 2108 To Make English Learning Free for everyone, please allow ads on our site. Thank y
2108ou for your support. (All the ads will be removed for you If you can pay a small subscription fee at eslfast.com) 2109 </p> 2110 2111 <button 2112 type="button" 2113 onclick="location.reload();" 2114 > 2115 I have disabled it 2116 </button> 2117 2118 </div> 2119 2120 </div> 2121 2122 <style> 2123 2124 #anti-adblock-message { 2125 2126 position: fixed; 2127 2128 inset: 0; 2129 2130 z-index: 2147483647; 2131 2132 width: 100%; 2133 height: 100%; 2134 2135 background: 2136 rgba(0, 0, 0, .85); 2137 2138 display: flex; 2139 2140 align-items: center; 2141 justify-content: center; 2142 2143 padding: 20px; 2144 2145 box-sizing: border-box; 2146 } 2147 2148 2149 .anti-adblock-box { 2150 2151 width: 100%; 2152 max-width: 480px; 2153 2154 background: #fff; 2155 2156 padding: 35px 30px; 2157 2158 text-align: center; 2159 2160 border-radius: 12px; 2161 2162 box-sizing: border-box; 2163 2164 box-shadow: 2165 0 10px 40px 2166 rgba(0, 0, 0, .35); 2167 2168 font-family: 2169 Arial, 2170 Helvetica, 2171 sans-serif; 2172 } 2173 2174 2175 .anti-adblock-icon { 2176 2177 font-size: 42px; 2178 2179 margin-bottom: 15px; 2180 } 2181 2182 2183 .anti-adblock-box h3 { 2184 2185 margin: 0 0 15px; 2186 2187 font-size: 26px; 2188 2189 line-height: 1.3; 2190 2191 color: #222; 2192 } 2193 2194 2195 .anti-adblock-box p { 2196 2197 margin: 0 0 25px; 2198 2199 font-size: 16px; 2200 2201 line-height: 1.6; 2202 2203 color: #555; 2204 } 2205 2206 2207 .anti-adblock-box button { 2208 2209 width: auto; 2210 2211 min-width: 180px; 2212 2213 padding: 12px 24px; 2214 2215 border: 0; 2216 2217 border-radius: 6px; 2218 2219 background: #006d77; 2220 2221 color: #fff; 2222 2223 font-size: 16px; 2224 2225 font-weight: 600; 2226 2227 cursor: pointer; 2228 } 2229 2230 2231 .anti-adblock-box button:hover { 2232 2233 background: #00555d; 2234 } 2235 2236 2237 @media (max-width: 480px) { 2238 2239 #anti-adblock-message { 2240 padding: 12px; 2241 } 2242 2243 .anti-adblock-box { 2244 2245 padding: 25px 18px; 2246 2247 border-radius: 10px; 2248 } 2249 2250 .anti-adblock-icon { 2251 font-size: 36px; 2252 } 2253 2254 .anti-adblock-box h3 { 2255 font-size: 21px; 2256 } 2257 2258 .anti-adblock-box p { 2259 font-size: 14px; 2260 } 2261 2262 .anti-adblock-box button { 2263 2264 width: 100%; 2265 2266 min-width: 0; 2267 2268 font-size: 15px; 2269 } 2270 2271 } 2272 2273 </style> 2274 2275 `); 2276 2277 $('body').css( 2278 'overflow', 2279 'hidden' 2280 ); 2281}
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.