1<!doctype html> 2<!--[if lt IE 7]><html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]--> 3<!--[if IE 7]><html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]--> 4<!--[if IE 8]><html class="no-js lt-ie9" lang="en"> <![endif]--> 5<!--[if IE 9 ]><html class="ie9 no-js"> <![endif]--> 6<!--[if (gt IE 9)|!(IE)]><!--> <html class="no-js"> <!--<![endif]--> 7<head> 8 9 <!-- Basic page needs ================================================== --> 10 <meta charset="utf-8"> 11 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 12 13 14 <link rel="icon" href="https://cdn.store-assets.com/s/897413/f/8318815.jpeg" /> 15 16 17 <!-- Title and description ================================================== --> 18 <title> 19 Login – PTTI 20 </title> 21 22 23 24 <!-- Social meta ================================================== --> 25 26 27 <meta property="og:type" content="website"> 28 <meta property="og:title" content="Login"> 29 <meta property="og:url" content="https://ptti.my/account/login"> 30 31 <meta property="og:image" content="https://cdn.store-assets.com/s/897413/f/8248207.jpeg?width=350&format=webp"> 32 <meta property="og:image:secure_url" content="https://cdn.store-assets.com/s/897413/f/8248207.jpeg?width=350&format=webp"> 33 34 35 36<meta property="og:description" content="PTTI is an Award Winning Online Tuition SPM Class for Form 5, 4, 3, 2, 1 and Year 6 students."> 37<meta property="og:site_name" content="PTTI"> 38 39 40 41 <meta name="twitter:card" content="summary"> 42 43 44 45 46 47 48 49 <!-- Helpers ================================================== --> 50 <link rel="canonical" href="https://ptti.my/account/login"> 51 <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=3.0"> 52 <meta name="theme-color" content=""> 53 54 <!-- CSS ================================================== --> 55 <link href="https://store-themes.easystore.co/897413/themes/2877/assets/timber.css?t=1791441402" rel="stylesheet" type="text/css" media="screen" /> 56 <link href="https://store-themes.easystore.co/897413/themes/2877/assets/theme.css?t=1791441402" rel="stylesheet" type="text/css" media="screen" /> 57 58 59 60 61 62<link href="https://fonts.googleapis.com/css?family=Rajdhani:400,600&display=swap" rel="stylesheet"> 63 64 65
65<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" type="text/javascript" ></script>
65 66 <!-- Header hook for plugins ================================================== --> 67 68<!-- ScriptTags -->
69<script>window.__st={p: "customers",cid: null,cem: null,cph: null,cfn: null,cln: null,cge: null,cdb: null,ccc: null};</script>
69<script src='/assets/events.js'></script>
69<script>(function(){function asyncLoad(){var urls=['/assets/facebook-pixel.js?v=1.2.1701504180','/assets/traffic.js?v=1','https://apps.easystore.co/sales-pop/script.js?shop=pttiptti.easy.co','https://smartarget.online/loader.js?type=int&u=ff30bff8d40f585fc830e546ea7171440e47c924&source=easystore_social_proof_sales','https://apps.easystore.co/facebook-login/script.js?shop=pttiptti.easy.co'];for(var i=0;i<urls.length;i++){var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=urls[i];var x=document.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);}}window.attachEvent ? window.attachEvent('onload', asyncLoad) : window.addEventListener('load', asyncLoad, false);})();</script>
69 70<!-- /ScriptTags --> 71 72 73 74<!--[if lt IE 9]>
75<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js" type="text/javascript" ></script>
vendor: 2 bytes, line 75
75
76<script src="https://store-themes.easystore.co/897413/themes/2877/assets/respond.min.js?t=1791441402" type="text/javascript" ></script>
76 77<link href="https://store-themes.easystore.co/897413/themes/2877/assets/respond-proxy.html" id="respond-proxy" rel="respond-proxy" /> 78<link href="//ptti.my/search?q=7568e8aae51f634de7b35ee2e709fe8d" id="respond-redirect" rel="respond-redirect" />
79<script src="//ptti.my/search?q=7568e8aae51f634de7b35ee2e709fe8d" type="text/javascript"></script>
79 80<![endif]--> 81 82 83 84
84<script src="https://store-themes.easystore.co/897413/themes/2877/assets/modernizr.min.js?t=1791441402" type="text/javascript" ></script>
84 85 86 87 88
88<script src="/assets/shop_common.js" type="text/javascript" ></script>
88 89
89<script src="/assets/customer_area.js" type="text/javascript" ></script>
89 90 91
91<script> 92 (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 93 (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 94 m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) 95 })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); 96 97 ga('create', '', 'auto','myTracker'); 98 ga('myTracker.send', 'pageview'); 99 100 </script>
100 101 102<!-- Snippet:global/head: ActionPop Email Popups & Upsell by OnVoard -->
103<script> 104 (function() { 105 window.OnVoard = window.OnVoard || function() { 106 (window.OnVoard.q = window.OnVoard.q || []).push(arguments); 107 }; 108 var script = document.createElement("script"); 109 var parent = document.getElementsByTagName("script")[0].parentNode; 110 script.async = 1; 111 112 113 script.src = "https://scripts.onvoard.com/apps/loader.js"; 114 115 parent.appendChild(script); 116 })(); 117</script>
117 118 119
120<script> 121 122var ovData = {}; 123ovData["ecommerce_platform"] = "easystore"; 124ovData["account_id"] = "acct_i56nf98ua40ya24"; 125 126 127 ovData["template"] = "customers"; 128 ovData["cart"] = {"item_count":0,"total_price":0,"announcements":[]}; 129 ovData["product"] = ""; 130 ovData["shop"] = {}; 131 ovData["customer"] = {}; 132 133 134 ovData["shop"] = { 135 "currency": "MYR", 136 "domain": "ptti.my", 137 "url": "https://ptti.my", 138 "money_format": "<span class=money data-ori-price='{{amount}}'>RM {{amount}} </span>", 139 }; 140 141 142 143 144 window.OnVoardData = ovData; 145</script>
145 146 147<!-- /Snippet --> 148 149<!-- Snippet:global/head: Insert Code --> 150 151<!--Hotjar --> 152<!-- Hotjar Tracking Code for https://ptti.my -->
153<script>
vendor: 128 bytes, lines 153-156
153 154 (function(h,o,t,j,a,r){ 155 h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)}; 156 h._hjSettings={hjid:
1566397015
vendor: 264 bytes, lines 156-161
156,hjsv:6}; 157 a=o.getElementsByTagName('head')[0]; 158 r=o.createElement('script');r.async=1; 159 r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv; 160 a.appendChild(r); 161 })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
162</script>
162 163<!-- /Snippet --> 164 165</head> 166 167<body id="login" class="template-customers " > 168 169 <ul id="MobileNav" class="mobile-nav"> 170 171 <li class="mobile-nav_icon-x"> 172 173 174 175 176 177 <span class="MobileNavTrigger icon icon-x"></span> 178 </li> 179 180 181 <li class="mobile-nav__link" aria-haspopup="true"> 182 183 <a href="/" > 184 Home 185 </a> 186 187 </li> 188 189 190 <li class="mobile-nav__link" aria-haspopup="true"> 191 192 <a href="/pages/apa-itu-otc" > 193 Apa itu OTC? 194 </a> 195 196 </li> 197 198 199 <li class="mobile-nav__link" aria-haspopup="true"> 200 201 202 <a href="/pages/free-trial" class="mobile-nav__parent-link"> 203 Free Trial 204 </a> 205 <span class="mobile-nav__sublist-trigger"> 206 <span class="icon-fallback-text mobile-nav__sublist-expand"> 207 <span class="icon icon-plus" aria-hidden="true"></span> 208 <span class="fallback-text">+</span> 209</span> 210<span class="icon-fallback-text mobile-nav__sublist-contract"> 211 <span class="icon icon-minus" aria-hidden="true"></span> 212 <span class="fallback-text">-</span> 213</span> 214 215 </span> 216 <ul class="mobile-nav__sublist"> 217 218 219 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 220 221 <a href="/pages/form-5-sains-tulen" >
222 Form 5 Sains Tulen 223 </a> 224 225 </li> 226 227 228 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 229 230 <a href="/pages/form-5-bukan-sains-tulen-teras" > 231 Form 5 Bukan Sains Tulen (Teras) 232 </a> 233 234 </li> 235 236 237 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 238 239 <a href="/pages/form-4-sains-tulen" > 240 Form 4 Sains Tulen 241 </a> 242 243 </li> 244 245 246 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 247 248 <a href="/pages/form-4-bukan-sains-tulen-teras" > 249 Form 4 Bukan Sains Tulen (Teras) 250 </a> 251 252 </li> 253 254 255 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 256 257 <a href="/pages/form-3" > 258 Form 3 259 </a> 260 261 </li> 262 263 264 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 265 266 <a href="/pages/form-2" > 267 Form 2 268 </a> 269 270 </li> 271 272 273 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 274 275 <a href="/pages/form-1" > 276 Form 1 277 </a> 278 279 </li> 280 281 </ul> 282 283 </li> 284 285 286 <li class="mobile-nav__link" aria-haspopup="true"> 287 288 <a href="/pages/better-result" > 289 Our Students 290 </a> 291 292 </li> 293 294 295 <li class="mobile-nav__link" aria-haspopup="true"> 296 297 <a href="/pages/ask-ptti" > 298 Ask PTTI 299 </a> 300 301 </li> 302 303 304 305 306 307 308 309 <li class="mobile-nav__link"> 310 <a href="/account/login">Log in</a> 311 </li> 312 313 <li class="mobile-nav__link"> 314 <a href="/account/register">Create account</a> 315 </li> 316 317 318 319 320 <li class="mobile-nav__link header-bar__search-wrapper"> 321 322 <div class="header-bar__module header-bar__search mobile-nav_search"> 323 324 <form action="/search" method="get" class="header-bar__search-form clearfix" role="search"> 325 326 <button type="submit" class="btn icon-fallback-text header-bar__search-submit"> 327 <span class="icon icon-search" aria-hidden="true"></span> 328 <span class="fallback-text">Search</span> 329 </button> 330 <input type="search" name="q" value="" aria-label="Search" class="header-bar__search-input" placeholder="Search" autocomplete="off"> 331 <div class="dropdown" id="searchDropdown"></div> 332 <input type="hidden" name="search_history" id="search_history"> 333 </form> 334 335 336 337
338<script> 339 var _search_history_listings = "" 340 if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings)); 341 342 function clearAll() { 343 localStorage.removeItem('searchHistory'); 344 345 var customer = ""; 346 if(customer) { 347 // Your logic to clear all data or call an endpoint 348 fetch('/account/search_histories', { 349 method: 'DELETE', 350 headers: { 351 "Content-Type": "application/json", 352 "X-Requested-With": "XMLHttpRequest" 353 }, 354 body: JSON.stringify({ 355 _token: "yNIxW1hoq0dss3xoPWARy0Hj9gwch3wF69BmtQmj" 356 }), 357 }) 358 .then(response => response.json()) 359 } 360 } 361 // End - store view history in local storage 362 363 // search history dropdown 364 var searchInputs = document.querySelectorAll('input[type=search]'); 365 366 if(searchInputs.length > 0) { 367 368 searchInputs.forEach((searchInput)=>{ 369 370 searchInput.addEventListener('focus', function() { 371 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 372 searchDropdown.innerHTML = ''; // Clear existing items 373 374 // retrieve data from local storage 375 var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || []; 376 377 // Convert JSON to string 378 var search_history_json = JSON.stringify(searchHistoryData); 379 380 // Set the value of the hidden input 381 searchInput.closest('form').querySelector("#search_history").value = search_history_json; 382 383 // create dropdown items 384 var clearAllItem = document.createElement('div'); 385 clearAllItem.className = 'dropdown-item clear-all'; 386 clearAllItem.textContent = 'Clear'; 387 clearAllItem.addEventListener('click', function() { 388 clearAll(); 389 searchDropdown.style.display = 'none'; 390 searchInput.classList.remove('is-focus'); 391 }); 392 searchDropdown.appendChild(clearAllItem); 393 394 // create dropdown items 395 searchHistoryData.forEach(function(item) { 396 var dropdownItem = document.createElement('div'); 397 dropdownItem.className = 'dropdown-item'; 398 dropdownItem.textContent = item.term; 399 dropdownItem.addEventListener('click', function() { 400 searchInput.value = item.term; 401 searchDropdown.style.display = 'none'; 402 }); 403 searchDropdown.appendChild(dropdownItem); 404 }); 405 406 if(searchHistoryData.length > 0){ 407 // display the dropdown 408 searchInput.classList.add('is-focus'); 409 document.body.classList.add('search-input-focus'); 410 searchDropdown.style.display = 'block'; 411 } 412 }); 413 414 searchInput.addEventListener("focusout", (event) => { 415 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 416 searchInput.classList.remove('is-focus'); 417 searchDropdown.classList.add('transparent'); 418 setTimeout(()=>{ 419 searchDropdown.style.display = 'none'; 420 searchDropdown.classList.remove('transparent'); 421 document.body.classList.remove('search-input-focus'); 422 }, 400); 423 }); 424 }) 425 } 426 // End - search history dropdown 427</script>
427 428 </div> 429 430 </li> 431 432 433</ul> 434<div id="MobileNavOutside" class="mobile-nav-outside"></div> 435 436 437<div id="PageContainer" class="page-container"> 438 439<!-- Snippet:global/body_start: Console Extension --> 440<div id='es_console' style='display: none;'>897413</div> 441<!-- /Snippet --> 442 443 444 <style> 445 .search-modal__form{ 446 position: relative; 447 } 448 449 .dropdown-wrapper { 450 position: relative; 451 } 452 453 .dropdown-wrapper:hover .dropdown { 454 display: block; 455 } 456 457 .header-icon-nav .dropdown { 458 left: -80px; 459 } 460 461 .dropdown { 462 display: none; 463 position: absolute; 464 top: 100%; 465 left: 0px; 466 width: 100%; 467 padding: 8px; 468 background-color: #fff; 469 z-index: 1000; 470 border-radius: 5px; 471 border: 1px solid rgba(var(--color-foreground), 1); 472 border-top: none; 473 overflow-x: hidden; 474 overflow-y: auto; 475 max-height: 350px; 476 min-width: 150px; 477 box-shadow: 0 0 5px rgba(0,0,0,0.1); 478 } 479 480 .dropdown a{ 481 text-decoration: none; 482 color: #000 !important; 483 } 484 485 .dropdown-item { 486 padding: 0.4rem 2rem; 487 cursor: pointer; 488 line-height: 1.4; 489 overflow: hidden; 490 text-overflow: ellipsis; 491 white-space: nowrap; 492 } 493 494 .dropdown-item:hover{ 495 background-color: #f3f3f3; 496 } 497 498 .search__input.is-focus{ 499 border-radius: 15px; 500 border-bottom-left-radius: 0; 501 border-bottom-right-radius: 0; 502 border: 1px solid rgba(var(--color-foreground), 1); 503 border-bottom: none; 504 box-shadow: none; 505 } 506 507 .clear-all { 508 text-align: right; 509 padding: 0 2rem 0.2rem; 510 line-height: 1; 511 font-size: 70%; 512 margin-bottom: -2px; 513 } 514 515 .clear-all:hover{ 516 background-color: #fff; 517 } 518 519 .referral-notification { 520 position: absolute; 521 top: 100%; 522 right: -12px; 523 background: white; 524 border: 1px solid #e0e0e0; 525 border-radius: 8px; 526 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); 527 width: 280px; 528 z-index: 1000; 529 padding: 16px; 530 margin-top: 8px; 531 font-size: 14px; 532 line-height: 1.4; 533 } 534 535 .referral-notification::before { 536 content: ''; 537 position: absolute; 538 top: -8px; 539 right: 20px; 540 width: 0; 541 height: 0; 542 border-left: 8px solid transparent; 543 border-right: 8px solid transparent; 544 border-bottom: 8px solid white; 545 } 546 547 .referral-notification::after { 548 content: ''; 549 position: absolute; 550 top: -9px; 551 right: 20px; 552 width: 0; 553 height: 0; 554 border-left: 8px solid transparent; 555 border-right: 8px solid transparent; 556 border-bottom: 8px solid #e0e0e0; 557 } 558 559 .referral-notification h4 { 560 margin: 0 0 8px 0; 561 color: #2196F3; 562 font-size: 16px; 563 font-weight: 600; 564 } 565 566 .referral-notification p { 567 margin: 0 0 12px 0; 568 color: #666; 569 } 570 571 .referral-notification .referral-code { 572 background: #f5f5f5; 573 padding: 8px; 574 border-radius: 4px; 575 font-family: monospace; 576 font-size: 13px; 577 text-align: center; 578 margin: 8px 0; 579 border: 1px solid #ddd; 580 } 581 582 .referral-notification .close-btn { 583 position: absolute; 584 top: 8px; 585 right: 8px; 586 background: none; 587 border: none; 588 font-size: 18px; 589 color: #999; 590 cursor: pointer; 591 padding: 0; 592 width: 20px; 593 height: 20px; 594 line-height: 1; 595 } 596 597 .referral-notification .close-btn:hover { 598 color: #333; 599 } 600 601 .referral-notification .action-btn { 602 background: #2196F3; 603 color: white; 604 border: none; 605 padding: 8px 16px; 606 border-radius: 4px; 607 cursor: pointer; 608 font-size: 12px; 609 margin-right: 8px; 610 margin-top: 8px; 611 } 612 613 .referral-notification .action-btn:hover { 614 background: #1976D2; 615 } 616 617 .referral-notification .dismiss-btn { 618 background: transparent; 619 color: #666; 620 border: 1px solid #ddd; 621 padding: 8px 16px; 622 border-radius: 4px; 623 cursor: pointer; 624 font-size: 12px; 625 margin-top: 8px; 626 } 627 628 .referral-notification .dismiss-btn:hover { 629 background: #f5f5f5; 630 } 631 .referral-modal__dialog { 632 transform: translate(-50%, 0); 633 transition: transform var(--duration-default) ease, visibility 0s; 634 z-index: 10000; 635 position: fixed; 636 top: 20vh; 637 left: 50%; 638 width: 100%; 639 max-width: 350px; 640 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); 641 border-radius: 12px; 642 background-color: #fff; 643 color: #000; 644 padding: 20px; 645 text-align: center; 646 } 647 .modal-overlay.referral-modal-overlay { 648 position: fixed; 649 top: 0; 650 left: 0; 651 width: 100%; 652 height: 100%; 653 background-color: rgba(0, 0, 0, 0.7); 654 z-index: 2001; 655 display: block; 656 opacity: 1; 657 transition: opacity var(--duration-default) ease, visibility 0s; 658 } 659</style> 660 661<header class="header-bar sticky-topbar"> 662 <div class="header-bg-wrapper"> 663 <div class="header-wrapper wrapper"> 664 665 666 <div class="logo-header" role="banner"> 667 668 669 <div class="h1 site-header__logo" itemscope itemtype="http://schema.org/Organization"> 670 671 672 673 674 <a href="/" class="logo-wrapper" itemprop="url"> 675 <img src="https://cdn.store-assets.com/s/897413/f/8248207.jpeg?width=350&format=webp" alt="PTTI" itemprop="logo"> 676 </a> 677 678 679 680 681 </div> 682 683 684 </div> 685 686 <div class="header-nav-bar medium-down--hide"> 687 688<ul class="site-nav large--text-center" id="AccessibleNav"> 689 690 691 692 <li > 693 <a href="/" class="site-nav__link">Home</a> 694 </li> 695 696 697 698 699 <li > 700 <a href="/pages/apa-itu-otc" class="site-nav__link">Apa itu OTC?</a> 701 </li> 702 703 704 705 706 707 <li class="site-nav--has-dropdown" aria-haspopup="true"> 708 <a href="/pages/free-trial" class="site-nav__link"> 709 Free Trial
710 <span class="arrow-icon"> 711 <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><title>arrow down</title><path d="M50,78.18A7.35,7.35,0,0,1,44.82,76L3.15,34.36A7.35,7.35,0,1,1,13.55,24L50,60.44,86.45,24a7.35,7.35,0,1,1,10.4,10.4L55.21,76A7.32,7.32,0,0,1,50,78.18Z"/></svg> 712 </span> 713 </a> 714 <ul class="site-nav__dropdown"> 715 716 717 718 <li > 719 <a href="/pages/form-5-sains-tulen" class="site-nav__link">Form 5 Sains Tulen</a> 720 </li> 721 722 723 724 725 <li > 726 <a href="/pages/form-5-bukan-sains-tulen-teras" class="site-nav__link">Form 5 Bukan Sains Tulen (Teras)</a> 727 </li> 728 729 730 731 732 <li > 733 <a href="/pages/form-4-sains-tulen" class="site-nav__link">Form 4 Sains Tulen</a> 734 </li> 735 736 737 738 739 <li > 740 <a href="/pages/form-4-bukan-sains-tulen-teras" class="site-nav__link">Form 4 Bukan Sains Tulen (Teras)</a> 741 </li> 742 743 744 745 746 <li > 747 <a href="/pages/form-3" class="site-nav__link">Form 3</a> 748 </li> 749 750 751 752 753 <li > 754 <a href="/pages/form-2" class="site-nav__link">Form 2</a> 755 </li> 756 757 758 759 760 <li > 761 <a href="/pages/form-1" class="site-nav__link">Form 1</a> 762 </li> 763 764 765 </ul> 766 </li> 767 768 769 770 771 <li > 772 <a href="/pages/better-result" class="site-nav__link">Our Students</a> 773 </li> 774 775 776 777 778 <li > 779 <a href="/pages/ask-ptti" class="site-nav__link">Ask PTTI</a> 780 </li> 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795</ul> 796 797 </div> 798 799 <div class="desktop-header-nav medium-down--hide"> 800 801 802 <div class="header-subnav"> 803 804 805 806 807 808 <div class="header-icon-nav"> 809 810 811 812 813 814 815 816 817 <div class="header-bar__module"> 818 819 <a class="popup-with-form" href="#search-form"> 820 821 822 823 824 <svg class="icon-search svg-icon" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><title>icon-search</title><path d="M68.5,65.87a35.27,35.27,0,1,0-5.4,4.5l23.11,23.1a3.5,3.5,0,1,0,5-4.94ZM14.82,41A28.47,28.47,0,1,1,43.28,69.43,28.5,28.5,0,0,1,14.82,41Z"/></svg> 825 826 827 828 </a> 829 830 831 832<!-- form itself --> 833<div id="search-form" class="white-popup-block mfp-hide popup-search"> 834 <div class="popup-search-content"> 835 <form action="/search" method="get" class="input-group search-bar" role="search"> 836 837 <input type="search" name="q" value="" placeholder="Search" class="input-group-field" aria-label="Search" placeholder="Search" autocomplete="off"> 838 <div class="dropdown" id="searchDropdown"></div> 839 <input type="hidden" name="search_history" id="search_history"> 840 <span class="input-group-btn"> 841 <button type="submit" class="btn icon-fallback-text"> 842 <span class="icon icon-search" aria-hidden="true"></span> 843 <span class="fallback-text">Search</span> 844 </button> 845 </span> 846 </form> 847 </div> 848</div> 849
850<script src="https://store-themes.easystore.co/897413/themes/2877/assets/magnific-popup.min.js?t=1791441402" type="text/javascript" ></script>
vendor: 1 bytes, line 850
850
851<script> 852$(document).ready(function() { 853 $('.popup-with-form').magnificPopup({ 854 type: 'inline', 855 preloader: false, 856 focus: '#name', 857 mainClass: 'popup-search-bg-wrapper', 858 859 // When elemened is focused, some mobile browsers in some cases zoom in 860 // It looks not nice, so we disable it: 861 callbacks: { 862 beforeOpen: function() { 863 if($(window).width() < 700) { 864 this.st.focus = false; 865 } else { 866 this.st.focus = '#name'; 867 } 868 } 869 } 870 }); 871 $('.popup-search-content').click(function(event) { 872 if($(event.target).attr('class') == "popup-search-content") { 873 $.magnificPopup.close(); 874 } 875 }); 876}); 877</script>
877 878 879
880<script> 881 var _search_history_listings = "" 882 if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings)); 883 884 function clearAll() { 885 localStorage.removeItem('searchHistory'); 886 887 var customer = ""; 888 if(customer) { 889 // Your logic to clear all data or call an endpoint 890 fetch('/account/search_histories', { 891 method: 'DELETE', 892 headers: { 893 "Content-Type": "application/json", 894 "X-Requested-With": "XMLHttpRequest" 895 }, 896 body: JSON.stringify({ 897 _token: "yNIxW1hoq0dss3xoPWARy0Hj9gwch3wF69BmtQmj" 898 }), 899 }) 900 .then(response => response.json()) 901 } 902 } 903 // End - store view history in local storage 904 905 // search history dropdown 906 var searchInputs = document.querySelectorAll('input[type=search]'); 907 908 if(searchInputs.length > 0) { 909 910 searchInputs.forEach((searchInput)=>{ 911 912 searchInput.addEventListener('focus', function() { 913 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 914 searchDropdown.innerHTML = ''; // Clear existing items 915 916 // retrieve data from local storage 917 var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || []; 918 919 // Convert JSON to string 920 var search_history_json = JSON.stringify(searchHistoryData); 921 922 // Set the value of the hidden input 923 searchInput.closest('form').querySelector("#search_history").value = search_history_json; 924 925 // create dropdown items 926 var clearAllItem = document.createElement('div'); 927 clearAllItem.className = 'dropdown-item clear-all'; 928 clearAllItem.textContent = 'Clear'; 929 clearAllItem.addEventListener('click', function() { 930 clearAll(); 931 searchDropdown.style.display = 'none'; 932 searchInput.classList.remove('is-focus'); 933 }); 934 searchDropdown.appendChild(clearAllItem); 935 936 // create dropdown items 937 searchHistoryData.forEach(function(item) { 938 var dropdownItem = document.createElement('div'); 939 dropdownItem.className = 'dropdown-item'; 940 dropdownItem.textContent = item.term; 941 dropdownItem.addEventListener('click', function() { 942 searchInput.value = item.term; 943 searchDropdown.style.display = 'none'; 944 }); 945 searchDropdown.appendChild(dropdownItem); 946 }); 947 948 if(searchHistoryData.length > 0){ 949 // display the dropdown 950 searchInput.classList.add('is-focus'); 951 document.body.classList.add('search-input-focus'); 952 searchDropdown.style.display = 'block'; 953 } 954 }); 955 956 searchInput.addEventListener("focusout", (event) => { 957 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 958 searchInput.classList.remove('is-focus'); 959 searchDropdown.classList.add('transparent'); 960 setTimeout(()=>{ 961 searchDropdown.style.display = 'none'; 962 searchDropdown.classList.remove('transparent'); 963 document.body.classList.remove('search-input-focus'); 964 }, 400); 965 }); 966 }) 967 } 968 // End - search history dropdown 969</script>
969 970 </div> 971 972 973 974 975 976 977 978 <div class="header-bar__module dropdown-wrapper"> 979 980 <a href="/account/login"> 981 982 983 984 <svg class="svg-icon" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><title>icon-profile</title><path d="M50,51.8A24.4,24.4,0,1,0,25.6,27.4,24.43,24.43,0,0,0,50,51.8ZM50,10A17.4,17.4,0,1,1,32.6,27.4,17.43,17.43,0,0,1,50,10Z"/><path d="M62.66,57.66H37.34a30.54,30.54,0,0,0-30.5,30.5V93.5a3.5,3.5,0,0,0,3.5,3.5H89.66a3.5,3.5,0,0,0,3.5-3.5V88.16A30.54,30.54,0,0,0,62.66,57.66ZM86.16,90H13.84V88.16a23.53,23.53,0,0,1,23.5-23.5H62.66a23.53,23.53,0,0,1,23.5,23.5Z"/></svg> 985 986 987</a> 988 989 <!-- Referral Notification Popup for Desktop --> 990 <div id="referralNotification" class="referral-notification" style="display: none;"> 991 <button class="close-btn" onclick="dismissReferralNotification()">×</button> 992 <div style="text-align: center; margin-bottom: 16px;"> 993 <div style="width: 100px; height: 100px; margin: 0 auto;"> 994 <img src="https://resources.easystore.co/storefront/icons/channels/vector_referral_program.svg"> 995 </div> 996 </div> 997 <p id="referralSignupMessage" style="text-align: center; font-size: 14px; color: #666; margin: 0 0 20px 0;"> 998 Your friend gifted you credit! Sign up now to redeem. 999 </p> 1000 <div style="text-align: center;"> 1001 <button class="btn" onclick="goToSignupPage()" style="width: 100%; color: #fff;"> 1002 Sign Up 1003 </button> 1004 </div> 1005 </div> 1006 1007 </div> 1008 1009 1010 <div class="header-bar__module cart-page-link-wrapper"> 1011 <span class="header-bar__sep" aria-hidden="true"></span> 1012 <a class="CartDrawerTrigger cart-page-link"> 1013 1014 1015 1016 1017 <svg class="svg-icon" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><title>icon-bag</title><path d="M91.78,93.11,84.17,24.44a3.5,3.5,0,0,0-3.48-3.11H69.06C67.53,10.94,59.57,3,50,3S32.47,10.94,30.94,21.33H19.31a3.5,3.5,0,0,0-3.48,3.11L8.22,93.11A3.49,3.49,0,0,0,11.69,97H88.31a3.49,3.49,0,0,0,3.47-3.89ZM50,10c5.76,0,10.6,4.83,12,11.33H38.05C39.4,14.83,44.24,10,50,10ZM15.6,90l6.84-61.67h8.23v9.84a3.5,3.5,0,0,0,7,0V28.33H62.33v9.84a3.5,3.5,0,0,0,7,0V28.33h8.23L84.4,90Z"/></svg> 1018 1019 1020 1021 <span class="cart-count header-bar__cart-count hidden-count">0</span> 1022 </a> 1023 </div> 1024 1025 </div> 1026 </div> 1027 1028 1029 1030 </div> 1031 1032 <div class="mobile-header-icons large--hide"> 1033 1034 <div class="large--hide"> 1035 1036 <a class="popup-with-form" href="#search-form"> 1037 1038 1039 1040 1041 <svg class="icon-search svg-icon" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><title>icon-search</title><path d="M68.5,65.87a35.27,35.27,0,1,0-5.4,4.5l23.11,23.1a3.5,3.5,0,1,0,5-4.94ZM14.82,41A28.47,28.47,0,1,1,43.28,69.43,28.5,28.5,0,0,1,14.82,41Z"/></svg> 1042 1043 1044 1045 </a> 1046 1047 1048 1049<!-- form itself --> 1050<div id="search-form" class="white-popup-block mfp-hide popup-search"> 1051 <div class="popup-search-content"> 1052 <form action="/search" method="get" class="input-group search-bar" role="search"> 1053 1054 <input type="search" name="q" value="" placeholder="Search" class="input-group-field" aria-label="Search" placeholder="Search" autocomplete="off"> 1055 <div class="dropdown" id="searchDropdown"></div> 1056 <input type="hidden" name="search_history" id="search_history"> 1057 <span class="input-group-btn"> 1058 <button type="submit" class="btn icon-fallback-text"> 1059 <span class="icon icon-search" aria-hidden="true"></span>
1060 <span class="fallback-text">Search</span> 1061 </button> 1062 </span> 1063 </form> 1064 </div> 1065</div> 1066
1067<script src="https://store-themes.easystore.co/897413/themes/2877/assets/magnific-popup.min.js?t=1791441402" type="text/javascript" ></script>
vendor: 1 bytes, line 1067
1067
1068<script> 1069$(document).ready(function() { 1070 $('.popup-with-form').magnificPopup({ 1071 type: 'inline', 1072 preloader: false, 1073 focus: '#name', 1074 mainClass: 'popup-search-bg-wrapper', 1075 1076 // When elemened is focused, some mobile browsers in some cases zoom in 1077 // It looks not nice, so we disable it: 1078 callbacks: { 1079 beforeOpen: function() { 1080 if($(window).width() < 700) { 1081 this.st.focus = false; 1082 } else { 1083 this.st.focus = '#name'; 1084 } 1085 } 1086 } 1087 }); 1088 $('.popup-search-content').click(function(event) { 1089 if($(event.target).attr('class') == "popup-search-content") { 1090 $.magnificPopup.close(); 1091 } 1092 }); 1093}); 1094</script>
1094 1095 1096
1097<script> 1098 var _search_history_listings = "" 1099 if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings)); 1100 1101 function clearAll() { 1102 localStorage.removeItem('searchHistory'); 1103 1104 var customer = ""; 1105 if(customer) { 1106 // Your logic to clear all data or call an endpoint 1107 fetch('/account/search_histories', { 1108 method: 'DELETE', 1109 headers: { 1110 "Content-Type": "application/json", 1111 "X-Requested-With": "XMLHttpRequest" 1112 }, 1113 body: JSON.stringify({ 1114 _token: "yNIxW1hoq0dss3xoPWARy0Hj9gwch3wF69BmtQmj" 1115 }), 1116 }) 1117 .then(response => response.json()) 1118 } 1119 } 1120 // End - store view history in local storage 1121 1122 // search history dropdown 1123 var searchInputs = document.querySelectorAll('input[type=search]'); 1124 1125 if(searchInputs.length > 0) { 1126 1127 searchInputs.forEach((searchInput)=>{ 1128 1129 searchInput.addEventListener('focus', function() { 1130 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 1131 searchDropdown.innerHTML = ''; // Clear existing items 1132 1133 // retrieve data from local storage 1134 var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || []; 1135 1136 // Convert JSON to string 1137 var search_history_json = JSON.stringify(searchHistoryData); 1138 1139 // Set the value of the hidden input 1140 searchInput.closest('form').querySelector("#search_history").value = search_history_json; 1141 1142 // create dropdown items 1143 var clearAllItem = document.createElement('div'); 1144 clearAllItem.className = 'dropdown-item clear-all'; 1145 clearAllItem.textContent = 'Clear'; 1146 clearAllItem.addEventListener('click', function() { 1147 clearAll(); 1148 searchDropdown.style.display = 'none'; 1149 searchInput.classList.remove('is-focus'); 1150 }); 1151 searchDropdown.appendChild(clearAllItem); 1152 1153 // create dropdown items 1154 searchHistoryData.forEach(function(item) { 1155 var dropdownItem = document.createElement('div'); 1156 dropdownItem.className = 'dropdown-item'; 1157 dropdownItem.textContent = item.term; 1158 dropdownItem.addEventListener('click', function() { 1159 searchInput.value = item.term; 1160 searchDropdown.style.display = 'none'; 1161 }); 1162 searchDropdown.appendChild(dropdownItem); 1163 }); 1164 1165 if(searchHistoryData.length > 0){ 1166 // display the dropdown 1167 searchInput.classList.add('is-focus'); 1168 document.body.classList.add('search-input-focus'); 1169 searchDropdown.style.display = 'block'; 1170 } 1171 }); 1172 1173 searchInput.addEventListener("focusout", (event) => { 1174 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 1175 searchInput.classList.remove('is-focus'); 1176 searchDropdown.classList.add('transparent'); 1177 setTimeout(()=>{ 1178 searchDropdown.style.display = 'none'; 1179 searchDropdown.classList.remove('transparent'); 1180 document.body.classList.remove('search-input-focus'); 1181 }, 400); 1182 }); 1183 }) 1184 } 1185 // End - search history dropdown 1186</script>
1186 1187 </div> 1188 1189 1190 <!-- Mobile cart --> 1191 <div class="large--hide"> 1192 <a class="CartDrawerTrigger cart-page-link mobile-cart-page-link"> 1193 1194 1195 1196 1197 <svg class="svg-icon" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><title>icon-bag</title><path d="M91.78,93.11,84.17,24.44a3.5,3.5,0,0,0-3.48-3.11H69.06C67.53,10.94,59.57,3,50,3S32.47,10.94,30.94,21.33H19.31a3.5,3.5,0,0,0-3.48,3.11L8.22,93.11A3.49,3.49,0,0,0,11.69,97H88.31a3.49,3.49,0,0,0,3.47-3.89ZM50,10c5.76,0,10.6,4.83,12,11.33H38.05C39.4,14.83,44.24,10,50,10ZM15.6,90l6.84-61.67h8.23v9.84a3.5,3.5,0,0,0,7,0V28.33H62.33v9.84a3.5,3.5,0,0,0,7,0V28.33h8.23L84.4,90Z"/></svg> 1198 1199 1200 1201 <span class="cart-count hidden-count">0</span> 1202 </a> 1203 </div> 1204 1205 <!-- Mobile hamburger --> 1206 <div class="large--hide"> 1207 <a class="mobile-nav-trigger MobileNavTrigger"> 1208 1209 1210 1211 1212 <svg class="svg-icon" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><title>icon-nav-menu</title><path d="M6.7,26.34H93a3.5,3.5,0,0,0,0-7H6.7a3.5,3.5,0,0,0,0,7Z"/><path d="M93.3,46.5H7a3.5,3.5,0,0,0,0,7H93.3a3.5,3.5,0,1,0,0-7Z"/><path d="M93.3,73.66H7a3.5,3.5,0,1,0,0,7H93.3a3.5,3.5,0,0,0,0-7Z"/></svg> 1213 1214 1215 1216 </a> 1217 </div> 1218 1219 1220 1221 <!-- Referral Notification Modal for Mobile --> 1222 <details-modal class="referral-modal" id="referralMobileModal"> 1223 <details> 1224 <summary class="referral-modal__toggle" aria-haspopup="dialog" aria-label="Open referral modal" style="display: none;"> 1225 </summary> 1226 <div class="modal-overlay referral-modal-overlay"></div> 1227 <div class="referral-modal__dialog" role="dialog" aria-modal="true" aria-label="Referral notification"> 1228 <div class="referral-modal__content"> 1229 <button type="button" class="modal__close-button" aria-label="Close" onclick="closeMobileReferralModal()" style="position: absolute; top: 16px; right: 16px; background: none; border: none; font-size: 24px; cursor: pointer;"> 1230 × 1231 </button> 1232 1233 <div style="margin-bottom: 24px;"> 1234 <div style="width: 120px; height: 120px; margin: 0 auto 20px;"> 1235 <img src="https://resources.easystore.co/storefront/icons/channels/vector_referral_program.svg" style="width: 100%; height: 100%;"> 1236 </div> 1237 </div> 1238 1239 <p id="referralSignupMessageMobile" style="font-size: 16px; color: #333; margin: 0 0 30px 0; line-height: 1.5;"> 1240 Your friend gifted you credit! Sign up now to redeem. 1241 </p> 1242 1243 <button type="button" class="btn" onclick="goToSignupPageFromMobile()" style="width: 100%; color: #fff;"> 1244 Sign Up 1245 </button> 1246 </div> 1247 </div> 1248 </details> 1249 </details-modal> 1250 1251 1252 1253 </div> 1254 1255 1256 </div> 1257 </div> 1258</header> 1259 1260 1261 1262 1263 1264 1265 1266 <main class="wrapper main-content" role="main"> 1267 <div class="grid"> 1268 <div class="grid__item">
vendor: 100 bytes, lines 1268-1272
1268 1269 1270 1271 1272<script src="https://www.recaptcha.net/recaptcha/enterprise.js?render=
12726LdMNdIqAAAAALegJp7y4weVcCIlnwmIN8TWseEF
vendor: 12 bytes, line 1272
1272"></script>
1273<link rel="preload" href="https://store-themes.easystore.co/897413/themes/2877/assets/customer.css?t=1791441402" as="style" onload="this.onload=null;this.rel='stylesheet'"> 1274<style> 1275 main.main-content .field > label{ 1276 display: none; 1277 } 1278 .h3{ 1279 font-size: 18px; 1280 } 1281 .button--full-width{ 1282 width: 100%; 1283 } 1284 .tab-wrapper{ 1285 display: inline-flex; 1286 justify-content: center; 1287 align-items: center; 1288 margin: 10px auto 20px; 1289 background-color: #eaeaea; 1290 border-radius: 200px; 1291 padding: 5px; 1292 gap: 10px; 1293 } 1294 .tab-wrapper .tab-label { 1295 display: inline-block; 1296 min-width: 130px; 1297 padding: 8px 15px; 1298 border-radius: 100px; 1299 cursor: pointer; 1300 font-size: 17px; 1301 line-height: 1.1; 1302 user-select: none; 1303 margin: 0; 1304 color: #000; 1305 } 1306 #register-tos a { 1307 display: inline; 1308 } 1309 @media screen and (max-width: 400px){ 1310 .tab-wrapper .tab-label { 1311 min-width: 110px; 1312 } 1313 } 1314 .tab-wrapper input[type='radio']:checked + .tab-label { 1315 background-color: #fff; 1316 box-shadow: 2px 2px 25px -10px #333; 1317 } 1318 1319 @media screen and (min-width: 500px){ 1320 .large--five-twelfths{ 1321 min-width: 420px; 1322 } 1323 } 1324</style> 1325 1326 1327 1328 1329<div class="customer login section-width-control small-width large--five-twelfths text-center wrapper"> 1330 <div class="card"> 1331 <h1 id="login" tabindex="-1" class="mb-0"> 1332 Welcome 1333 </h1> 1334 <p class="h3 mt-0"> 1335 1336 Sign up or log in to continue 1337 1338 </p> 1339 <div> 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 <div class="tab-wrapper"> 1358 <div> 1359 <input type="radio" name="type" id="tab-register" class="hide hidden" checked> 1360 <label for="tab-register" class="tab-label"> 1361 Sign up 1362 </label> 1363 </div> 1364 <div> 1365 <input type="radio" name="type" id="tab-login" class="hide hidden"> 1366 <label for="tab-login" class="tab-label"> 1367 Login 1368 </label> 1369 </div> 1370 </div> 1371 1372 1373 <form id="form-login" action="/account/auth" method="post" class="mt-2"> 1374 <input type="hidden" name="_token" value="yNIxW1hoq0dss3xoPWARy0Hj9gwch3wF69BmtQmj"> 1375 <input type="hidden" name="location_id" value=""> 1376 <input type="hidden" name="staff_id" value=""> 1377 <input type="hidden" id="recaptchaResponse" name="g-recaptcha-response"> 1378 1379 1380 <div id="error-content"></div> 1381 1382 <div class="field"> 1383 <input 1384 type="text" 1385 name="customer[email_or_phone]" 1386 id="CustomerDetail" 1387 autocorrect="off" 1388 autocapitalize="off" 1389 placeholder="Email" 1390 required 1391 > 1392 <label for="CustomerDetail"> 1393 Email 1394 </label> 1395 </div> 1396 1397 <button 1398 type="submit" 1399 form="form-login" 1400 class="btn button--full-width g-recaptcha"> 1401 Continue 1402 </button> 1403 1404 <div class="button-snippet"> 1405 1406<!-- Snippet:login/button: Facebook Login --> 1407 <button id="fb-login-btn" type="button" class="btn" onclick="fb_login()" style="background-color: #3a5795; color: white; font-weight: bold;"><span class="icon icon-facebook" aria-hidden="true"></span> Continue with Facebook</button> 1408 1409
1409<script> 1410 function fb_login(){ 1411 location.href = 'https://apps.easystore.co/facebook-login/run?domain='+window.location.protocol+'//'+window.location.hostname+'&shop=pttiptti.easy.co'; 1412 } 1413 </script>
1413 1414<!-- /Snippet --> 1415 1416 </div> 1417 1418 1419 1420 <div id="register-tos"> 1421 By signing up, I agree to the PTTI's <a target="_blank" href="/legal/terms-of-service">Terms of Service</a>, <a target="_blank" href="/legal/privacy-policy">Privacy Policy</a> and <a target="_blank" href="/legal/refund-policy">Refund Policy</a>. 1422 </div> 1423 1424 </form> 1425 </div> 1426 </div> 1427 1428</div> 1429 1430 1431
1432<script> 1433 const register_tab = document.querySelector('#tab-register'); 1434 const login_tab = document.querySelector('#tab-login'); 1435 const register_tos = document.querySelector('#register-tos'); 1436 const isRegistrationEnabled = "1"; 1437 1438 if (register_tab) { 1439 register_tab.addEventListener('click', function() { 1440 if (register_tos) { 1441 register_tos.style.display = 'block'; 1442 } 1443 }); 1444 } 1445 if (login_tab) { 1446 login_tab.addEventListener('click', function() { 1447 if (register_tos) { 1448 register_tos.style.display = 'none'; 1449 } 1450 }); 1451 } 1452 1453 const methodSwitchBtn = document.getElementById('phone-login-btn'); 1454 if (methodSwitchBtn) { 1455 methodSwitchBtn.onclick = function () { 1456 var type = (register_tab && register_tab.checked) ? 'register' : 'login'; 1457 window.location.href = '/account/login?method=phone&type=' + type; 1458 }; 1459 } 1460 1461 let lastPathSegment = window.location.pathname.split('/').filter(segment => segment.length > 0).pop(); 1462 1463 // Redirect to login if trying to access register when self registration is disabled 1464 if (!isRegistrationEnabled) { 1465 if (lastPathSegment === 'register') { 1466 window.location.href = '/account/login'; 1467 } else if (lastPathSegment === 'login' || lastPathSegment === 'auth') { 1468 if (register_tos) { 1469 register_tos.style.display = 'none'; 1470 } 1471 } 1472 } else { 1473 // Only proceed with tab logic if not redirecting 1474 if(lastPathSegment === 'login') { 1475 if (login_tab) { 1476 login_tab.checked = true; 1477 } 1478 if (register_tos) { 1479 register_tos.style.display = 'none'; 1480 } 1481 } else { 1482 if (register_tos) { 1483 register_tos.style.display = 'block'; 1484 } 1485 } 1486 } 1487 1488 const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; 1489 const phonePattern = /^(?:\+?\d{1,3}[\s-]?)?(?:\d{1,14}[\s-]?){1,5}$/; 1490 1491 let form = document.querySelector('#form-login'), 1492 input = document.querySelector('#CustomerDetail'), 1493 error_content = document.querySelector('#error-content'); 1494 1495 1496 // One attempt at a time: the reCAPTCHA wait below is async, so without 1497 // this a double-click starts two continuations and posts the form twice. 1498 var submitting = false; 1499 1500 form.addEventListener('submit', async function (event) { 1501 // preventDefault FIRST: a re-entrant submit must still be cancelled, or the 1502 // browser performs a native post with no captcha token. 1503 event.preventDefault(); 1504 if (submitting) return; 1505 1506 let input_value = input.value 1507 error_content.innerHTML = ''; 1508 if (!input_value.match(emailPattern) && !input_value.match(phonePattern)) { 1509 error_content.innerHTML = `<div class="errors note">Invalid Email or Phone</div>`; 1510 return false; 1511 } 1512 1513 submitting = true; 1514 document.querySelector('#form-login .btn').classList.add('btn--loading','loading'); 1515 1516 // reCAPTCHA is unreachable from some regions (google.com is blocked in 1517 // mainland China). Fail open the same way checkout and forgot-password do: 1518 // submit without a token rather than leave the button spinning forever. 1519 try { 1520 if (window.grecaptcha && typeof window.grecaptcha.enterprise === 'object') { 1521 // The loader defines a stub {ready} synchronously and fetches the real 1522 // implementation asynchronously, so execute() may not exist yet. 1523 // ready() queues until it does; the timeout stops a bundle that never 1524 // arrives from hanging the button. 1525 await new Promise(function (resolve) { 1526 setTimeout(resolve, 3000); 1527 try { grecaptcha.enterprise.ready(resolve); } catch (e) { resolve(); } 1528 }); 1529 1530 const token = await grecaptcha.enterprise.execute('6LdMNdIqAAAAALegJp7y4weVcCIlnwmIN8TWseEF', { action: 'LOGIN' }); 1531 document.getElementById('recaptchaResponse').value = token; 1532 } 1533 } catch (e) { /* fail open */ } 1534 1535 document.getElementById('form-login').submit(); 1536 }); 1537 1538 1539</script>
1539 1540 1541 1542 1543 </div> 1544 </div> 1545 1546 1547 1548 </main> 1549 1550 <footer class="site-footer small--text-center" role="contentinfo"> 1551 1552 1553 1554 <div class="wrapper"> 1555 1556 <div class="grid-uniform"> 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 <div class="grid__item large--one-half "> 1580 <a href="/" class="logo-wrapper" itemprop="url" > 1581 1582 <img style="max-width: 250px" src="https://cdn.store-assets.com/s/897413/f/8257285.png?width=350&format=webp" alt="PTTI" itemprop="logo"> 1583 1584 </a> 1585 <p class="site-footer__links">© 2026 PTTI GROUP SDN BHD</p> 1586 </div> 1587 1588 1589 <div class="grid__item large--one-quarter medium--one-half"> 1590 1591 <h4>Quick Links</h4> 1592 1593 <ul class="site-footer__links"> 1594 1595 <li><a href="/pages/news-coverage" >News Coverage</a></li> 1596 1597 <li><a href="/pages/careers-we-are-hiring" >Careers (We Are Hiring!)</a></li> 1598 1599 <li><a href="/pages/download-ptti-app-free" >Download PTTI APP (Free)</a></li> 1600 1601 1602 </ul> 1603 </div> 1604 1605 1606 1607 <div class="grid__item large--one-quarter medium--one-half"> 1608 <h4>Follow Us</h4> 1609 1610 <ul class="inline-list social-icons"> 1611 1612 1613 1614 1615 <li> 1616 <a class="icon-fallback-text" href="https://instagram.com/pttionline?utm_medium=copy_link" title="PTTI on Instagram" target="_blank"> 1617 1618 1619 1620 1621 <svg xmlns="http://www.w3.org/2000/svg" class="instagram-icon-svg social-icon-svg" viewBox="0 0 1024 1024"> 1622 <title>icon-instagram</title> 1623 <path d="M834.35,341.22a231.23,231.23,0,0,0-9.59-46.45,166.71,166.71,0,0,0-52.17-78.33c-17-14.41-36.33-24.44-57.44-31.3-21.52-7-43.69-10.21-66.19-11.12-22.28-.9-44.58-1.73-66.87-1.85-47.68-.26-95.37-.16-143.06,0-27.47.11-54.95.69-82.32,3.39a220.7,220.7,0,0,0-37.43,6.95c-26.2,7.26-50,19-70.24,37.45-18.06,16.4-32.3,35.52-41.87,58.05-9.89,23.29-15.13,47.68-16.69,72.82-1.23,19.78-2.06,39.6-2.32,59.41-.38,28.91-.1,57.82-.1,86.73-.23,39.92-.67,79.85,1,119.76.72,17.66,1.57,35.3,4.6,52.76,3.22,18.52,8.32,36.51,16.71,53.34C232.83,768,268.81,797,317.12,811a246.28,246.28,0,0,0,59.24,9.11c25.3.95,50.63,1.78,75.95,1.94,43.83.28,87.66.1,131.5,0,26-.08,52.08-.72,78.06-2.74a234.52,234.52,0,0,0,45.76-8c24.54-6.92,46.82-18.12,66.22-34.79,24.65-21.17,41.5-47.44,51.3-78.36,6.7-21.14,9.83-42.88,10.73-64.94.9-21.84,1.73-43.69,1.82-65.55q.33-78.21-.15-156.44C837.42,387.82,836.72,364.47,834.35,341.22Zm-55.3,232.84c-.12,20.41-1,40.84-2,61.24-1,19.2-4.13,38.08-11.74,55.92q-18.43,43.24-62.47,60c-14.36,5.48-29.3,8.3-44.55,9.53-27.07,2.18-54.21,2.63-81.36,2.73-21.31.07-42.62,0-63.93,0v-.16c-28.47,0-56.94.22-85.4-.09-17.5-.18-35-1-52.49-1.89-19.94-1-39.51-4.31-57.95-12.38q-41.6-18.2-58-60.68a162.37,162.37,0,0,1-9.95-45.62c-2-24.66-2.62-49.38-2.66-74.1-.09-50.88-.16-101.77.12-152.65.11-19,1-38.09,2-57.11a180,180,0,0,1,8.78-48.23c8.32-24.84,23.63-44.14,45.66-58.12,11.78-7.48,24.85-11.91,38.36-15,15.57-3.61,31.43-4.65,47.34-5.32,54.32-2.28,108.68-1.46,163-1.5,18.67,0,37.34.12,56,.56,15.84.38,31.7,1,47.51,2,18.33,1.18,36.27,4.59,53.19,12q41.67,18.25,58.1,60.83c5.67,14.7,8.64,30,9.91,45.63,2,25,2.63,50,2.67,75.09C779.25,475.82,779.35,524.94,779.05,574.06Z" fill="#999"/><path d="M513,330.12c-92-.34-167,74.55-167.08,166.87s74.71,167,167,167A166.86,166.86,0,0,0,679.77,497.12C679.87,405,605.46,330.45,513,330.12Zm-.29,275.31A108.38,108.38,0,1,1,621.21,497.15,108.38,108.38,0,0,1,512.7,605.43Z" fill="#999"/><path d="M686.47,284.5a39,39,0,1,0,38.92,39.14A39,39,0,0,0,686.47,284.5Z" fill="#999"/> 1624 </svg> 1625 1626 1627 1628 <span class="fallback-text">Instagram</span> 1629 </a> 1630 </li> 1631 1632 1633 1634 1635 1636 1637 <li> 1638 <a class="icon-fallback-text" href="https://WebsitePTTI.wasap.my " title="PTTI on Whatsapp" target="_blank"> 1639 1640 1641 1642 1643 <svg xmlns="http://www.w3.org/2000/svg" class="whatsapp-icon-svg social-icon-svg" viewBox="0 0 1024 1024"> 1644 <title>icon-whatsapp</title> 1645 <path d="M816.7,348.82A345.81,345.81,0,0,0,694.1,218.71c-44.79-28-93.6-44.39-146.07-49.88a345.45,345.45,0,0,0-92,2.72,339.05,339.05,0,0,0-94.38,29.87A343.85,343.85,0,0,0,238,302.05Q177.25,381,167.56,480.22a345,345,0,0,0,43.29,203.46,6.68,6.68,0,0,1,.57,4.56q-16.36,60.35-32.93,120.63c-5.08,18.56-10.2,37.12-15.43,56.13,1.15-.24,1.8-.34,2.43-.51Q254.72,841.08,344,817.7a7.88,7.88,0,0,1,4.84.57c11.92,5.41,23.56,11.5,35.68,16.39a344.42,344.42,0,0,0,274.43-8.3,343.9,343.9,0,0,0,122.89-97q64.35-80.48,74.57-183.1a344.59,344.59,0,0,0-2.88-89.12A336.49,336.49,0,0,0,816.7,348.82ZM799.12,528.11c-3.35,60.82-23.74,115.33-61.56,163C695.72,743.88,641.71,778,576.15,793.47A277.11,277.11,0,0,1,491.09,800a284.89,284.89,0,0,1-129.36-41.68,16.37,16.37,0,0,0-14.17-2c-33.08,8.93-66.26,17.47-99.4,26.13-.46.12-.93.19-2,.42,1.61-5.94,3.07-11.39,4.56-16.83q11.91-43.44,23.73-86.9a6.64,6.64,0,0,0-.91-4.73c-11.53-18-21.73-36.58-29.45-56.51a287.49,287.49,0,0,1-17.41-68.71c-5.7-46-.87-90.81,15-134.35a287.26,287.26,0,0,1,479.82-98.72c32.53,34.66,55.29,74.85,67.86,120.72A284,284,0,0,1,799.12,528.11Z" fill="#999"/><path d="M679.23,590c-12.9-6.08-25.57-12.63-38.44-18.75-10.69-5.09-21.41-10.15-32.36-14.63-8.48-3.47-12.2-1.6-17.82,5.65-8.75,11.27-17.79,22.32-26.93,33.28-4.38,5.25-8.82,6.33-15,3.54-11.48-5.18-23.13-10.16-34.09-16.32C477.68,562,449.73,532.17,428.22,496c-4.54-7.64-4-11.33,2-17.83,8.45-9.23,17.15-18.29,22.45-29.93a16.29,16.29,0,0,0,.44-13.68c-8.9-21.42-17.75-42.87-26.8-64.23a70.6,70.6,0,0,0-6.52-11.83c-2.39-3.56-6.15-5.12-10.51-5-3.28,0-6.56,0-9.84,0,0-.17,0-.34,0-.52-5.1.27-10.26.1-15.27.89-8.07,1.27-14,6.29-19.53,12.06-23.72,24.67-32.22,53.95-26.71,87.44a135.88,135.88,0,0,0,19.34,50.09c9.28,14.85,19.38,29.25,29.94,43.23a405.65,405.65,0,0,0,65.73,68.21c29.34,24.26,62.45,41.51,98.38,53.66,15,5.07,29.89,10.33,46,10.64,10.73.21,21.46.08,31.83-3a103.21,103.21,0,0,0,39.24-22c5.11-4.48,9.77-9.49,12.29-15.89a103.2,103.2,0,0,0,7.06-34.67C687.88,597,685.22,592.79,679.23,590Z" fill="#999"/> 1646 </svg> 1647 1648 1649
1650 <span class="fallback-text">Whatsapp</span> 1651 </a> 1652 </li> 1653 1654 1655 1656 1657</ul> 1658 1659 </div> 1660 1661 </div> 1662 1663 <hr class="hr--small hr--clear"> 1664 1665 1666 <div class="grid"> 1667 1668 <div class="grid__item text-center"> 1669 <ul class="inline-list payment-icons"> 1670 1671 <li> 1672 <span class="icon-fallback-text"> 1673 <span class="icon icon-visa" aria-hidden="true"></span> 1674 <span class="fallback-text">Visa</span> 1675 </span> 1676 </li> 1677 1678 1679 <li> 1680 <span class="icon-fallback-text"> 1681 <span class="icon icon-master" aria-hidden="true"></span> 1682 <span class="fallback-text">Master</span> 1683 </span> 1684 </li> 1685 1686 1687 1688 1689 1690 </ul> 1691 </div> 1692 1693 1694 <div class="grid__item text-center"> 1695 <ul class="inline-list payment-icons"> 1696 1697 <li> 1698 <img src="https://s3.dualstack.ap-southeast-1.amazonaws.com/eesb.public/images/payment/payments_billplz.svg" alt="payment_billplz"> 1699 </li> 1700 1701 <li> 1702 <img src="https://s3.dualstack.ap-southeast-1.amazonaws.com/eesb.public/images/payment/payments_razerms.svg" alt="payment_razerms"> 1703 </li> 1704 1705 <li> 1706 <img src="https://s3.dualstack.ap-southeast-1.amazonaws.com/eesb.public/images/payment/payments_atome.svg" alt="payment_atome"> 1707 </li> 1708 1709 </ul> 1710 </div> 1711 1712 1713 <div class="grid__item text-center"> 1714 <ul class="inline-list payment-icons"> 1715 <li> 1716 <img src="https://s3-ap-southeast-1.amazonaws.com/eesb.public/images/payment/ssl_certified.png"> 1717 </li> 1718 </ul> 1719 </div> 1720 1721 </div> 1722 1723 1724 <div class="grid"> 1725 <div class="grid__item text-center"> 1726 1727 1728 <p class="site-footer__links"> 1729 1730 1731 1732 <a href="/legal/terms-of-service">Terms of Service</a> 1733 1734 1735 1736 1737 | <a href="/legal/privacy-policy">Privacy Policy</a> 1738 1739 1740 1741 1742 | <a href="/legal/refund-policy">Refund Policy</a> 1743 1744 1745 1746 </p> 1747 1748 </div> 1749 </div> 1750 1751 </div> 1752 </footer> 1753 1754 1755<div class="footer-bar large--hide"> 1756 <div> 1757 1758 1759 1760 1761 1762 1763 <a href="https://www.ptti.my/pages/better-result"> 1764 1765 <img src="https://cdn.store-assets.com/s/897413/f/8327050.png?width=150&format=webp"/> 1766 1767 <div> 1768 Our Students 1769 </div> 1770 </a> 1771 1772 1773 1774 1775 1776 1777 1778 1779 <a href="https://www.ptti.my/pages/free-trial"> 1780 1781 <img src="https://cdn.store-assets.com/s/897413/f/8327783.gif"/> 1782 1783 <div> 1784 Free Trial 1785 </div> 1786 </a> 1787 1788 1789 1790 1791 1792 1793 1794 1795 <a href="https://www.ptti.my/pages/choose-your-level"> 1796 1797 <img src="https://cdn.store-assets.com/s/897413/f/8327612.gif"/> 1798 1799 <div> 1800 Join OTC 1801 </div> 1802 </a> 1803 1804 1805 1806 1807 1808 1809 1810 1811 <a href="https://www.ptti.my/pages/ask-ptti"> 1812 1813 <img src="https://cdn.store-assets.com/s/897413/f/8335499.png?width=150&format=webp"/> 1814 1815 <div> 1816 Ask PTTI 1817 </div> 1818 </a> 1819 1820 1821 1822 </div> 1823</div> 1824 1825 1826 1827 1828 1829 1830 <div id="scrollTopButton" class="on-right" style="display: none"> 1831 <svg class="svg-icon" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
1831<path d="M22,18.25a1.21,1.21,0,0,1-.88-.37L12,8.77,2.88,17.88a1.24,1.24,0,0,1-1.76-1.76l10-10a1.24,1.24,0,0,1,1.76,0l10,10a1.24,1.24,0,0,1,0,1.76A1.21,1.21,0,0,1,22,18.25Z"/></svg> 1832 </div> 1833
1833<script> 1834 $( document ).ready(function() { 1835 var winScroll = $(this).scrollTop(), 1836 this_el = $("#scrollTopButton"); 1837 1838 // Header bar 1839 if(winScroll > 400){ 1840 this_el.fadeIn(); 1841 }else{ 1842 this_el.fadeOut(); 1843 } 1844 1845 $("#scrollTopButton").click(function() { 1846 $('html,body').animate({ scrollTop: 0 }); 1847 }); 1848 1849 $(window).scroll(function(){ 1850 var winScroll = $(this).scrollTop(); 1851 1852 // Header bar 1853 if(winScroll > 400){ 1854 this_el.fadeIn(); 1855 }else{ 1856 this_el.fadeOut(); 1857 } 1858 1859 }); 1860 }); 1861 </script>
1861 1862 1863 1864 1865 1866 1867
1867<script src="https://store-themes.easystore.co/897413/themes/2877/assets/fastclick.min.js?t=1791441402" type="text/javascript" ></script>
1867 1868
1868<script src="https://store-themes.easystore.co/897413/themes/2877/assets/timber.js?v1.1?t=1791441402" type="text/javascript" ></script>
1868 1869
1869<script src="https://store-themes.easystore.co/897413/themes/2877/assets/theme.js?t=1791441402" type="text/javascript" ></script>
1869 1870 1871 1872 1873 1874 1875 1876
1877<script src="/assets/currencies.js" type="text/javascript" ></script>
vendor: 1 bytes, line 1877
1877
1878<script src="/assets/jquery.currencies.min.js" type="text/javascript" ></script>
vendor: 1 bytes, line 1878
1878
1879<script src="/assets/currencies_format.js" type="text/javascript" ></script>
1879 1880
1881<script> 1882Currency.format = "money_with_currency_format"; 1883var shopCurrency = 'MYR'; 1884var selectedCurrency = ''; 1885 1886 1887 Currency.convert = function(amount, from, to) { 1888 return amount; 1889 }; 1890 1891 1892if( $.cookie("currency") == null ){ 1893 1894 if( selectedCurrency != false ) { 1895 1896 Currency.convertAll(shopCurrency, selectedCurrency); 1897 jQuery('.selected-currency').text(Currency.currentCurrency); 1898 1899 } 1900 1901} 1902 1903/* Sometimes merchants change their shop currency, let's tell our JavaScript file */ 1904// Currency.moneyFormats[shopCurrency].money_with_currency_format = ""; 1905// Currency.moneyFormats[shopCurrency].money_format = "RM {{amount}} "; 1906 1907/* Default currency */ 1908var defaultCurrency = 'MYR'; 1909 1910/* Cookie currency */ 1911var cookieCurrency = Currency.cookie.read(); 1912 1913 cookieCurrency = shopCurrency; 1914 1915$("input[name=current_currency]").val(cookieCurrency); 1916if(cookieCurrency == null){ 1917 cookieCurrency = shopCurrency; 1918 Currency.cookie.write(shopCurrency); 1919} 1920/* Fix for customer account pages */ 1921jQuery('span.money span.money').each(function() { 1922 jQuery(this).parents('span.money').removeClass('money'); 1923}); 1924/* Saving the current price */ 1925jQuery('span.money').each(function() { 1926 jQuery(this).attr('data-currency-MYR', jQuery(this).html()); 1927}); 1928// If there's no cookie. 1929if (cookieCurrency == null) { 1930 if (shopCurrency !== defaultCurrency) { 1931 Currency.convertAll(shopCurrency, defaultCurrency); 1932 } 1933 else { 1934 Currency.currentCurrency = defaultCurrency; 1935 } 1936} 1937// If the cookie value does not correspond to any value in the currency dropdown. 1938else if (jQuery('[name=currencies]').size() && jQuery('[name=currencies] option[value=' + cookieCurrency + ']').size() === 0) { 1939 Currency.currentCurrency = shopCurrency; 1940 Currency.cookie.write(shopCurrency); 1941} 1942else if (cookieCurrency === shopCurrency) { 1943 Currency.currentCurrency = shopCurrency; 1944 Currency.convertAll(shopCurrency, cookieCurrency); 1945} 1946else { 1947 Currency.convertAll(shopCurrency, cookieCurrency); 1948} 1949jQuery('[name=currencies]').val(Currency.currentCurrency).change(function() { 1950 var newCurrency = jQuery(this).val(); 1951 1952 1953 Currency.cookie.write(newCurrency) 1954 if ('customers' == 'cart') { 1955 const params = new URLSearchParams(window.location.search); 1956 params.set('delete_cache', 1); 1957 window.location.search = params; 1958 } else { 1959 window.location.reload(); 1960 } 1961 1962}); 1963var original_selectCallback = window.selectCallback; 1964var selectCallback = function(variant, selector) { 1965 var currencies = null; 1966 original_selectCallback(variant, selector); 1967 if(typeof jQuery('[name=currencies]').val() == "undefined"){ 1968 currencies = shopCurrency; 1969 } 1970 else{ 1971 currencies = jQuery('[name=currencies]').val(); 1972 } 1973 Currency.convertAll(shopCurrency, currencies); 1974 jQuery('.selected-currency').text(Currency.currentCurrency); 1975}; 1976$('body').on('ajaxCart.afterCartLoad', function(cart) { 1977 Currency.convertAll(shopCurrency, jQuery('[name=currencies]').val()); 1978 jQuery('.selected-currency').text(Currency.currentCurrency); 1979}); 1980jQuery('.selected-currency').text(Currency.currentCurrency); 1981</script>
1981 1982 1983 1984
1984<script> 1985 1986 /* 1987 1988 ------ 1989 Events 1990 ------ 1991 1992 pages/viewed 1993 1994 customers/signup 1995 1996 customers/login 1997 1998 products/searched 1999 2000 collections/viewed 2001 2002 products/viewed 2003 2004 products/shared 2005 2006 wishlists/item_added 2007 2008 carts/items_added 2009 2010 carts/viewed 2011 2012 carts/item_removed 2013 2014 checkouts/initiated 2015 2016 checkouts/shipping_info_added 2017 2018 checkouts/payment_info_added 2019 2020 checkouts/completed 2021 2022 orders/placed 2023 2024 orders/purchased 2025 2026 payments/captured 2027 2028 payments/failed 2029 2030 */ 2031 2032 window.__latest_cart = window.__latest_cart || null; 2033 2034 const _selector = document.querySelector.bind(document), 2035 _selectorAll = document.querySelectorAll.bind(document) 2036 2037 document.addEventListener('DOMContentLoaded', (event) => { 2038 2039 const default_currency = getCookie("currency") 2040 const customer_id = window.__st.cid 2041 const template = window.__st.p 2042 2043 onPageView() 2044 2045 //-----------------------// 2046 // Configs // 2047 //-----------------------// 2048 2049 window.dataLayer = window.dataLayer || [] 2050 2051 Array.prototype.last = Array.prototype.last || function() { 2052 return this[this.length - 1] || null 2053 } 2054 2055 Array.prototype.first = Array.prototype.first || function() { 2056 return this[0] || null 2057 } 2058 2059 //----------------------// 2060 // Triggers // 2061 //----------------------// 2062 2063 const XHR = window.XMLHttpRequest 2064 2065 function xhr() { 2066 2067 const xhr = new XHR() 2068 2069 xhr.addEventListener("readystatechange", function() { 2070 2071 if(xhr.readyState != 4) return 2072 2073 try { 2074 2075 const response_url = xhr.responseURL 2076 2077 if (response_url.includes("cart/add")) { 2078 2079 window.__latest_cart = JSON.parse(xhr.response) 2080 2081 onCartItemsAdded() // ok 2082 2083 } 2084 2085 if (response_url.includes("cart/remove_item_quantity")) { 2086 2087 window.__latest_cart = JSON.parse(xhr.response) 2088 2089 onCartItemRemoved() // ok 2090 2091 } 2092 2093 if (response_url.includes("new_cart?retrieve=true")) { 2094 2095 result = JSON.parse(xhr.response) 2096 2097 if (result.cart) { 2098 window.__latest_cart = result.cart 2099 } 2100 2101 } 2102 2103 } catch(e) { 2104 2105 console.error(e) 2106 2107 } 2108 2109 }, false); 2110 2111 return xhr 2112 2113 } 2114 2115 window.XMLHttpRequest = xhr 2116 2117 switch(template) { 2118 2119 case 'cart': onCartView() // ok 2120 break 2121 case 'product': onProductView() // ok 2122 break 2123 case 'collection': onCollectionView() // ok 2124 break 2125 case 'blog': onBlogView() 2126 break 2127 case 'article': onArticleView() 2128 break 2129 case 'payment_completed': onOrderPlace() 2130 break 2131 case 'payment_fail': onPaymentFail() 2132 break 2133 2134 } 2135 2136 // _selector('form[action="/checkout/payments"]').addEventListener("submit", onPaymentInfoAdded(_selector('form[action="/checkout/payments"]'))) 2137 if (_selector('form[action="/checkout/detail"]')) _selector('form[action="/checkout/detail"]').addEventListener("submit", ()=>{onShippingInfoAdded(_selector('form[action="/checkout/detail"]'))}) // ok 2138 if (_selector('form[action="/checkout/shipping"]')) _selector('form[action="/checkout/shipping"]').addEventListener("submit", ()=>{onShippingInfoAdded(_selector('form[action="/checkout/shipping"]'))}) // ok 2139 if (_selector('form[action="/account/register"]')) _selector('form[action="/account/register"]').addEventListener("submit", onSignUp) // ok 2140 if (_selector('form[action="/account/login"]')) _selector('form[action="/account/login"]').addEventListener("submit", onLogin) // ok 2141 if (_selector('form[action="/search"]')) _selector('form[action="/search"]').addEventListener("submit", onProductSearch()) // ok 2142 if (_selector('#line-login-btn')) _selector('#line-login-btn').addEventListener('click', onLineLogin) // ok 2143 if (_selector('#PlaceOrder')) _selector('#PlaceOrder').addEventListener("click", ()=>{onCheckoutComplete(_selector('form[action="/checkout/payments"]'))}); // ok 2144 if (_selector('#add_wishlist')) _selector('#add_wishlist').addEventListener("click", onWishlistItemAdded) // ok 2145 if (_selectorAll('a[href="/account/logout"]')) _selectorAll('a[href="/account/logout"]').forEach(logoutButton => logoutButton.addEventListener("click", onLogout)) // ok 2146 if (_selector('.CartDrawerTrigger.cart-page-link')) _selector('.CartDrawerTrigger.cart-page-link').addEventListener("click", onCartView) // ok 2147 if (_selector('.CartDrawerTrigger.cart-page-link.mobile-cart-page-link')) _selector('.CartDrawerTrigger.cart-page-link.mobile-cart-page-link').addEventListener("click", onCartView) // ok 2148 if (_selectorAll('a[class^="share-"]')) _selectorAll('a[class^="share-"]').forEach(shareButton => shareButton.addEventListener("click", ()=>{onProductShare(shareButton)}) ) // ok 2149 if (_selectorAll('[name$="checkout"]')) _selectorAll('[name$="checkout"]').forEach(checkoutButton => checkoutButton.addEventListener("click", onCheckoutInitiate)) 2150 2151 // For append elements 2152 const bodyMutationObserver = new MutationObserver(() => { 2153 if (_selector('#form__spc #PlaceOrder')) _selector('#form__spc #PlaceOrder').addEventListener("click", onSinglePageCheckout) // ok 2154 if (_selectorAll('[name$="checkout"]')) _selectorAll('[name$="checkout"]').forEach(checkoutButton => checkoutButton.addEventListener("click", onCheckoutInitiate)) 2155 }); 2156 bodyMutationObserver.observe(_selector("body"), {subtree: true, childList: true}); 2157 2158 //------------------------------// 2159 // Event handlers // 2160 //------------------------------// 2161 2162 function onPageView() { 2163 2164 EasyStore.Event.dispatch('pages/viewed', { 2165 page: { 2166 type: template, 2167 title: document.title, 2168 description: _selector('meta[name=description]') ? _selector('meta[name=description]').getAttribute('content') : null, 2169 url: location.href, 2170 } 2171 }) 2172 2173 } 2174 2175 function onSignUp() { 2176 2177 const email_regex = new RegExp(/^[a-zA-Z0-9.!#$%&"*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/) 2178 const phone_regex = new RegExp(/^(\+?6?01)[0-46-9]-*[0-9]{7,8}$/) 2179 2180 const email_or_phone = _selector(`input[name="customer[email_or_phone]"]`).value.replace("+", "").replace(/\s+/, "") 2181 2182 let data = {} 2183 2184 if (email_regex.test(email_or_phone)) { 2185 data.method = 'email' 2186 data.email = email_or_phone 2187 } 2188 2189 if (phone_regex.test(email_or_phone)) { 2190 data.method = "phone" 2191 data.phone = email_or_phone 2192 } 2193 2194 if (!data.method) return 2195 2196 EasyStore.Event.dispatch('customers/signup', data) 2197 2198 } 2199 2200 function onLogin() { 2201 2202 const email_regex = new RegExp(/^[a-zA-Z0-9.!#$%&"*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/) 2203 const phone_regex = new RegExp(/^(\+?6?01)[0-46-9]-*[0-9]{7,8}$/) 2204 2205 const email_or_phone = _selector(`input[name="customer[email_or_phone]"]`).value.replace("+", "").replace(/\s+/, "") 2206 2207 let data = {} 2208 2209 if (email_regex.test(email_or_phone)) { 2210 data.method = 'email' 2211 data.email = email_or_phone 2212 } 2213 2214 if (phone_regex.test(email_or_phone)) { 2215 data.method = "phone" 2216 data.phone = email_or_phone 2217 } 2218 2219 if (!data.method) return 2220 2221 EasyStore.Event.dispatch('customers/login', data) 2222 2223 } 2224 2225 function onLineLogin() { 2226 2227 EasyStore.Event.dispatch('customers/login', { method: 'line' }) 2228 2229 } 2230 2231 function onLogout() { 2232 2233 EasyStore.Event.dispatch('customers/logout', { customer_id }) 2234 2235 } 2236 2237 function onBlogView() { 2238 2239 const blog = "" 2240 2241 EasyStore.Event.dispatch('blogs/viewed', { blog }) 2242 2243 } 2244 2245 function onArticleView() { 2246 2247 const article = "" 2248 2249 EasyStore.Event.dispatch('articles/viewed', { article }) 2250 2251 } 2252 2253 function onProductSearch() { 2254 2255 const query = _selector('input[name=q]').value 2256 2257 if (!query) return 2258 2259 EasyStore.Event.dispatch('products/searched', { query }) 2260 2261 } 2262 2263 function onCollectionView() { 2264 2265 const collection = "" 2266 2267 EasyStore.Event.dispatch('collections/viewed', { collection }) 2268 2269 } 2270 2271 function onProductView() { 2272 2273 const product = "" 2274 2275 EasyStore.Event.dispatch("products/viewed", { product }) 2276 2277 } 2278 2279 function onProductShare(el) { 2280 2281 const product = "" 2282 2283 const channel = el.getAttribute("class").split("-").last() 2284 2285 EasyStore.Event.dispatch('products/shared', { product, channel }) 2286 2287 } 2288 2289 function onWishlistItemAdded() { 2290 2291 let product = "" 2292 const quantity = _selector("#Quantity").value 2293 2294 EasyStore.Event.dispatch('wishlists/item_added', { product }) 2295 2296 } 2297 2298 async function onCartItemsAdded() { 2299 2300 const cart = await getCart() 2301 2302 if(cart && cart.items != undefined && cart.items.length > 0) { 2303 2304 EasyStore.Event.dispatch('carts/item_added', { cart }) 2305 2306 } 2307 2308 } 2309 2310 async function onCartView() { 2311 2312 const cart = await getCart() 2313 2314 EasyStore.Event.dispatch('carts/viewed', { cart }) 2315 2316 } 2317 2318 async function onCartItemRemoved() { 2319 2320 const cart = await getCart() 2321 2322 cart.items = [] 2323 2324 if(cart) { 2325 2326 EasyStore.Event.dispatch('carts/item_removed', { cart }) 2327 2328 } 2329 2330 } 2331 2332 async function onCheckoutInitiate() { 2333 2334 const cart = await getCart() 2335 2336 EasyStore.Event.dispatch('checkouts/initiated', { cart }) 2337 2338 } 2339 2340 async function onShippingInfoAdded(form) { 2341 let checkout = getCheckout() 2342 2343 let form_data = {} 2344 new FormData(form).forEach((value, key) => form_data[key] = value) 2345 2346 let shipping_tier = null 2347 2348 if (form_data.type && form_data.type.startsWith("r_pickup")) { 2349 shipping_tier = `Pickup - ${form_data.pick_location}` 2350 } 2351 2352 if (form_data.s_id) {
2353 shipping_tier = _selector(`input[id='`+form_data.s_id+`']`).getAttribute("data-shipping-name") 2354 } 2355 2356 if (!shipping_tier) return 2357 2358 EasyStore.Event.dispatch('checkouts/shipping_info_added', { checkout, shipping_tier }) 2359 2360 } 2361 2362 async function onPaymentInfoAdded(form) { 2363 2364 let checkout = getCheckout() 2365 2366 let payment_type = new FormData(form).get('payment_method') 2367 2368 EasyStore.Event.dispatch("checkouts/payment_info_added", { checkout, payment_type }) 2369 2370 } 2371 2372 async function onOrderPlace() { 2373 2374 let cart_token = getCookie("cart_js") 2375 let previous_cart_token = getCookie("previous_cart_ga4_js") 2376 2377 if (previous_cart_token && previous_cart_token == cart_token) { 2378 // Prevent duplicate purchase tracking 2379 return 2380 } 2381 2382 let order = getOrder() 2383 2384 EasyStore.Event.dispatch('orders/placed', { order }) 2385 2386 if(order.is_manual_payment) { 2387 2388 EasyStore.Event.dispatch('orders/purchased', { order }) 2389 2390 } 2391 2392 const last_transaction = order.transactions.last() 2393 2394 if (last_transaction.status) { 2395 2396 EasyStore.Event.dispatch('orders/purchased', { order }) 2397 EasyStore.Event.dispatch('payments/captured', { order }) 2398 2399 } 2400 2401 } 2402 2403 async function onPaymentFail() { 2404 2405 const order = getOrder() 2406 2407 EasyStore.Event.dispatch('payments/failed', { order }) 2408 2409 } 2410 2411 async function onCheckoutComplete(form) { 2412 2413 onPaymentInfoAdded(form) 2414 2415 const checkout = getCheckout() 2416 2417 EasyStore.Event.dispatch('checkouts/completed', { checkout }) 2418 2419 } 2420 2421 async function onSinglePageCheckout() { 2422 2423 // let checkout = $("[data-app-checkout]").data("app-checkout") 2424 2425 let checkout = getCheckout() 2426 2427 // const payment_type = _selector("#app_spc_payment_method").find(`[class*="label-content"]`).first().find("b").first().text() 2428 const payment_type = _selector("#app_spc_payment_method").getElementsByClassName('label-content')[0].getElementsByTagName('b')[0].innerHTML 2429 2430 const shipping_method = _selector("#delivery_method").value 2431 2432 let shipping_tier = null 2433 let app_spc_customer_info_label = _selector("#app_spc_customer_info").getElementsByClassName('label-content') 2434 if (shipping_method == "shipping") { 2435 shipping_tier = app_spc_customer_info_label[app_spc_customer_info_label.length - 1].getElementsByTagName('b')[0].innerHTML 2436 } 2437 2438 if (shipping_method == "pickup") { 2439 shipping_tier = app_spc_customer_info_label[0].innerHTML 2440 } 2441 2442 if (shipping_tier) { 2443 2444 EasyStore.Event.dispatch('checkouts/shipping_info_added', { 2445 checkout, 2446 shipping_tier, 2447 }) 2448 2449 } 2450 2451 if (payment_type) { 2452 2453 EasyStore.Event.dispatch('checkouts/payment_info_added', { 2454 checkout, 2455 payment_type, 2456 }) 2457 2458 } 2459 2460 EasyStore.Event.dispatch('checkouts/completed', { checkout }) 2461 2462 } 2463 2464 }) 2465 2466 2467 //-----------------------// 2468 // Functions // 2469 //-----------------------// 2470 2471 function getCookie(name) { 2472 2473 name += "=" 2474 2475 decodedCookie = decodeURIComponent(document.cookie) 2476 2477 ca = decodedCookie.split(";") 2478 2479 for(i = 0; i < ca.length; i++) { 2480 c = ca[i] 2481 while (c.charAt(0) == " ") { 2482 c = c.substring(1) 2483 } 2484 if (c.indexOf(name) == 0) { 2485 return c.substring(name.length, c.length) 2486 } 2487 } 2488 2489 return "" 2490 2491 } 2492 2493 const parsePrice = price => { 2494 if(typeof price === 'string') { 2495 return parseFloat(price.split(',').join('')) 2496 } 2497 2498 return price 2499 } 2500 2501 const requestCart = async (method, data) => { 2502 2503 let response = await fetch('/cart.json', {method: 'GET',headers: {'Content-Type': 'application/json'}}) 2504 result = await response.json() 2505 2506 return result.cart 2507 2508 } 2509 const getCart = async (latest = false) => { 2510 2511 let cart = window.__latest_cart 2512 2513 const cart_invalid = !cart || !cart.items || (cart.total_price > 0 && !cart.items.length) 2514 2515 if(latest || cart_invalid) { 2516 cart = await requestCart() 2517 } 2518 2519 cart.items = cart.items || [] 2520 2521 return mapCart(cart) 2522 2523 } 2524 2525 const getCheckout = async () => { 2526 mapCheckout(window.__latest_cart || await requestCart()) 2527 } 2528 2529 const getOrder = async () => { 2530 mapOrder(window.__latest_cart || await requestCart()) 2531 } 2532 2533 //-----------------------// 2534 // Mappers // 2535 //-----------------------// 2536 2537 const fallbackAttribute = (object, attribute) => { 2538 2539 if(!Array.isArray(attribute)) { 2540 attribute = [attribute] 2541 } 2542 2543 let final_value = null 2544 2545 do { 2546 2547 final_value = object[attribute.shift()] 2548 2549 } while(!final_value && attribute.length) 2550 2551 return final_value 2552 2553 } 2554 2555 const map = (object, mapper) => { 2556 2557 const newObject = {} 2558 2559 for(const key in mapper) { 2560 2561 // Handle different keys between new and old format
2562 newObject[key] = fallbackAttribute(object, mapper[key]) 2563 2564 // Cast price to float 2565 if(newObject[key] && ['price', 'amount', 'discount', 'discounts'].some(x => key.endsWith(x))) { 2566 newObject[key] = parsePrice(newObject[key]) 2567 } 2568 2569 if(newObject[key] === undefined) { 2570 delete newObject[key] 2571 } 2572 2573 } 2574 2575 return newObject 2576 2577 } 2578 2579 const mapCart = cart => { 2580 2581 const oldCart = cart 2582 2583 const mapper = { 2584 id: 'id', 2585 currency: 'currency', 2586 item_count: 'item_count', 2587 items: 'items', 2588 total_price: 'total_price', 2589 latest_items: 'latest_items' 2590 } 2591 2592 cart = map(cart, mapper) 2593 2594 const discounts = (oldCart.storewide_discounts || []).concat((oldCart.voucher_discounts || [])) 2595 2596 cart.discount_applications = discounts.map(discount => ({ 2597 title: discount.voucher_code || null, 2598 value: parsePrice(discount.amount), 2599 })) 2600 2601 cart.original_total_price = cart.items.length 2602 ? cart.items 2603 .map(item => item.original_price) 2604 .reduce((sum, price) => sum + price) 2605 : 0 2606 2607 cart.total_discount = cart.discount_applications.length 2608 ? cart.discount_applications 2609 .map(discount => parsePrice(discount.value)) 2610 .reduce((sum, value) => sum + value) 2611 : 0 2612 2613 cart.items = cart.items.map(item => mapLineItem(item)) 2614 2615 return cart 2616 2617 } 2618 2619 const mapCheckout = checkout => { 2620 2621 const mapper = { 2622 note: 'note', 2623 attributes: 'note_attributes', 2624 billing_address: 'billing_address', 2625 currency: 'currency', 2626 customer_id: 'customer_id', 2627 discounts_amount: 'total_discount', 2628 id: 'id', 2629 line_items: 'order_item', 2630 order_number: 'order_number', 2631 shipping_address: 'shipping_address', 2632 shipping_price: 'shipping_tax', 2633 shipping_method: 'shipping_method_name', 2634 tax_price: 'total_tax', 2635 } 2636 2637 checkout = map(checkout, mapper) 2638 2639 checkout.requires_shipping = checkout.line_items.some(item => item.shipping_required) 2640 2641 checkout.line_items = checkout.line_items.map(item => mapLineItem(item)) 2642 2643 return checkout 2644 2645 } 2646 2647 const mapOrder = order => { 2648 2649 const mapper = { 2650 attributes: 'note_attributes', 2651 billing_address: 'billing_address', 2652 cancelled: 'is_cancelled', 2653 cancelled_at: 'cancelled_at', 2654 created_at: 'created_at', 2655 customer_id: 'customer_id', 2656 // discount_applications: 'discount_applications', 2657 email: 'email', 2658 financial_status: 'financial_status', 2659 fulfillment_status: 'fulfillment_status', 2660 line_items: 'order_item', 2661 note: 'note', 2662 order_number: 'order_number', 2663 phone: 'phone', 2664 shipping_address: 'shipping_address', 2665 shipping_methods: 'shipping_methods', 2666 shipping_price: 'total_shipping', 2667 subtotal_price: 'subtotal_price', 2668 // tax_lines: 'tax_lines', 2669 tax_price: 'total_tax', 2670 total_discounts: 'total_discount', 2671 total_net_amount: 'total_amount_include_transaction', 2672 total_price: 'total_price', 2673 transactions: 'transaction_records', 2674 is_manual_payment: 'is_manual_payment', 2675 } 2676 2677 order.email = order.billing_address.email 2678 order.phone = order.billing_address.phone 2679 order.shipping_method = order.shipping_method_name 2680 2681 order = map(order, mapper) 2682 2683 order.line_items = order.line_items.map(item => mapLineItem(item)) 2684 order.transactions = order.transactions.map(transaction => mapTransaction(transaction)) 2685 2686 return order 2687 2688 } 2689 2690 const mapLineItem = line_item => { 2691 2692 const old_line_item = line_item 2693 2694 const mapper = { 2695 final_price: 'price', 2696 image: 'img_url', 2697 message: 'message', 2698 original_line_price: 'original_line_price', 2699 original_price: 'original_price', 2700 properties: 'properties', 2701 quantity: 'quantity', 2702 requires_shipping: 'shipping_required', 2703 sku: 'sku', 2704 taxable: 'taxable', 2705 title: 'product_name', 2706 product_name: 'product_name', 2707 url: 'url', 2708 product_id: 'product_id', 2709 variant_id: 'variant_id', 2710 id: ['id', 'i_id'], 2711 } 2712 2713 line_item = map(line_item, mapper) 2714 2715 line_item.product_id = line_item.product_id || (old_line_item.product && old_line_item.product.id) || null 2716 line_item.variant_id = line_item.variant_id || (old_line_item.variant && old_line_item.variant.id) || null 2717 line_item.image = line_item.image || (old_line_item.image && old_line_item.image.url) || null 2718 2719 return line_item 2720 2721 } 2722 2723 const mapTransaction = transaction => { 2724 2725 const mapper = { 2726 amount: 'amount', 2727 created_at: 'created_at', 2728 gateway: 'gateway_type', 2729 id: 'id', 2730 status: 'status', 2731 } 2732 2733 transaction = map(transaction, mapper) 2734 2735 return transaction 2736 2737 } 2738 2739 2740</script>
2740 2741 2742</div> 2743 2744 2745 2746<style> 2747 #CartTemplate{ 2748 min-height: 80vh; 2749 } 2750 .cart-drawer .cart__row .small--one-whole, 2751 .cart-drawer .cart-sticky-button-wrapper{ 2752 width: 100%; 2753 } 2754 .cart-drawer .promotion__code-input .input-group{ 2755 margin-top: 20px; 2756 max-width: 100%; 2757 } 2758 .cart-drawer-wrapper{ 2759 display: flex; 2760 flex-wrap: wrap; 2761 flex-direction: row; 2762 } 2763 .cart-drawer-wrapper > div{ 2764 width: 100%; 2765 } 2766 vouchers-modal .vouchers-modal.active , 2767 vouchers-modal #vouchers-modal-backdrop.active{ 2768 z-index: 2147483647; 2769 } 2770</style> 2771 2772<div id="CartDrawer" class="cart-drawer" data-fetch="0"> 2773 2774 2775 <div class="cart-drawer-wrapper"> 2776 <div id="cart-promotion-top"></div> 2777 2778 2779 <div id="CartTemplate"> 2780 2781 2782 2783 2784 2785 <div id="noCartItem" class="cart-drawer-content"> 2786 <div class="cart-drawer-content-wrapper text-center"> 2787 <div class="section-header"> 2788 <span></span> 2789 <span class="CartDrawerTrigger icon icon-x"></span> 2790 </div> 2791 <div class="section-header__title h2">Your cart is currently empty.</div> 2792 <a class="btn btn--secondary" href="/collections/all">Continue shopping</a> 2793 </div> 2794 </div> 2795 2796 2797 2798 </div> 2799 2800 <link href="/assets/css/promotion.css?v2.94" rel="stylesheet" type="text/css" media="screen" /> 2801<div id="cart-promotion-section"></div> 2802
2803<script>var shop_money_format = "<span class=money data-ori-price='{{amount}}'>RM {{amount}} </span>";</script>
vendor: 1 bytes, line 2803
2803
2804<script src="/assets/js/promotion/promotion.js?v1.11" type="text/javascript"></script>
2804 2805
2806<script> 2807 2808 window.EasyStore = window.EasyStore || {}; 2809 window.EasyStore.Promotion = window.EasyStore.Promotion || {}; 2810 2811 var get_cart_promo_initial = false, 2812 current_template = 'customers'; 2813 2814 window.EasyStore.Promotion.updateCartPromotion = function (){ 2815 get_cart_promo_initial = true 2816 $.ajax({ 2817 type: "GET", 2818 dataType: 'json', 2819 url: "/new_cart/promotion", 2820 success: function(response){ 2821 $("#cart-promotion-section").html(response["cart/content_bottom"].trim()); 2822 $("#cart-promotion-top").html(response["cart/content_top"].trim()); 2823 2824 promoVariantDetailInitial() 2825 }, 2826 error: function(xhr){ 2827 } 2828 }); 2829 } 2830 2831 2832 if(current_template == 'cart') { 2833 document.addEventListener("DOMContentLoaded", function() { 2834 window.EasyStore.Promotion.updateCartPromotion() 2835 }); 2836 } 2837 2838</script>
vendor: 1 bytes, line 2838
2838
2839<script> 2840 document.addEventListener('DOMContentLoaded', function () { 2841 window._getVoucherErrorTranslation = Object.assign(window._getVoucherErrorTranslation || {}, { 2842 "condition_not_matched": "Voucher condition not matched", 2843 "promotion_unavailable": "This promotion is currently unavailable", 2844 "available_on": "Available on channels", 2845 "available_on_only": "Available on channels only", 2846 "available_with_locations": "Available on channels (locations only)", 2847 "pos_at_locations": "Retail Store at locations only", 2848 "channel_website": "Website", 2849 "channel_mobile": "Mobile Apps", 2850 "channel_pos": "Retail Store" 2851 }); 2852 }); 2853</script>
2853 2854 2855 </div> 2856 2857 2858 2859</div> 2860 2861<div id="toast"><div id="toastContent"></div></div> 2862<style> 2863 .cart-drawer .cart-drawer-content .cart-sticky-button-wrapper a.btn.CartDrawerTrigger{margin-bottom: 10px !important;} 2864 #toastContent a{color: #fff;text-decoration: underline;margin-top: 10px;display: block;} 2865 #toastContent .svg-icon{margin-right: 8px;margin-top: -1px;} 2866</style> 2867
2868<script type="text/javascript"> 2869 $('body').on("submit", "#CartForm", function() { 2870 $(this).find('[type=submit]').addClass('btn--loading'); 2871 }); 2872 2873 $("input[name=current_currency]").val($( "select.currency-picker" ).val()); 2874 $( "select.currency-picker" ).change(function(){ 2875 $("select.currency-picker").val($(this).val()); 2876 url=window.location.href; 2877 newParam="currency=" + $( "select.currency-picker" ).val(); 2878 if(url.indexOf("currency=")===-1){ 2879 separator = (url.indexOf("?")===-1)?"?":"&"; 2880 newUrl= url + separator + newParam; 2881 }else{ 2882 oldParam= new URL(url); 2883 oldParam = oldParam.searchParams.get("currency"); 2884 newParam= $(this).val(); 2885 newUrl=url.replace(oldParam,newParam); 2886 } 2887 $("input[name=current_currency]").val($( "select.currency-picker" ).val()); 2888 // window.location.href =newUrl; 2889 $('#CartDrawer').attr('data-fetch', 0); 2890 }); 2891 2892 $("body").on("click", ".cart__remove", function() { 2893 $('#CartTemplate').addClass('is-loading'); 2894 $.ajax({ 2895 type: 'POST', 2896 url: '/cart/remove_item_quantity', 2897 data: { 2898 variant_id: $(this).data( "variant-id"), 2899 item_id: $(this).data( "item-id"), 2900 quantity: $(this).data( "quantity"), 2901 i_id: $(this).data("i_id"), 2902 }, 2903 dataType: 'json', 2904 success: function(response){ 2905 2906 theme.cartDrawer(response); 2907 $('#CartTemplate').removeClass('is-loading'); 2908 2909 if (window.checkProductProperties !== undefined){ 2910 window.checkProductProperties(); 2911 } 2912 }, 2913 error: function(xhr){ 2914 console.log('error',xhr); 2915 $('#CartTemplate').removeClass('is-loading'); 2916 } 2917 }); 2918 2919 }); 2920 2921 2922 $('body').on("click", "#applycode",function() { 2923 2924 if($("input[name='voucher_code']").val() != '') { 2925 2926 $('#CartTemplate').addClass('is-loading'); 2927 2928 $.ajax({ 2929 type: 'POST', 2930 url: '/new_cart/voucher', 2931 data: { 2932 voucher_code: $("input[name='voucher_code']").val(), 2933 category: 'create' 2934 }, 2935 dataType: 'json', 2936 success: function(response){ 2937 2938 // console.log(response); 2939 2940 if(response.error != undefined){ 2941 2942 if(response.error.message != undefined) popToast(response.error.message); 2943 2944 $("input[name='voucher_code']").val('') 2945 2946 } 2947 2948 if(response.cart_content != undefined) theme.cartDrawer(response); 2949 2950 2951 $('#CartTemplate').removeClass('is-loading'); 2952 2953 }, 2954 error: function(xhr){ 2955 console.log('error',xhr); 2956 $('#CartTemplate').removeClass('is-loading'); 2957 } 2958 }); 2959 2960 } 2961 2962 }); 2963 2964 2965 $("body").on("click", ".remove_voucher_btn", function() { 2966 $('#CartTemplate').addClass('is-loading'); 2967 $.ajax({ 2968 type: 'DELETE', 2969 url: '/new_cart/voucher', 2970 data: { 2971 category: 'remove', 2972 order_discount_id: $(this).data( "discount-id") 2973 }, 2974 dataType: 'json', 2975 success: function(data){ 2976 // console.log(data); 2977 theme.cartDrawer(data); 2978 $('#CartTemplate').removeClass('is-loading'); 2979 }, 2980 error: function(xhr){ 2981 console.log('error',xhr); 2982 $('#CartTemplate').removeClass('is-loading'); 2983 } 2984 }); 2985 2986 }); 2987 2988 2989 theme.cartDrawer = function(data){ 2990 2991 $('#CartDrawer').attr('data-fetch', 1); 2992 $('#CartTemplate').addClass('is-loading'); 2993 2994 2995 if(typeof data.cart_content == 'string'){ 2996 $('#CartTemplate').html(data.cart_content); 2997 } 2998 2999 let cart_item_count = data.item_count || data.cart.item_count; 3000 3001 if(cart_item_count > 0){ 3002 $('.cart-count').removeClass('hidden-count'); 3003 }else{ 3004 $('.cart-count').addClass('hidden-count'); 3005 } 3006 3007 $('.cart-count').text(cart_item_count); 3008 $('#CartTemplate').removeClass('is-loading'); 3009 $(".cart-drawer-content").animate({ scrollTop: 0 }); 3010 3011 if(window.EasyStore != undefined && window.EasyStore.Promotion != undefined && window.EasyStore.Promotion.updateCartPromotion != undefined) window.EasyStore.Promotion.updateCartPromotion() 3012 3013 } 3014 3015 theme.fetchCartDrawer = function(data){ 3016 $('#CartTemplate').addClass('is-loading'); 3017 $.ajax({ 3018 url: '/new_cart?retrieve=true', 3019 type: 'GET', 3020 success: function(data, status) { 3021 // console.log(data); 3022 theme.cartDrawer(data); 3023 3024 $('#CartTemplate').removeClass('is-loading'); 3025 3026 if (window.checkProductProperties !== undefined){ 3027 window.checkProductProperties(); 3028 } 3029 }, 3030 error: function(XMLHttpRequest, textStatus) { 3031 console.log('error',XMLHttpRequest,textStatus); 3032 $('#CartTemplate').removeClass('is-loading'); 3033 } 3034 }); 3035 } 3036 3037 theme.updateCartDrawer = function(data){ 3038 $('#CartTemplate').addClass('is-loading'); 3039 3040 $.ajax({ 3041 url: '/new_cart/update', 3042 type: 'PUT', 3043 dataType: 'json', 3044 data: $('#CartDrawer form').serialize(), 3045 success: function(data, status) { 3046 theme.cartDrawer(data); 3047 3048 if (window.checkProductProperties !== undefined){ 3049 window.checkProductProperties(); 3050 } 3051 }, 3052 error: function(XMLHttpRequest, textStatus) { 3053 console.log('error',XMLHttpRequest,textStatus); 3054 } 3055 }); 3056 } 3057 3058 function debounce(func, wait, immediate) { 3059 var timeout; 3060 return function() { 3061 var context = this, args = arguments; 3062 var later = function() { 3063 timeout = null;
3064 if (!immediate) func.apply(context, args); 3065 }; 3066 var callNow = immediate && !timeout; 3067 clearTimeout(timeout); 3068 timeout = setTimeout(later, wait); 3069 if (callNow) func.apply(context, args); 3070 }; 3071 }; 3072 3073 $('body').on("change", 'input.cart__quantity-selector', function (){ 3074 theme.updateCartDrawer(); 3075 }); 3076 3077 3078 $('#updateCartDrawer').click(function() { 3079 theme.updateCartDrawer(); 3080 }); 3081 3082 $('body').on("click", ".btn-qty-adjust", function() { 3083 3084 var $button = $(this); 3085 var oldValue = $button.parent().find("input.cart__quantity-selector").val(); 3086 3087 if ($button.attr('data-adjust') == 1) { 3088 var newVal = parseFloat(oldValue) + 1; 3089 } else { 3090 // Don't allow decrementing below zero 3091 if (oldValue > 0) { 3092 var newVal = parseFloat(oldValue) - 1; 3093 } else { 3094 newVal = 0; 3095 } 3096 } 3097 3098 $button.parent().find("input").val(newVal); 3099 }); 3100 3101 $('body').on("click", ".btn-qty-adjust", debounce(function() { 3102 theme.updateCartDrawer(); 3103 },350)); 3104 3105 $('button.checkout').click(function() { 3106 $(this).addClass('btn--loading'); 3107 }); 3108 3109 var add_cart_success_html = '<svg class="svg-icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> <g> <g> <path d="M383.841,171.838c-7.881-8.31-21.02-8.676-29.343-0.775L221.987,296.732l-63.204-64.893 c-8.005-8.213-21.13-8.393-29.35-0.387c-8.213,7.998-8.386,21.137-0.388,29.35l77.492,79.561 c4.061,4.172,9.458,6.275,14.869,6.275c5.134,0,10.268-1.896,14.288-5.694l147.373-139.762 C391.383,193.294,391.735,180.155,383.841,171.838z"/> </g> </g> <g> <g> <path d="M256,0C114.84,0,0,114.84,0,256s114.84,256,256,256s256-114.84,256-256S397.16,0,256,0z M256,470.487 c-118.265,0-214.487-96.214-214.487-214.487c0-118.265,96.221-214.487,214.487-214.487c118.272,0,214.487,96.221,214.487,214.487 C470.487,374.272,374.272,470.487,256,470.487z"/> </g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> <g> </g> </svg>'; 3110 add_cart_success_html += 'Added to cart <br><a class="CartDrawerTrigger">View cart</a>'; 3111 3112 function popToast(content) { 3113 var x = document.getElementById("toast"), 3114 y = document.getElementById("toastContent"); 3115 3116 y.innerHTML = content; 3117 x.className += " show"; 3118 3119 var hideToast = setTimeout(function(){ x.className = x.className.replace(" show", ""); }, 3000); 3120 } 3121 3122</script>
3122 3123 3124<link href="/assets/css/vouchers.css?v1.2" rel="stylesheet" type="text/css" media="screen" /> 3125<link href="/assets/account/vouchers/vouchers.css" rel="stylesheet" type="text/css" media="screen" /> 3126<link href="/assets/account/vouchers/voucher-widget.css" rel="stylesheet" type="text/css" media="screen" />
3127<script src="/assets/js/promotion/vouchers.js?v1.3" type="text/javascript" ></script>
vendor: 1 bytes, line 3127
3127
3128<script src="/assets/account/vouchers/voucher-widget.js" type="text/javascript" ></script>
3128 3129 3130<vouchers-modal> 3131 <div id="vouchers-modal-backdrop" class="vouchers-modal__close"></div> 3132 <div class="vouchers-modal-wrapper page-width"> 3133 <div id="vouchers-modal" class="vouchers-modal focus-inset" aria-modal="true" role="dialog" tabindex="-1"> 3134 <div class="vouchers-modal__header"> 3135 <div class="vouchers-modal__heading">Vouchers</div> 3136 <button type="button" class="vouchers-modal__close modal__close-button link link--text focus-inset" aria-label="accessibility.close"> 3137 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" role="presentation" class="icon icon-close " fill="none" viewBox="0 0 18 17"> 3138 <path d="M.865 15.978a.5.5 0 00.707.707l7.433-7.431 7.579 7.282a.501.501 0 00.846-.37.5.5 0 00-.153-.351L9.712 8.546l7.417-7.416a.5.5 0 10-.707-.708L8.991 7.853 1.413.573a.5.5 0 10-.693.72l7.563 7.268-7.418 7.417z" fill="currentColor"> 3139 </path> 3140 </svg> 3141 </button> 3142 </div> 3143 3144 <discount-input> 3145 <div class="field"> 3146 <input type="text" id="input-discount_code" class="search__input field__input" name="voucher_code" placeholder="Discount code"> 3147 <button type="button" name="apply" class="btn btn--secondary button button--secondary">Apply</button> 3148 </div> 3149 <div class="form__message hidden" tabindex="-1" autofocus> 3150 <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-error " viewBox="0 0 13 13"> 3151 <circle cx="6.5" cy="6.50049" r="5.5" stroke="white" stroke-width="2"></circle> 3152 <circle cx="6.5" cy="6.5" r="5.5" fill="#EB001B" stroke="#EB001B" stroke-width="0.7"></circle> 3153 <path d="M5.87413 3.52832L5.97439 7.57216H7.02713L7.12739 3.52832H5.87413ZM6.50076 9.66091C6.88091 9.66091 7.18169 9.37267 7.18169 9.00504C7.18169 8.63742 6.88091 8.34917 6.50076 8.34917C6.12061 8.34917 5.81982 8.63742 5.81982 9.00504C5.81982 9.37267 6.12061 9.66091 6.50076 9.66091Z" fill="white"></path> 3154 <path d="M5.87413 3.17832H5.51535L5.52424 3.537L5.6245 7.58083L5.63296 7.92216H5.97439H7.02713H7.36856L7.37702 7.58083L7.47728 3.537L7.48617 3.17832H7.12739H5.87413ZM6.50076 10.0109C7.06121 10.0109 7.5317 9.57872 7.5317 9.00504C7.5317 8.43137 7.06121 7.99918 6.50076 7.99918C5.94031 7.99918 5.46982 8.43137 5.46982 9.00504C5.46982 9.57872 5.94031 10.0109 6.50076 10.0109Z" fill="white" stroke="#EB001B" stroke-width="0.7"></path> 3155 </svg> 3156 <div class="js-error-content"></div> 3157 </div> 3158 </discount-input> 3159 <br> 3160 3161 3162 3163 <div class="empty-vouchers_placeholder">No available vouchers</div> 3164 3165 3166 <!-- For voucher widget --> 3167
3167<script type="text/javascript"> 3168 let settings = {"logo_use_image":"1","logo_img":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/8248207.jpeg?width=350&format=webp","footer_logo_img":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/8257285.png?width=350&format=webp","nav_below_logo":"","logo_alignment":"center","heading_font_family":["'HelveticaNeue','Helvetica Neue',Helvetica,Arial,sans-serif"],"left_aligned_logo":"0","favicon_enable":"1","favicon_img":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/8318815.jpeg","header_message":"","header_search_enable":true,"topbar_sticky":true,"footer_quicklinks_enable":true,"footer_quicklinks_linklist":"footer","footer_social_enable":true,"footer_show_credit_card_logo":"1","footer_show_methods_of_payment":true,"footer_visa":"1","footer_master":"1","footer_american_express":0,"footer_jcb":0,"footer_diners_club":0,"footer_discover":0,"footer_ssl":true,"show_footer_lines":"1","home_section_1":"highlight-section","home_section_2":"featured-product","home_section_3":"img-text-section","home_section_4":"parallax-section","home_section_5":"","home_section_6":"","featured_title":"","featured_1_img":"","featured_1_text":"","featured_1_link":"","featured_2_img":"","featured_2_text":"","featured_2_link":"","featured_3_img":"","featured_3_text":"","featured_3_link":"","featured_4_img":"","featured_4_text":"","featured_4_link":"","featured_5_img":"","featured_5_text":"","featured_5_link":"","featured_6_img":"","featured_6_text":"","featured_6_link":"","featured_7_img":"","featured_7_text":"","featured_7_link":"","featured_8_img":"","featured_8_text":"","featured_8_link":"","parallax_img":"","parallax_mobile_img":"","parallax_title":"","parallax_subtitle":"","parallax_button_text":"","parallax_button_link":"","parallax_full_width":"1","slider_home_auto":"1","slider_home_show_dots":"1","slider_home_rate":"4000","slider_home_transition":"fade","slider_full_screen":"0","slide_1":"1","slide_1_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17889576.png?width=1500&format=webp","slide_1_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17889577.png?width=900&format=webp","slide_1_link":"https:\/\/linktr.ee\/StudyGroupPTTI","slide_1_alt":"","slide_1_title":"","slide_1_subtitle":"","slide_1_button_text":"Daftar sekarang","slide_2":"1","slide_2_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17808842.jpg?width=900&format=webp","slide_2_link":"https:\/\/ptti.onpay.my\/order\/form\/1104\/1033","slide_2_alt":"","slide_2_title":"","slide_2_subtitle":"","slide_2_button_text":"DAFTAR SEKARANG","slide_3":"","slide_3_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17862245.png?width=1500&format=webp","slide_3_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17862244.jpg?width=900&format=webp","slide_3_link":"https:\/\/ptti.onpay.my\/order\/form\/472\/1033","slide_3_alt":"","slide_3_title":"","slide_3_subtitle":"","slide_3_button_text":"Daftar sekarang","slide_4":"","slide_4_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17873233.png?width=1500&format=webp","slide_4_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17873235.png?width=900&format=webp","slide_4_link":"https:\/\/tinyurl.com\/batch10PTTI","slide_4_alt":"","slide_4_title":"","slide_4_subtitle":"","slide_4_button_text":"Join Channel Form 4","slide_5":"","slide_5_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17852772.png?width=1500&format=webp","slide_5_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17777593.jpg?width=900&format=webp","slide_5_link":"https:\/\/wa.link\/e0aw80","slide_5_alt":"","slide_5_title":"","slide_5_subtitle":"","slide_5_button_text":"Info lanjut","slide_6":"","slide_6_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17850552.png?width=1500&format=webp","slide_6_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17850562.png?width=900&format=webp","slide_6_link":"https:\/\/wa.me\/601133417834","slide_6_alt":"","slide_6_title":"","slide_6_subtitle":"","slide_6_button_text":"INFO LANJUT","testimonial_slide_img_crop":0,"testimonial_slide_1_img":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/15295405.png?width=1500&format=webp","testimonial_slide_
31681_title":"","testimonial_slide_1_content":"","testimonial_slide_1_text_link":"","testimonial_slide_1_link":"https:\/\/ptti.store\/otc\/?utm_source=pttimy&utm_medium=banner&utm_campaign=easystore-otc&utm_id=easystore&utm_content=easystore","testimonial_slide_2_img":"","testimonial_slide_2_title":"","testimonial_slide_2_content":"","testimonial_slide_2_text_link":"","testimonial_slide_2_link":"","testimonial_slide_3_img":"","testimonial_slide_3_title":"","testimonial_slide_3_content":"","testimonial_slide_3_text_link":"","testimonial_slide_3_link":"","testimonial_slide_4_img":"","testimonial_slide_4_title":"","testimonial_slide_4_content":"","testimonial_slide_4_text_link":"","testimonial_slide_4_link":"","testimonial_slide_5_img":"","testimonial_slide_5_title":"","testimonial_slide_5_content":"","testimonial_slide_5_text_link":"","testimonial_slide_5_link":"","testimonial_slide_6_img":"","testimonial_slide_6_title":"","testimonial_slide_6_content":"","testimonial_slide_6_text_link":"","testimonial_slide_6_link":"","logo_list_on_footer":0,"logo_list_title":"","logo_list_1_img":"","logo_list_1_link":"","logo_list_2_img":"","logo_list_2_link":"\/collections\/all","logo_list_3_img":"","logo_list_3_link":"\/collections\/all","logo_list_4_img":"","logo_list_4_link":"\/collections\/all","logo_list_5_img":"","logo_list_5_link":"\/collections\/all","logo_list_6_img":"","logo_list_6_link":"\/collections\/all","logo_list_7_img":"","logo_list_7_link":"\/collections\/all","logo_list_8_img":"","logo_list_8_link":"\/collections\/all","home_featured_products":"feature-on-homepage","home_featured_products_num":"20","home_featured_products_row_num":"7","home_featured_products_show_heading":"","home_page_content":"home","home_page_show_heading":"0","home_page_add_to_cart":true,"scroll_to_top_button":"on-right","product_quantity_enable":"1","product_image_zoom_type":"lightbox","product_thumbnails_position":"below","product_related_enable":true,"products_per_row":4,"products_list_per_row":"4","product_page_float_btn":"1","product_page_variants_tag":"1","featured_product_title":"Online Tuition Class (OTC)","product_img_res":"grande","product_img_crop":"product_img-crop ratio_1-1","collections_show_sale_circle":"1","collections_show_sold_out_circle":"1","collections_sort_enable":true,"collections_tags_enable":"0","collections_products_per_row":"3","collections_rows":"6","footer_bar":"1","footer_bar_icon_product_page":"1","footer_bar_icon_1":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/8327050.png?width=150&format=webp","footer_bar_icon_1_text":"Our Students","footer_bar_icon_1_link":"https:\/\/www.ptti.my\/pages\/better-result","footer_bar_icon_2":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/8327783.gif","footer_bar_icon_2_text":"Free Trial","footer_bar_icon_2_link":"https:\/\/www.ptti.my\/pages\/free-trial","footer_bar_icon_3":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/8327612.gif","footer_bar_icon_3_text":"Join OTC","footer_bar_icon_3_link":"https:\/\/www.ptti.my\/pages\/choose-your-level","footer_bar_icon_4":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/8335499.png?width=150&format=webp","footer_bar_icon_4_text":"Ask PTTI","footer_bar_icon_4_link":"https:\/\/www.ptti.my\/pages\/ask-ptti","cart_enable_ajax":"1","social_sharing_products":"1","social_sharing_blog":"1","social_sharing_count":"1","share_facebook":"1","share_twitter":"1","share_line":"1","share_pinterest":"1","facebook_url":"","twitter_url":"","pinterest_url":"","instagram_url":"https:\/\/instagram.com\/pttionline?utm_medium=copy_link","tumblr_url":"","youtube_url":"","vimeo_url":"","wechat_url":"","whatsapp_url":"https:\/\/WebsitePTTI.wasap.my ","line_url":"","featured_blog":"","featured_blog_title":"Blog","articles_handle_1":"","articles_handle_2":"","articles_handle_3":"","use_original_image":0,"slide_2_jpg":"https:\/\/cdn.store-assets.com\/s\/897413\/f\/17852763.png?width=1500&format=webp","promotion_uis":{"primary_color":"#E44040","header_bg_color":"#E44040","header_text_color":"#fff","recommendation":{"is_show_product_page":true,"is_show_cart_page_top":true,"is_show_cart_page_bottom":true},"voucher_widget":{"primary_color":"#4089e4"}},"show_multiple_currencies":true,"supported_currencies":"MYR ","theme_id":2877,"theme_is_edited":1,"theme_updated_at":"2026-10-08T06:36:42.000Z","phone_account_enabled":false,"line_login_enabled":false,"apple_login_enabled":false,"timezone":"Asia\/Kuala_Lumpur","is_server_side_currency_conversion":true,"is_self_registration_enabled":true,"is_highlight_enabled":false,"is_auto_gen_highlight_enabled":false,"is_common_question_enabled":false,"is_auto_gen_common_question_enabled":false,"highlight_section_title":"Highlights","common_question_section_title":"Frequently asked questions","is_new_promotion_enabled":true} 3169 if (settings.promotion_uis.voucher_widget != null) { 3170 setVoucherTheme(settings.promotion_uis.voucher_widget) 3171 } 3172 var shop = { 3173 money_prefix: "", 3174 format_decimals: "" 3175 }; 3176 var _getEntitlementTranslation = { 3177 "free_shipping": "FREE SHIPPING", 3178 "free_of_charge": "FREE GIFT", 3179 } 3180 var _getTargetTypeTranslation = { 3181 "amount_credit": " CREDIT", 3182 "amount_off": " OFF", 3183 } 3184 var _getPrerequisiteTranslation = { 3185 "min_quantity": "Min formatValue item(s) purchase", 3186 "every_quantity": "Every formatValue item(s) purchase", 3187 "min_amount": "Min formatCurrency spend", 3188 "every_amount": "Every formatCurrency spend" 3189 } 3190 var _getPrerequisiteConditionTranslation = { 3191 "selected_items": "Selected Items", 3192 "selected_collections": "Selected Collections", 3193 "storewide": "Storewide", 3194 "order_subtotal": "Order Subtotal" 3195 } 3196 var _getVoucherButtonTextTranslation = { 3197 "apply": "Apply", 3198 } 3199 var _getVoucherErrorTranslation = { 3200 "condition_not_matched": "Voucher condition not matched" 3201 } 3202 </script>
3202 3203 3204 </div> 3205 </div> 3206</vouchers-modal> 3207 3208 3209</body> 3210</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.