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/861942/f/8088793.png" /> 15 16 17 <!-- Title and description ================================================== --> 18 <title> 19 Login – Tip Top Fruits & Groceries 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://www.tiptopfruits.com.my/account/login"> 30 31 <meta property="og:image" content="https://cdn.store-assets.com/s/861942/f/8388694.png?width=350&format=webp"> 32 <meta property="og:image:secure_url" content="https://cdn.store-assets.com/s/861942/f/8388694.png?width=350&format=webp"> 33 34 35 36<meta property="og:description" content="Your premier source for fresh fruits and vegetables wholesaler and supplier deliver in Kuala Lumpur and Selangor."> 37<meta property="og:site_name" content="Tip Top Fruits & Groceries"> 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://www.tiptopfruits.com.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/861942/themes/2877/assets/timber.css?t=1787079718" rel="stylesheet" type="text/css" media="screen" /> 56 <link href="https://store-themes.easystore.co/861942/themes/2877/assets/theme.css?t=1787079718" 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/traffic.js?v=1','https://apps.easystore.co/marketplace/shopee-malaysia/script.js?shop=christiewttfg.easy.co','https://apps.easystore.co/google-analytics-4/script.js?shop=christiewttfg.easy.co&t=1719763460','https://apps.easystore.co/google-tag-manager/script.js?shop=christiewttfg.easy.co&t=1720542078'];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/861942/themes/2877/assets/respond.min.js?t=1787079718" type="text/javascript" ></script>
76 77<link href="https://store-themes.easystore.co/861942/themes/2877/assets/respond-proxy.html" id="respond-proxy" rel="respond-proxy" /> 78<link href="//www.tiptopfruits.com.my/search?q=3872116bcc37ba006840ea0601517c4e" id="respond-redirect" rel="respond-redirect" />
79<script src="//www.tiptopfruits.com.my/search?q=3872116bcc37ba006840ea0601517c4e" type="text/javascript"></script>
79 80<![endif]--> 81 82 83 84
84<script src="https://store-themes.easystore.co/861942/themes/2877/assets/modernizr.min.js?t=1787079718" 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: Shopee Malaysia --> 103<link type="text/css" rel="stylesheet" href="https://apps.easystore.co/assets/css/marketplace/main.css?v1.7"> 104<!-- /Snippet --> 105 106<!-- Snippet:global/head: Google Search Console --> 107<meta name="google-site-verification" content="uDJw81-WI_bgpsUn0pJISYdwEZDAeRcVjIk36xYHBus" /> 108<!-- /Snippet --> 109 110</head> 111 112<body id="login" class="template-customers " > 113 114 <ul id="MobileNav" class="mobile-nav"> 115 116 <li class="mobile-nav_icon-x"> 117 118 119 120 121 122 <span class="MobileNavTrigger icon icon-x"></span> 123 </li> 124 125 126 <li class="mobile-nav__link" aria-haspopup="true"> 127 128 <a href="/" > 129 HOME 130 </a> 131 132 </li> 133 134 135 <li class="mobile-nav__link" aria-haspopup="true"> 136 137 <a href="/pages/about" > 138 ABOUT US 139 </a> 140 141 </li> 142 143 144 <li class="mobile-nav__link" aria-haspopup="true"> 145 146 147 <a href="/collections/all" class="mobile-nav__parent-link"> 148 PRODUCTS 149 </a> 150 <span class="mobile-nav__sublist-trigger"> 151 <span class="icon-fallback-text mobile-nav__sublist-expand"> 152 <span class="icon icon-plus" aria-hidden="true"></span> 153 <span class="fallback-text">+</span> 154</span> 155<span class="icon-fallback-text mobile-nav__sublist-contract"> 156 <span class="icon icon-minus" aria-hidden="true"></span> 157 <span class="fallback-text">-</span> 158</span> 159 160 </span> 161 <ul class="mobile-nav__sublist"> 162 163 164 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 165 166 <a href="/collections/all-1" > 167 All 168 </a> 169 170 </li> 171 172 173 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 174 175 <a href="/collections/new" > 176 NEW 177 </a> 178 179 </li> 180 181 182 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 183 184 <a href="/collections/promotion" > 185 Promotion 186 </a> 187 188 </li> 189 190 191 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 192 193 <a href="/collections/fruits" > 194 Fruits 195 </a> 196 197 </li> 198 199 200 <li class="mobile-nav__sublist-link" aria-haspopup="true"> 201 202 <a href="/collections/vegetables" > 203 Vegetables 204 </a> 205 206 </li> 207 208 </ul> 209 210 </li> 211 212 213 <li class="mobile-nav__link" aria-haspopup="true"> 214 215 <a href="/collections/promotion" > 216 PROMOTION 217 </a> 218 219 </li> 220 221 222 <li class="mobile-nav__link" aria-haspopup="true"> 223 224 <a href="/pages/supply" > 225 SUPPLY 226 </a> 227 228 </li> 229 230 231 <li class="mobile-nav__link" aria-haspopup="true"> 232 233 <a href="/pages/delivery-area" > 234 DELIVERY AREA 235 </a> 236 237 </li> 238 239 240 <li class="mobile-nav__link" aria-haspopup="true"> 241 242 <a href="/pages/guarantee" > 243 GUARANTEE 244 </a> 245 246 </li> 247 248 249 <li class="mobile-nav__link" aria-haspopup="true"> 250 251 <a href="https://tiptopfruits.com.my/a/contact-form" > 252 CONTACT US 253 </a> 254 255 </li> 256 257 258 259 260 261 262 263 <li class="mobile-nav__link"> 264 <a href="/account/login">Log in</a> 265 </li> 266 267 <li class="mobile-nav__link"> 268 <a href="/account/register">Create account</a> 269 </li> 270 271 272 273 274 <li class="mobile-nav__link header-bar__search-wrapper"> 275 276 <div class="header-bar__module header-bar__search mobile-nav_search"> 277 278 <form action="/search" method="get" class="header-bar__search-form clearfix" role="search"> 279 280 <button type="submit" class="btn icon-fallback-text header-bar__search-submit"> 281 <span class="icon icon-search" aria-hidden="true"></span> 282 <span class="fallback-text">Search</span> 283 </button> 284 <input type="search" name="q" value="" aria-label="Search" class="header-bar__search-input" placeholder="Search" autocomplete="off"> 285 <div class="dropdown" id="searchDropdown"></div> 286 <input type="hidden" name="search_history" id="search_history"> 287 </form> 288 289 290 291
292<script> 293 var _search_history_listings = "" 294 if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings)); 295 296 function clearAll() { 297 localStorage.removeItem('searchHistory'); 298 299 var customer = ""; 300 if(customer) { 301 // Your logic to clear all data or call an endpoint 302 fetch('/account/search_histories', { 303 method: 'DELETE', 304 headers: { 305 "Content-Type": "application/json", 306 "X-Requested-With": "XMLHttpRequest" 307 }, 308 body: JSON.stringify({ 309 _token: "TNYibZpXzUp6Eo3mau1Sbxad4gLDzXZSpgvdPVE9" 310 }), 311 }) 312 .then(response => response.json()) 313 } 314 } 315 // End - store view history in local storage 316 317 // search history dropdown 318 var searchInputs = document.querySelectorAll('input[type=search]'); 319 320 if(searchInputs.length > 0) { 321 322 searchInputs.forEach((searchInput)=>{ 323 324 searchInput.addEventListener('focus', function() { 325 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 326 searchDropdown.innerHTML = ''; // Clear existing items 327 328 // retrieve data from local storage 329 var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || []; 330 331 // Convert JSON to string 332 var search_history_json = JSON.stringify(searchHistoryData); 333 334 // Set the value of the hidden input 335 searchInput.closest('form').querySelector("#search_history").value = search_history_json; 336 337 // create dropdown items 338 var clearAllItem = document.createElement('div'); 339 clearAllItem.className = 'dropdown-item clear-all'; 340 clearAllItem.textContent = 'Clear'; 341 clearAllItem.addEventListener('click', function() { 342 clearAll(); 343 searchDropdown.style.display = 'none'; 344 searchInput.classList.remove('is-focus'); 345 }); 346 searchDropdown.appendChild(clearAllItem); 347 348 // create dropdown items 349 searchHistoryData.forEach(function(item) { 350 var dropdownItem = document.createElement('div'); 351 dropdownItem.className = 'dropdown-item'; 352 dropdownItem.textContent = item.term; 353 dropdownItem.addEventListener('click', function() { 354 searchInput.value = item.term; 355 searchDropdown.style.display = 'none'; 356 }); 357 searchDropdown.appendChild(dropdownItem); 358 }); 359 360 if(searchHistoryData.length > 0){ 361 // display the dropdown 362 searchInput.classList.add('is-focus'); 363 document.body.classList.add('search-input-focus'); 364 searchDropdown.style.display = 'block'; 365 } 366 }); 367 368 searchInput.addEventListener("focusout", (event) => { 369 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 370 searchInput.classList.remove('is-focus'); 371 searchDropdown.classList.add('transparent'); 372 setTimeout(()=>{ 373 searchDropdown.style.display = 'none'; 374 searchDropdown.classList.remove('transparent'); 375 document.body.classList.remove('search-input-focus'); 376 }, 400); 377 }); 378 }) 379 } 380 // End - search history dropdown 381</script>
381 382 </div> 383 384 </li> 385 386 387</ul> 388<div id="MobileNavOutside" class="mobile-nav-outside"></div> 389 390 391<div id="PageContainer" class="page-container"> 392 393<!-- Snippet:global/body_start: Announcement Bar --> 394<link rel="stylesheet" href="https://apps.easystore.co/assets/css/annoucement-bar/slider.css?v1.01"> 395 396<input type="hidden" id="total_announcement_left" name="total_announcement_left" value="1"> 397<input type="hidden" id="locale" name="locale" value="en_US"> 398 399<slider-announcement-bar-app id="announcement-bar" name="announcement-bar" style=" 400 border: unset; 401 padding: 4px 0px; 402 margin: 0px; 403 z-index:2999; 404 background:rgba(177, 162, 0, 0.88); 405 color:rgb(255, 255, 255); 406 position: -webkit-sticky; position: sticky; top: 0; 407"> 408 409 <div style=" 410 display: flex; 411 justify-content: space-between; 412 align-items: center; 413 padding: 0px 0px; 414 border-top: 0px; 415 border-bottom: 0px; 416 border-color: transparent; 417 "> 418 <div style="height: 24px;"> 419 </div> 420 421 <ul style="flex-grow: 2; margin: 0px;"> 422 <li id="announcement_bar_0" style=" 423 display: flex; 424 justify-content: center; 425 align-items: center; 426 flex-wrap: wrap; 427 margin: 0px; 428 width: 100%; 429 word-wrap: break-word; 430 "> 431 Wholesale Fresh Fruits & Vegetables Supplier in KL and Selangor. 432 <a class="announcement-bar-button" href="https://wa.me/60183833772?text=Hello,%20I%20want%20to%20get%20quotation%20of" style="color: rgb(255, 255, 255); background: rgba(136, 126, 0, 0.88);">GET QUOTE NOW</a> 433 <input type="hidden" id="expired_at_0" name="expired_at_0" value="2025-01-26 00:00"> 434 </li> 435 </ul> 436 437 <div style="display: flex;"> 438 </div> 439 </div> 440 441 442</slider-announcement-bar-app> 443
444<script> 445 $(function() { 446 var is_top_enabled = 1; 447 448 const loadScript = function(url, callback) { 449 const script = document.createElement("script"); 450 script.type = "text/javascript"; 451 // If the browser is Internet Explorer. 452 if (script.readyState) { 453 script.onreadystatechange = function() { 454 if (script.readyState == "loaded" || script.readyState == "complete") { 455 script.onreadystatechange = null; 456 callback(); 457 } 458 }; 459 // For any other browser. 460 } else { 461 script.onload = function() { 462 callback(); 463 }; 464 } 465 script.src = url; 466 document.getElementsByTagName("head")[0].appendChild(script); 467 }; 468 469 const announcementBarAppJS = function($) { 470 471 $('#announcement-close-button').on('click', function() { 472 $('#announcement-bar, #announcement-bar-top').hide(); 473 $('#easystore-section-header, .sticky-topbar').css('top', ''); 474 }); 475 } 476 477 if (typeof jQuery === 'undefined') { 478 loadScript('//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js', function() { 479 jQuery = jQuery.noConflict(true); 480 announcementBarAppJS(jQuery); 481 }); 482 } else { 483 announcementBarAppJS(jQuery); 484 } 485 486 487 488 if(is_top_enabled){ 489 // Prevent announcement bar block header 490 setTimeout(()=>{ 491 $('#easystore-section-header, .sticky-topbar').css('top', $('#announcement-bar').height()+'px'); 492 }, 2000); 493 } 494 }); 495 496 setInterval(function() { 497 const total_announcement = "1" 498 var total_announcement_left = $("#total_announcement_left").val(); 499 500 for (let i = 0; i <= total_announcement; i++) { 501 const startDate = new Date(); 502 const endDateStr = $("#expired_at_" + i).val(); 503 const endDate = endDateStr == undefined ? new Date() : new Date(endDateStr.replace(/-/g, "/")); 504 const seconds = (endDate.getTime() - startDate.getTime()) / 1000; 505 506 const days = parseInt(seconds / 86400); 507 const hours = parseInt((seconds % 86400) / 3600); 508 const mins = parseInt((seconds % 86400 % 3600) / 60); 509 const secs = parseInt((seconds % 86400 % 3600) % 60); 510 511 // use to translate countdown unit 512 // (translate based on the preferred language when save announcement bar setting) 513 String.prototype.translate = function() { 514 try { 515 if ($("#locale").val() == "zh_TW") { 516 if (this.toString() === 'day') { 517 return "天"; 518 } 519 if (this.toString() === 'hour') { 520 return "å°æ"; 521 } 522 if (this.toString() === 'min') { 523 return "åé"; 524 } 525 if (this.toString() === 'sec') { 526 return "ç§"; 527 } 528 } else { 529 if (this.toString() === 'day') { 530 if (days > 0) { 531 return "Days"; 532 } else { 533 return "Day"; 534 } 535 } else if (this.toString() === 'hour') { 536 if (hours > 0) { 537 return "Hours"; 538 } else { 539 return "Hour"; 540 } 541 } else if (this.toString() === 'min') { 542 if (mins > 0) { 543 return "Mins"; 544 } else { 545 return "Min"; 546 } 547 } else if (this.toString() === 'sec') { 548 if (secs > 0) { 549 return "Secs"; 550 } else { 551 return "Sec"; 552 } 553 } 554 } 555 } catch (error) { 556 console.log("Some errors heres", error); 557 } 558 }; 559 560 const announcementBar_countdown = document.getElementById("announcementBar_countdown_" + i); 561 if (announcementBar_countdown && seconds > 0) { 562 563 $(announcementBar_countdown).show() 564 announcementBar_countdown.innerHTML = ` 565 <div> 566 ${days} <small>${'day'.translate()}</small> 567 </div> 568 <div> 569 ${hours} <small>${'hour'.translate()}</small> 570 </div> 571 <div> 572 ${mins} <small>${'min'.translate()}</small> 573 </div> 574 <div> 575 ${secs} <small>${'sec'.translate()}</small> 576 </div> 577 `; 578 579 580 } else if (announcementBar_countdown && seconds <= 0) { 581 $("#announcement_bar_" + i).remove(); 582 total_announcement_left = total_announcement_left - 1; 583 $("#total_announcement_left").val(total_announcement_left); 584 } 585 } 586 587 showOrHide(total_announcement_left); 588 }, 1000); 589 590 591 function showOrHide(total_announcement_left) { 592 if (total_announcement_left <= 1) { 593 $("#previous-announcement-bar-button,#next-announcement-bar-button").hide(); 594 } else { 595 $("#previous-announcement-bar-button,#next-announcement-bar-button").show(); 596 } 597 598 if (total_announcement_left == 0) { 599 $("#announcement-close-button").hide(); 600 $("#announcement-bar").hide(); 601 $('#announcement-bar-top').hide(); 602 $('#easystore-section-header, .sticky-topbar').css('top', ''); 603 } 604 }; 605 606 let annoucementBarAutoMoveInterval = ''; 607 class AnnouncementBarAppSlider extends HTMLElement { 608 constructor() { 609 super(); 610 this.slider = this.querySelector('ul'); 611 this.sliderItems = this.querySelectorAll('li'); 612 this.prevButton = this.querySelector('a[name="previous"]'); 613 this.nextButton = this.querySelector('a[name="next"]'); 614 615 if (!this.slider || !this.nextButton) return; 616 617 const resizeObserver = new ResizeObserver(entries => this.initPages()); 618 resizeObserver.observe(this.slider); 619 620 this.slider.addEventListener('scroll', this.update.bind(this)); 621 this.prevButton.addEventListener('click', this.onButtonClick.bind(this)); 622 this.nextButton.addEventListener('click', this.onButtonClick.bind(this)); 623 624 625 } 626 627 initPages() { 628 const sliderItemsToShow = Array.from(this.sliderItems).filter(element => element.clientWidth > 0); 629 this.sliderLastItem = sliderItemsToShow[sliderItemsToShow.length - 1]; 630 if (sliderItemsToShow.length === 0) return; 631 this.slidesPerPage = Math.floor(this.slider.clientWidth / sliderItemsToShow[0].clientWidth); 632 this.totalPages = sliderItemsToShow.length - this.slidesPerPage + 1; 633 this.update(); 634 let self = this 635 var total_announcement_left = $("#total_announcement_left").val(); 636 annoucementBarAutoMoveInterval = setInterval(function() { 637 if (total_announcement_left > 1) { 638 self.moveSlide('next') 639 } 640 }, 5000) 641 } 642 643 update() { 644 this.currentPage = Math.round(this.slider.scrollLeft / this.sliderLastItem.clientWidth) + 1; 645 } 646 647 onButtonClick(event) { 648 event.preventDefault(); 649 let self = this; 650 self.moveSlide(event.currentTarget.name); 651 } 652 653 654 moveSlide(move_to) { 655 656 clearInterval(annoucementBarAutoMoveInterval); 657 let self = this; 658 annoucementBarAutoMoveInterval = setInterval(function() { 659 self.moveSlide('next'); 660 }, 5000) 661 662 if (move_to === 'previous' && this.currentPage === 1) { 663 this.slider.scrollTo({ 664 left: this.sliderLastItem.clientWidth * (this.totalPages - 1) 665 }); 666 } else if (move_to === 'next' && this.currentPage === this.totalPages) { 667 this.slider.scrollTo({ 668 left: 0 669 }); 670 } else { 671 const slideScrollPosition = move_to === 'next' ? this.slider.scrollLeft + this.sliderLastItem 672 .clientWidth : this.slider.scrollLeft - this.sliderLastItem.clientWidth; 673 this.slider.scrollTo({ 674 left: slideScrollPosition 675 }); 676 } 677 } 678 679 } 680 681 customElements.define('slider-announcement-bar-app', AnnouncementBarAppSlider); 682</script>
682 683 684<!-- /Snippet --> 685 686<!-- Snippet:global/body_start: Console Extension --> 687<div id='es_console' style='display: none;'>861942</div> 688<!-- /Snippet --> 689 690 691 <style> 692 .search-modal__form{ 693 position: relative; 694 } 695 696 .dropdown-wrapper { 697 position: relative; 698 } 699 700 .dropdown-wrapper:hover .dropdown { 701 display: block; 702 } 703 704 .header-icon-nav .dropdown { 705 left: -80px; 706 } 707 708 .dropdown { 709 display: none; 710 position: absolute; 711 top: 100%; 712 left: 0px; 713 width: 100%; 714 padding: 8px; 715 background-color: #fff; 716 z-index: 1000; 717 border-radius: 5px; 718 border: 1px solid rgba(var(--color-foreground), 1); 719 border-top: none; 720 overflow-x: hidden; 721 overflow-y: auto; 722 max-height: 350px; 723 min-width: 150px; 724 box-shadow: 0 0 5px rgba(0,0,0,0.1); 725 } 726 727 .dropdown a{ 728 text-decoration: none; 729 color: #000 !important; 730 } 731 732 .dropdown-item { 733 padding: 0.4rem 2rem; 734 cursor: pointer; 735 line-height: 1.4; 736 overflow: hidden; 737 text-overflow: ellipsis; 738 white-space: nowrap; 739 } 740 741 .dropdown-item:hover{ 742 background-color: #f3f3f3; 743 } 744 745 .search__input.is-focus{ 746 border-radius: 15px; 747 border-bottom-left-radius: 0; 748 border-bottom-right-radius: 0; 749 border: 1px solid rgba(var(--color-foreground), 1); 750 border-bottom: none; 751 box-shadow: none; 752 } 753 754 .clear-all { 755 text-align: right; 756 padding: 0 2rem 0.2rem; 757 line-height: 1; 758 font-size: 70%; 759 margin-bottom: -2px; 760 } 761 762 .clear-all:hover{ 763 background-color: #fff; 764 } 765 766 .referral-notification { 767 position: absolute; 768 top: 100%; 769 right: -12px; 770 background: white; 771 border: 1px solid #e0e0e0; 772 border-radius: 8px; 773 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); 774 width: 280px; 775 z-index: 1000; 776 padding: 16px; 777 margin-top: 8px; 778 font-size: 14px; 779 line-height: 1.4; 780 } 781 782 .referral-notification::before { 783 content: ''; 784 position: absolute; 785 top: -8px; 786 right: 20px; 787 width: 0; 788 height: 0; 789 border-left: 8px solid transparent; 790 border-right: 8px solid transparent; 791 border-bottom: 8px solid white; 792 } 793 794 .referral-notification::after { 795 content: ''; 796 position: absolute; 797 top: -9px; 798 right: 20px; 799 width: 0; 800 height: 0; 801 border-left: 8px solid transparent; 802 border-right: 8px solid transparent; 803 border-bottom: 8px solid #e0e0e0; 804 } 805 806 .referral-notification h4 { 807 margin: 0 0 8px 0; 808 color: #2196F3; 809 font-size: 16px; 810 font-weight: 600; 811 } 812 813 .referral-notification p { 814 margin: 0 0 12px 0; 815 color: #666; 816 } 817 818 .referral-notification .referral-code { 819 background: #f5f5f5; 820 padding: 8px; 821 border-radius: 4px; 822 font-family: monospace; 823 font-size: 13px; 824 text-align: center; 825 margin: 8px 0; 826 border: 1px solid #ddd; 827 } 828 829 .referral-notification .close-btn { 830 position: absolute; 831 top: 8px; 832 right: 8px; 833 background: none; 834 border: none; 835 font-size: 18px; 836 color: #999; 837 cursor: pointer; 838 padding: 0; 839 width: 20px; 840 height: 20px; 841 line-height: 1; 842 } 843 844 .referral-notification .close-btn:hover { 845 color: #333; 846 } 847 848 .referral-notification .action-btn { 849 background: #2196F3; 850 color: white; 851 border: none; 852 padding: 8px 16px; 853 border-radius: 4px; 854 cursor: pointer; 855 font-size: 12px; 856 margin-right: 8px; 857 margin-top: 8px; 858 } 859 860 .referral-notification .action-btn:hover { 861 background: #1976D2; 862 } 863 864 .referral-notification .dismiss-btn { 865 background: transparent; 866 color: #666; 867 border: 1px solid #ddd; 868 padding: 8px 16px; 869 border-radius: 4px; 870 cursor: pointer; 871 font-size: 12px; 872 margin-top: 8px; 873 } 874 875 .referral-notification .dismiss-btn:hover { 876 background: #f5f5f5; 877 } 878 .referral-modal__dialog { 879 transform: translate(-50%, 0); 880 transition: transform var(--duration-default) ease, visibility 0s; 881 z-index: 10000; 882 position: fixed; 883 top: 20vh; 884 left: 50%; 885 width: 100%; 886 max-width: 350px; 887 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); 888 border-radius: 12px; 889 background-color: #fff; 890 color: #000; 891 padding: 20px; 892 text-align: center; 893 } 894 .modal-overlay.referral-modal-overlay { 895 position: fixed; 896 top: 0; 897 left: 0; 898 width: 100%; 899 height: 100%; 900 background-color: rgba(0, 0, 0, 0.7); 901 z-index: 2001; 902 display: block; 903 opacity: 1; 904 transition: opacity var(--duration-default) ease, visibility 0s; 905 } 906</style> 907 908<header class="header-bar sticky-topbar"> 909 <div class="header-bg-wrapper"> 910 <div class="header-wrapper wrapper"> 911 912 913<div class="logo-header" role="banner"> 914 915 <div class="h1 site-header__logo" itemscope itemtype="http://schema.org/Organization"> 916 917 918 <a href="/" class="logo-wrapper" itemprop="url"> 919 <img src="https://cdn.store-assets.com/s/861942/f/8388694.png?width=350&format=webp" alt="Tip Top Fruits & Groceries" itemprop="logo"> 920 </a> 921 922 923 </div> 924 925</div> 926 927 <div class="header-nav-bar medium-down--hide"> 928 929<ul class="site-nav large--text-center" id="AccessibleNav"> 930 931 932 933 <li > 934 <a href="/" class="site-nav__link">HOME</a> 935 </li> 936 937 938 939 940 <li > 941 <a href="/pages/about" class="site-nav__link">ABOUT US</a> 942 </li> 943 944 945 946 947 948 <li class="site-nav--has-dropdown" aria-haspopup="true"> 949 <a href="/collections/all" class="site-nav__link"> 950 PRODUCTS
951 <span class="arrow-icon"> 952 <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> 953 </span> 954 </a> 955 <ul class="site-nav__dropdown"> 956 957 958 959 <li > 960 <a href="/collections/all-1" class="site-nav__link">All</a> 961 </li> 962 963 964 965 966 <li > 967 <a href="/collections/new" class="site-nav__link">NEW</a> 968 </li> 969 970 971 972 973 <li > 974 <a href="/collections/promotion" class="site-nav__link">Promotion</a> 975 </li> 976 977 978 979 980 <li > 981 <a href="/collections/fruits" class="site-nav__link">Fruits</a> 982 </li> 983 984 985 986 987 <li > 988 <a href="/collections/vegetables" class="site-nav__link">Vegetables</a> 989 </li> 990 991 992 </ul> 993 </li> 994 995 996 997 998 <li > 999 <a href="/collections/promotion" class="site-nav__link">PROMOTION</a> 1000 </li> 1001 1002 1003 1004 1005 <li > 1006 <a href="/pages/supply" class="site-nav__link">SUPPLY</a> 1007 </li> 1008 1009 1010 1011 1012 <li > 1013 <a href="/pages/delivery-area" class="site-nav__link">DELIVERY AREA</a> 1014 </li> 1015 1016 1017 1018 1019 <li > 1020 <a href="/pages/guarantee" class="site-nav__link">GUARANTEE</a> 1021 </li> 1022 1023 1024 1025 1026 <li > 1027 <a href="https://tiptopfruits.com.my/a/contact-form" class="site-nav__link">CONTACT US</a> 1028 </li> 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043</ul> 1044 1045 </div> 1046 1047 <div class="desktop-header-nav medium-down--hide"> 1048 1049 1050 <div class="header-subnav"> 1051 1052 1053 1054 1055 1056 <div class="header-icon-nav"> 1057 1058 1059 1060 1061 1062 1063 1064 1065 <div class="header-bar__module"> 1066 1067 <a class="popup-with-form" href="#search-form"> 1068 1069 1070 1071 1072 <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> 1073 1074 1075 1076 </a> 1077 1078 1079 1080<!-- form itself --> 1081<div id="search-form" class="white-popup-block mfp-hide popup-search"> 1082 <div class="popup-search-content"> 1083 <form action="/search" method="get" class="input-group search-bar" role="search"> 1084 1085 <input type="search" name="q" value="" placeholder="Search" class="input-group-field" aria-label="Search" placeholder="Search" autocomplete="off"> 1086 <div class="dropdown" id="searchDropdown"></div> 1087 <input type="hidden" name="search_history" id="search_history"> 1088 <span class="input-group-btn"> 1089 <button type="submit" class="btn icon-fallback-text"> 1090 <span class="icon icon-search" aria-hidden="true"></span> 1091 <span class="fallback-text">Search</span> 1092 </button> 1093 </span> 1094 </form> 1095 </div> 1096</div> 1097
1098<script src="https://store-themes.easystore.co/861942/themes/2877/assets/magnific-popup.min.js?t=1787079718" type="text/javascript" ></script>
vendor: 1 bytes, line 1098
1098
1099<script> 1100$(document).ready(function() { 1101 $('.popup-with-form').magnificPopup({ 1102 type: 'inline', 1103 preloader: false, 1104 focus: '#name', 1105 mainClass: 'popup-search-bg-wrapper', 1106 1107 // When elemened is focused, some mobile browsers in some cases zoom in 1108 // It looks not nice, so we disable it: 1109 callbacks: { 1110 beforeOpen: function() { 1111 if($(window).width() < 700) { 1112 this.st.focus = false; 1113 } else { 1114 this.st.focus = '#name'; 1115 } 1116 } 1117 } 1118 }); 1119 $('.popup-search-content').click(function(event) { 1120 if($(event.target).attr('class') == "popup-search-content") { 1121 $.magnificPopup.close(); 1122 } 1123 }); 1124}); 1125</script>
1125 1126 1127
1128<script> 1129 var _search_history_listings = "" 1130 if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings)); 1131 1132 function clearAll() { 1133 localStorage.removeItem('searchHistory'); 1134 1135 var customer = ""; 1136 if(customer) { 1137 // Your logic to clear all data or call an endpoint 1138 fetch('/account/search_histories', { 1139 method: 'DELETE', 1140 headers: { 1141 "Content-Type": "application/json", 1142 "X-Requested-With": "XMLHttpRequest" 1143 }, 1144 body: JSON.stringify({ 1145 _token: "TNYibZpXzUp6Eo3mau1Sbxad4gLDzXZSpgvdPVE9" 1146 }), 1147 }) 1148 .then(response => response.json()) 1149 } 1150 } 1151 // End - store view history in local storage 1152 1153 // search history dropdown 1154 var searchInputs = document.querySelectorAll('input[type=search]'); 1155 1156 if(searchInputs.length > 0) { 1157 1158 searchInputs.forEach((searchInput)=>{ 1159 1160 searchInput.addEventListener('focus', function() { 1161 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 1162 searchDropdown.innerHTML = ''; // Clear existing items 1163 1164 // retrieve data from local storage 1165 var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || []; 1166 1167 // Convert JSON to string 1168 var search_history_json = JSON.stringify(searchHistoryData); 1169 1170 // Set the value of the hidden input 1171 searchInput.closest('form').querySelector("#search_history").value = search_history_json; 1172 1173 // create dropdown items 1174 var clearAllItem = document.createElement('div'); 1175 clearAllItem.className = 'dropdown-item clear-all'; 1176 clearAllItem.textContent = 'Clear'; 1177 clearAllItem.addEventListener('click', function() { 1178 clearAll(); 1179 searchDropdown.style.display = 'none'; 1180 searchInput.classList.remove('is-focus'); 1181 }); 1182 searchDropdown.appendChild(clearAllItem); 1183 1184 // create dropdown items 1185 searchHistoryData.forEach(function(item) { 1186 var dropdownItem = document.createElement('div'); 1187 dropdownItem.className = 'dropdown-item'; 1188 dropdownItem.textContent = item.term; 1189 dropdownItem.addEventListener('click', function() { 1190 searchInput.value = item.term; 1191 searchDropdown.style.display = 'none'; 1192 }); 1193 searchDropdown.appendChild(dropdownItem); 1194 }); 1195 1196 if(searchHistoryData.length > 0){ 1197 // display the dropdown 1198 searchInput.classList.add('is-focus'); 1199 document.body.classList.add('search-input-focus'); 1200 searchDropdown.style.display = 'block'; 1201 } 1202 }); 1203 1204 searchInput.addEventListener("focusout", (event) => { 1205 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 1206 searchInput.classList.remove('is-focus'); 1207 searchDropdown.classList.add('transparent'); 1208 setTimeout(()=>{ 1209 searchDropdown.style.display = 'none'; 1210 searchDropdown.classList.remove('transparent'); 1211 document.body.classList.remove('search-input-focus'); 1212 }, 400); 1213 }); 1214 }) 1215 } 1216 // End - search history dropdown 1217</script>
1217 1218 </div> 1219 1220 1221 1222 1223 1224 1225 1226 <div class="header-bar__module dropdown-wrapper"> 1227 1228 <a href="/account/login"> 1229 1230 1231 1232 <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> 1233 1234 1235</a> 1236 1237 <!-- Referral Notification Popup for Desktop --> 1238 <div id="referralNotification" class="referral-notification" style="display: none;"> 1239 <button class="close-btn" onclick="dismissReferralNotification()">×</button> 1240 <div style="text-align: center; margin-bottom: 16px;"> 1241 <div style="width: 100px; height: 100px; margin: 0 auto;"> 1242 <img src="https://resources.easystore.co/storefront/icons/channels/vector_referral_program.svg"> 1243 </div> 1244 </div> 1245 <p id="referralSignupMessage" style="text-align: center; font-size: 14px; color: #666; margin: 0 0 20px 0;"> 1246 Your friend gifted you credit! Sign up now to redeem. 1247 </p> 1248 <div style="text-align: center;"> 1249 <button class="btn" onclick="goToSignupPage()" style="width: 100%; color: #fff;"> 1250 Sign Up 1251 </button> 1252 </div> 1253 </div> 1254 1255 </div> 1256 1257 1258 1259 1260 </div> 1261 </div> 1262 1263 1264 1265 </div> 1266 1267 <div class="mobile-header-icons large--hide"> 1268 1269 <div class="large--hide"> 1270 1271 <a class="popup-with-form" href="#search-form"> 1272 1273 1274 1275 1276 <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> 1277 1278 1279 1280 </a> 1281 1282 1283 1284<!-- form itself --> 1285<div id="search-form" class="white-popup-block mfp-hide popup-search"> 1286 <div class="popup-search-content"> 1287 <form action="/search" method="get" class="input-group search-bar" role="search"> 1288 1289 <input type="search" name="q" value="" placeholder="Search" class="input-group-field" aria-label="Search" placeholder="Search" autocomplete="off"> 1290 <div class="dropdown" id="searchDropdown"></div> 1291 <input type="hidden" name="search_history" id="search_history"> 1292 <span class="input-group-btn"> 1293 <button type="submit" class="btn icon-fallback-text"> 1294 <span class="icon icon-search" aria-hidden="true"></span> 1295 <span class="fallback-text">Search</span> 1296 </button> 1297 </span> 1298 </form> 1299 </div> 1300</div> 1301
1302<script src="https://store-themes.easystore.co/861942/themes/2877/assets/magnific-popup.min.js?t=1787079718" type="text/javascript" ></script>
vendor: 1 bytes, line 1302
1302
1303<script> 1304$(document).ready(function() { 1305 $('.popup-with-form').magnificPopup({ 1306 type: 'inline', 1307 preloader: false, 1308 focus: '#name', 1309 mainClass: 'popup-search-bg-wrapper', 1310 1311 // When elemened is focused, some mobile browsers in some cases zoom in 1312 // It looks not nice, so we disable it: 1313 callbacks: { 1314 beforeOpen: function() { 1315 if($(window).width() < 700) { 1316 this.st.focus = false; 1317 } else { 1318 this.st.focus = '#name'; 1319 } 1320 } 1321 } 1322 }); 1323 $('.popup-search-content').click(function(event) { 1324 if($(event.target).attr('class') == "popup-search-content") { 1325 $.magnificPopup.close(); 1326 } 1327 }); 1328}); 1329</script>
1329 1330 1331
1332<script> 1333 var _search_history_listings = "" 1334 if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings)); 1335 1336 function clearAll() { 1337 localStorage.removeItem('searchHistory'); 1338 1339 var customer = ""; 1340 if(customer) { 1341 // Your logic to clear all data or call an endpoint 1342 fetch('/account/search_histories', { 1343 method: 'DELETE', 1344 headers: { 1345 "Content-Type": "application/json", 1346 "X-Requested-With": "XMLHttpRequest" 1347 }, 1348 body: JSON.stringify({ 1349 _token: "TNYibZpXzUp6Eo3mau1Sbxad4gLDzXZSpgvdPVE9" 1350 }), 1351 }) 1352 .then(response => response.json()) 1353 } 1354 } 1355 // End - store view history in local storage 1356 1357 // search history dropdown 1358 var searchInputs = document.querySelectorAll('input[type=search]'); 1359 1360 if(searchInputs.length > 0) { 1361 1362 searchInputs.forEach((searchInput)=>{ 1363 1364 searchInput.addEventListener('focus', function() { 1365 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 1366 searchDropdown.innerHTML = ''; // Clear existing items 1367 1368 // retrieve data from local storage 1369 var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || []; 1370 1371 // Convert JSON to string 1372 var search_history_json = JSON.stringify(searchHistoryData); 1373 1374 // Set the value of the hidden input 1375 searchInput.closest('form').querySelector("#search_history").value = search_history_json; 1376 1377 // create dropdown items 1378 var clearAllItem = document.createElement('div'); 1379 clearAllItem.className = 'dropdown-item clear-all'; 1380 clearAllItem.textContent = 'Clear'; 1381 clearAllItem.addEventListener('click', function() { 1382 clearAll(); 1383 searchDropdown.style.display = 'none'; 1384 searchInput.classList.remove('is-focus'); 1385 }); 1386 searchDropdown.appendChild(clearAllItem); 1387 1388 // create dropdown items 1389 searchHistoryData.forEach(function(item) { 1390 var dropdownItem = document.createElement('div'); 1391 dropdownItem.className = 'dropdown-item'; 1392 dropdownItem.textContent = item.term; 1393 dropdownItem.addEventListener('click', function() { 1394 searchInput.value = item.term; 1395 searchDropdown.style.display = 'none'; 1396 }); 1397 searchDropdown.appendChild(dropdownItem); 1398 }); 1399 1400 if(searchHistoryData.length > 0){ 1401 // display the dropdown 1402 searchInput.classList.add('is-focus'); 1403 document.body.classList.add('search-input-focus'); 1404 searchDropdown.style.display = 'block'; 1405 } 1406 }); 1407 1408 searchInput.addEventListener("focusout", (event) => { 1409 var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown'); 1410 searchInput.classList.remove('is-focus'); 1411 searchDropdown.classList.add('transparent'); 1412 setTimeout(()=>{ 1413 searchDropdown.style.display = 'none'; 1414 searchDropdown.classList.remove('transparent'); 1415 document.body.classList.remove('search-input-focus'); 1416 }, 400); 1417 }); 1418 }) 1419 } 1420 // End - search history dropdown 1421</script>
1421 1422 </div> 1423 1424 1425 1426 1427 <!-- Mobile hamburger --> 1428 <div class="large--hide"> 1429 <a class="mobile-nav-trigger MobileNavTrigger"> 1430 1431 1432 1433 1434 <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> 1435 1436 1437 1438 </a> 1439 </div> 1440 1441 1442 1443 <!-- Referral Notification Modal for Mobile --> 1444 <details-modal class="referral-modal" id="referralMobileModal"> 1445 <details> 1446 <summary class="referral-modal__toggle" aria-haspopup="dialog" aria-label="Open referral modal" style="display: none;"> 1447 </summary> 1448 <div class="modal-overlay referral-modal-overlay"></div> 1449 <div class="referral-modal__dialog" role="dialog" aria-modal="true" aria-label="Referral notification"> 1450 <div class="referral-modal__content"> 1451 <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;"> 1452 × 1453 </button> 1454 1455 <div style="margin-bottom: 24px;"> 1456 <div style="width: 120px; height: 120px; margin: 0 auto 20px;"> 1457 <img src="https://resources.easystore.co/storefront/icons/channels/vector_referral_program.svg" style="width: 100%; height: 100%;"> 1458 </div> 1459 </div> 1460 1461 <p id="referralSignupMessageMobile" style="font-size: 16px; color: #333; margin: 0 0 30px 0; line-height: 1.5;"> 1462 Your friend gifted you credit! Sign up now to redeem. 1463 </p> 1464 1465 <button type="button" class="btn" onclick="goToSignupPageFromMobile()" style="width: 100%; color: #fff;"> 1466 Sign Up 1467 </button> 1468 </div> 1469 </div> 1470 </details> 1471 </details-modal> 1472 1473 1474 1475 </div> 1476 1477 1478 </div> 1479 </div> 1480</header> 1481 1482 1483 1484 1485 1486 1487 1488 <main class="wrapper main-content" role="main"> 1489 <div class="grid"> 1490 <div class="grid__item">
vendor: 100 bytes, lines 1490-1494
1490 1491 1492 1493 1494<script src="https://www.recaptcha.net/recaptcha/enterprise.js?render=
14946LdMNdIqAAAAALegJp7y4weVcCIlnwmIN8TWseEF
vendor: 12 bytes, line 1494
1494"></script>
1495<link rel="preload" href="https://store-themes.easystore.co/861942/themes/2877/assets/customer.css?t=1787079718" as="style" onload="this.onload=null;this.rel='stylesheet'"> 1496<style> 1497 main.main-content .field > label{ 1498 display: none; 1499 } 1500 .h3{ 1501 font-size: 18px; 1502 } 1503 .button--full-width{ 1504 width: 100%; 1505 } 1506 .tab-wrapper{ 1507 display: inline-flex; 1508 justify-content: center; 1509 align-items: center; 1510 margin: 10px auto 20px; 1511 background-color: #eaeaea; 1512 border-radius: 200px; 1513 padding: 5px; 1514 gap: 10px; 1515 } 1516 .tab-wrapper .tab-label { 1517 display: inline-block; 1518 min-width: 130px; 1519 padding: 8px 15px; 1520 border-radius: 100px; 1521 cursor: pointer; 1522 font-size: 17px; 1523 line-height: 1.1; 1524 user-select: none; 1525 margin: 0; 1526 color: #000; 1527 } 1528 #register-tos a { 1529 display: inline; 1530 } 1531 @media screen and (max-width: 400px){ 1532 .tab-wrapper .tab-label { 1533 min-width: 110px; 1534 } 1535 } 1536 .tab-wrapper input[type='radio']:checked + .tab-label { 1537 background-color: #fff; 1538 box-shadow: 2px 2px 25px -10px #333; 1539 } 1540 1541 @media screen and (min-width: 500px){ 1542 .large--five-twelfths{ 1543 min-width: 420px; 1544 } 1545 } 1546</style> 1547 1548 1549 1550 1551<div class="customer login section-width-control small-width large--five-twelfths text-center wrapper"> 1552 <div class="card"> 1553 <h1 id="login" tabindex="-1" class="mb-0"> 1554 Welcome 1555 </h1> 1556 <p class="h3 mt-0"> 1557 1558 Sign up or log in to continue 1559 1560 </p> 1561 <div> 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 <div class="tab-wrapper"> 1580 <div> 1581 <input type="radio" name="type" id="tab-register" class="hide hidden" checked> 1582 <label for="tab-register" class="tab-label"> 1583 Sign up 1584 </label> 1585 </div> 1586 <div> 1587 <input type="radio" name="type" id="tab-login" class="hide hidden"> 1588 <label for="tab-login" class="tab-label"> 1589 Login 1590 </label> 1591 </div> 1592 </div> 1593 1594 1595 <form id="form-login" action="/account/auth" method="post" class="mt-2"> 1596 <input type="hidden" name="_token" value="TNYibZpXzUp6Eo3mau1Sbxad4gLDzXZSpgvdPVE9"> 1597 <input type="hidden" name="location_id" value=""> 1598 <input type="hidden" name="staff_id" value=""> 1599 <input type="hidden" id="recaptchaResponse" name="g-recaptcha-response"> 1600 1601 1602 <div id="error-content"></div> 1603 1604 <div class="field"> 1605 <input 1606 type="text" 1607 name="customer[email_or_phone]" 1608 id="CustomerDetail" 1609 autocorrect="off" 1610 autocapitalize="off" 1611 placeholder="Email" 1612 required 1613 > 1614 <label for="CustomerDetail"> 1615 Email 1616 </label> 1617 </div> 1618 1619 <button 1620 type="submit" 1621 form="form-login" 1622 class="btn button--full-width g-recaptcha"> 1623 Continue 1624 </button> 1625 1626 <div class="button-snippet"> 1627 1628 </div> 1629 1630 1631 1632 <div id="register-tos"> 1633 By signing up, I agree to the Tip Top Fruits & Groceries's <a target="_blank" href="/legal/refund-policy">Refund Policy</a>, <a target="_blank" href="/legal/privacy-policy">Privacy Policy</a>, <a target="_blank" href="/legal/terms-of-service">Terms of Service</a> and <a target="_blank" href="/legal/delivery-policy">Delivery Policy</a>. 1634 </div> 1635 1636 </form> 1637 </div> 1638 </div> 1639 1640</div> 1641 1642 1643
1644<script> 1645 const register_tab = document.querySelector('#tab-register'); 1646 const login_tab = document.querySelector('#tab-login'); 1647 const register_tos = document.querySelector('#register-tos'); 1648 const isRegistrationEnabled = "1"; 1649 1650 if (register_tab) { 1651 register_tab.addEventListener('click', function() { 1652 if (register_tos) { 1653 register_tos.style.display = 'block'; 1654 } 1655 }); 1656 } 1657 if (login_tab) { 1658 login_tab.addEventListener('click', function() { 1659 if (register_tos) { 1660 register_tos.style.display = 'none'; 1661 } 1662 }); 1663 } 1664 1665 const methodSwitchBtn = document.getElementById('phone-login-btn'); 1666 if (methodSwitchBtn) { 1667 methodSwitchBtn.onclick = function () { 1668 var type = (register_tab && register_tab.checked) ? 'register' : 'login'; 1669 window.location.href = '/account/login?method=phone&type=' + type; 1670 }; 1671 } 1672 1673 let lastPathSegment = window.location.pathname.split('/').filter(segment => segment.length > 0).pop(); 1674 1675 // Redirect to login if trying to access register when self registration is disabled 1676 if (!isRegistrationEnabled) { 1677 if (lastPathSegment === 'register') { 1678 window.location.href = '/account/login'; 1679 } else if (lastPathSegment === 'login' || lastPathSegment === 'auth') { 1680 if (register_tos) { 1681 register_tos.style.display = 'none'; 1682 } 1683 } 1684 } else { 1685 // Only proceed with tab logic if not redirecting 1686 if(lastPathSegment === 'login') { 1687 if (login_tab) { 1688 login_tab.checked = true; 1689 } 1690 if (register_tos) { 1691 register_tos.style.display = 'none'; 1692 } 1693 } else { 1694 if (register_tos) { 1695 register_tos.style.display = 'block'; 1696 } 1697 } 1698 } 1699 1700 const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; 1701 const phonePattern = /^(?:\+?\d{1,3}[\s-]?)?(?:\d{1,14}[\s-]?){1,5}$/; 1702 1703 let form = document.querySelector('#form-login'), 1704 input = document.querySelector('#CustomerDetail'), 1705 error_content = document.querySelector('#error-content'); 1706 1707 1708 // One attempt at a time: the reCAPTCHA wait below is async, so without 1709 // this a double-click starts two continuations and posts the form twice. 1710 var submitting = false; 1711 1712 form.addEventListener('submit', async function (event) { 1713 // preventDefault FIRST: a re-entrant submit must still be cancelled, or the 1714 // browser performs a native post with no captcha token. 1715 event.preventDefault(); 1716 if (submitting) return; 1717 1718 let input_value = input.value 1719 error_content.innerHTML = ''; 1720 if (!input_value.match(emailPattern) && !input_value.match(phonePattern)) { 1721 error_content.innerHTML = `<div class="errors note">Invalid Email or Phone</div>`; 1722 return false; 1723 } 1724 1725 submitting = true; 1726 document.querySelector('#form-login .btn').classList.add('btn--loading','loading'); 1727 1728 // reCAPTCHA is unreachable from some regions (google.com is blocked in 1729 // mainland China). Fail open the same way checkout and forgot-password do: 1730 // submit without a token rather than leave the button spinning forever. 1731 try { 1732 if (window.grecaptcha && typeof window.grecaptcha.enterprise === 'object') { 1733 // The loader defines a stub {ready} synchronously and fetches the real 1734 // implementation asynchronously, so execute() may not exist yet. 1735 // ready() queues until it does; the timeout stops a bundle that never 1736 // arrives from hanging the button. 1737 await new Promise(function (resolve) { 1738 setTimeout(resolve, 3000); 1739 try { grecaptcha.enterprise.ready(resolve); } catch (e) { resolve(); } 1740 }); 1741 1742 const token = await grecaptcha.enterprise.execute('6LdMNdIqAAAAALegJp7y4weVcCIlnwmIN8TWseEF', { action: 'LOGIN' }); 1743 document.getElementById('recaptchaResponse').value = token; 1744 } 1745 } catch (e) { /* fail open */ } 1746 1747 document.getElementById('form-login').submit(); 1748 }); 1749 1750 1751</script>
1751 1752 1753 1754 1755 </div> 1756 </div> 1757 1758 1759 1760 </main> 1761 1762 <footer class="site-footer small--text-center" role="contentinfo"> 1763 1764 1765 1766 <div class="wrapper"> 1767 1768 <div class="grid-uniform"> 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 <div class="grid__item large--one-half "> 1792 <a href="/" class="logo-wrapper" itemprop="url" > 1793 1794 <img style="max-width: 250px" src="https://cdn.store-assets.com/s/861942/f/8082524.png?width=350&format=webp" alt="Tip Top Fruits & Groceries" itemprop="logo"> 1795 <div style="display:inline;position:relative;top: -5px;padding: 20px;"> 1796 <img src="https://cdn.store-assets.com/s/861942/f/8371592.png" style="max-width: 250px; 1797 height: inherit; 1798 object-fit: cover; 1799 object-positon: center center;"> 1800 </div> 1801 1802 </a> 1803 <p class="site-footer__links">Copyright © 2026 Tip Top Fruits & Groceries (002450675-D). All right reserved.</p> 1804 </div> 1805 1806 1807 <div class="grid__item large--one-quarter medium--one-half"> 1808 1809 <h4>Quick Links</h4> 1810 1811 <ul class="site-footer__links"> 1812 1813 <li><a href="/store-locator" >Store Locator</a></li> 1814 1815 <li><a href="/a/contact-form" >Contact us</a></li> 1816 1817 1818 </ul> 1819 </div> 1820 1821 1822 1823 <div class="grid__item large--one-quarter medium--one-half"> 1824 <h4>Follow Us</h4> 1825 1826 <ul class="inline-list social-icons"> 1827 1828 1829 <li> 1830 <a class="icon-fallback-text" href="https://www.facebook.com/" title="Tip Top Fruits & Groceries on Facebook" target="_blank"> 1831 1832 1833 1834 1835 <svg xmlns="http://www.w3.org/2000/svg" class="facebook-icon-svg social-icon-svg" viewBox="0 0 1024 1024"> 1836 <title>icon-facebook</title> 1837 <path d="M837.66,223.9a33.73,33.73,0,0,0-3.11-15c-6.78-13.85-17.87-21.09-33.37-21.09q-288.46,0-576.91,0c-.62,0-1.24,0-1.85,0a34.51,34.51,0,0,0-25.88,12.11c-6.31,7.13-8.85,15.57-8.85,25.07q.08,287.7,0,575.4c0,1,0,1.9,0,2.86A32.93,32.93,0,0,0,190,814.71c4.45,11.79,16.3,23.11,35,23.1q153.61-.1,307.24,0c2.36,0,2.36,0,2.36-2.37q0-123.3,0-246.6c0-2.55,0-2.55-2.53-2.55H452.27c-2.26,0-2.26,0-2.26-2.17v-96.3h84.63v-2.46c0-22.12-.11-44.24.06-66.36.07-8.29.57-16.59,1.28-24.85a129.58,129.58,0,0,1,7.43-33c10.86-30,30.59-51.74,60-64.51A133.44,133.44,0,0,1,653,285.82c12.45-.37,24.93,0,37.38.34,9.64.27,19.27.95,28.9,1.6,5.36.36,10.7,1.07,16.06,1.5,1.46.12,1.65.75,1.65,2q0,42.2,0,84.39c0,.59-.06,1.18-.09,1.85h-2.39c-16.28,0-32.56,0-48.84.05-7.63,0-15.23.54-22.65,2.61-11.61,3.23-19.86,10.09-23.65,21.78a55.66,55.66,0,0,0-2.74,16.86c-.14,22.23-.1,44.47-.13,66.7,0,2.25,0,2.25,2.31,2.25h94.66a15.13,15.13,0,0,1,0,1.54c-.38,2.94-.81,5.88-1.18,8.82-1.17,9.16-2.3,18.33-3.48,27.5-1.29,10-2.63,20-3.94,30-1.23,9.44-2.43,18.88-3.67,28.32-.31,2.32-.35,2.32-2.78,2.32h-79a4.62,4.62,0,0,0-1.67,0,2.5,2.5,0,0,0-1.2,1.16,3.68,3.68,0,0,0,0,1.49V835.21c0,2.56,0,2.56,2.53,2.56H797.83c2.13,0,4.27-.07,6.39-.21,11.56-.78,20.61-6.07,27.23-15.48,4.66-6.6,6.24-14.09,6.24-22.11q-.06-287.19,0-574.38Z" fill="#999"/> 1838 </svg> 1839 1840 1841 1842 <span class="fallback-text">Facebook</span> 1843 </a> 1844 </li> 1845 1846 1847 1848 <li> 1849 <a class="icon-fallback-text" href="https://instagram.com/" title="Tip Top Fruits & Groceries on Instagram" target="_blank"> 1850 1851 1852 1853 1854 <svg xmlns="http://www.w3.org/2000/svg" class="instagram-icon-svg social-icon-svg" viewBox="0 0 1024 1024"> 1855 <title>icon-instagram</title> 1856 <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"/> 1857 </svg> 1858 1859 1860
1861 <span class="fallback-text">Instagram</span> 1862 </a> 1863 </li> 1864 1865 1866 1867 <li> 1868 <a class="icon-fallback-text" href="https://www.youtube.com/" title="Tip Top Fruits & Groceries on YouTube" target="_blank"> 1869 1870 1871 1872 1873 <svg xmlns="http://www.w3.org/2000/svg" class="youtube-icon-svg social-icon-svg" viewBox="0 0 1024 1024"> 1874 <title>icon-youtube</title> 1875 <path d="M870.81,327.93c-7.44-35.32-28.1-59.52-60.39-71.9-16.32-6.27-33.58-8-50.71-9.35-31.74-2.54-63.52-4.94-95.32-6.05q-68.85-2.41-137.75-2.8c-75.45-.43-150.91.42-226.25,5.31a672.25,672.25,0,0,0-68,7.84c-35.52,6-75.56,36.22-83.33,86.62a946.72,946.72,0,0,0-10.15,116.2c-1.48,49.67-1.33,99.34,1.42,149,1.57,28.34,4.16,56.51,9,84.49,6.1,35.11,25.46,59,54.45,75.29,17.17,9.66,36,12.91,54.91,14.37,38.69,3,77.44,5.58,116.21,7,42.47,1.56,85,1.63,127.49,2.35v-.91c27.2,0,54.4.26,81.6-.06,59.05-.68,118.09-1.91,176.89-8.23,14.61-1.57,29.51-3.48,43.44-8.06,29.6-9.75,52.29-29.47,63.23-60.8,5.32-15.27,7.62-31.93,9.82-48.18,5.81-43.06,7.61-86.47,8.39-129.92a1196.45,1196.45,0,0,0-5.15-133.62C878.49,373.5,875.55,350.44,870.81,327.93ZM440.45,633.7V390L627.17,511.81Z" fill="#999"/> 1876 </svg> 1877 1878 1879 1880 <span class="fallback-text">YouTube</span> 1881 </a> 1882 </li> 1883 1884 1885 1886 <li> 1887 <a class="icon-fallback-text" href="https://www.wechat.com/" title="Tip Top Fruits & Groceries on Wechat" target="_blank"> 1888 1889 1890 1891 1892 <svg xmlns="http://www.w3.org/2000/svg" class="wechat-icon-svg social-icon-svg" viewBox="0 0 1024 1024"> 1893 <title>icon-wechat</title> 1894 <path d="M509.37,482.16c29.49-24.59,63.48-40.07,100.86-48.3a294.69,294.69,0,0,1,44.64-6.5c5.71-.37,11.4-.79,17.11-1.08,1.86-.1,2.77-.6,2.42-2.69s-.42-4.28-.61-6.43a220.51,220.51,0,0,0-7.19-40C656,339.07,635.46,306.83,607.75,279c-28.36-28.5-61.83-49-99.56-62.69A283.2,283.2,0,0,0,417,199.23a213.94,213.94,0,0,0-24.16.59c-13,1.2-26.13,2.3-38.94,4.79-26.94,5.23-52.62,14.48-77.2,26.72C223.21,258,183.68,297.88,161,353.71c-9.81,24.2-15.95,49.33-16.92,75.46a264.06,264.06,0,0,0,1.51,35.32c2,19.79,7.67,38.67,15.79,56.79,16.2,36.18,40.74,65.8,71.65,90.31,5.36,4.25,10.89,8.29,16.38,12.37,4.93,3.67,7.12,8.26,5.36,14.43-1.42,4.94-2.86,9.89-4,14.9-4.58,20.71-9.05,41.45-13.55,62.18-.67,3.09-1.31,6.2-2.13,10.06,1.92-1.16,3-1.81,4.14-2.49,24.62-15.41,49.21-30.88,73.89-46.2,5.56-3.46,11.19-7,17.2-9.49,8.12-3.39,16.8-2,25.27-1.09,10.7,1.12,21.38,2.41,32,3.73,11.14,1.37,22.26,2.87,33.39,4.3,4.15.53,8.32,1,12.79,1.55,0-1.4,0-2.24,0-3.07-.54-8.87-1.34-17.74-1.6-26.63a203.63,203.63,0,0,1,5.42-53.2C448.47,547.52,474,511.61,509.37,482.16ZM514.5,349a39.34,39.34,0,1,1,.23,78.68c-22.59,0-40.23-17.22-40.22-39.24C474.53,366.87,492.52,349.12,514.5,349ZM318.71,427.66c-22.27,0-39.42-17.12-39.48-39.51-.06-21.76,17.28-39,39.35-39.11s40.28,17.87,40.3,39.75C358.9,410.07,340.76,427.61,318.71,427.66Z" fill="#999"/><path d="M872.26,588.13c-17.12-52.29-51.4-89.71-100.43-113.63-36.54-17.84-75.42-25-116.08-22.74a229.67,229.67,0,0,0-41.87,6c-46,11.25-84.79,34.59-115,71.23-29.36,35.63-42.93,76.58-38.61,122.87a159.58,159.58,0,0,0,20.55,64.22c17.53,30.94,42.08,55.13,72,74.06a197.32,197.32,0,0,0,60.32,25.26A226.27,226.27,0,0,0,653.94,821c14.18.73,28.34.55,42.24-2.35,11.7-2.43,23.17-5.94,34.79-8.79,13.65-3.36,27.33-3.68,40.59,1.46,9.31,3.61,18.3,8.06,27.42,12.15,1,.44,1.94.94,2.91,1.41l.44-.56-1.2-3.12A45.11,45.11,0,0,1,798.44,798c1.49-9.7,6.24-17.84,12.75-24.89,5.4-5.85,11.26-11.28,17-16.82,30.25-29.33,48-64.76,51.33-106.91A156.1,156.1,0,0,0,872.26,588.13ZM571.12,613.35a34.25,34.25,0,1,1,.73-68.5c19.32.06,34.27,15.33,34.16,34.9C605.9,598.49,590.39,613.47,571.12,613.35Zm158.69-.1c-19.24-.43-33.87-15.38-33.57-34.53A34,34,0,0,1,730.63,545c18.66,0,33.41,15.37,33.4,34.69A33.63,33.63,0,0,1,729.81,613.25Z" fill="#999"/> 1895 </svg> 1896 1897 1898 1899 <span class="fallback-text">Wechat</span> 1900 </a> 1901 </li> 1902 1903 1904 <li> 1905 <a class="icon-fallback-text" href="https://whatsapp.com/" title="Tip Top Fruits & Groceries on Whatsapp" target="_blank"> 1906 1907 1908 1909 1910 <svg xmlns="http://www.w3.org/2000/svg" class="whatsapp-icon-svg social-icon-svg" viewBox="0 0 1024 1024"> 1911 <title>icon-whatsapp</title> 1912 <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"/> 1913 </svg> 1914 1915 1916
1917 <span class="fallback-text">Whatsapp</span> 1918 </a> 1919 </li> 1920 1921 1922 1923 1924</ul> 1925 1926 </div> 1927 1928 </div> 1929 1930 <hr class="hr--small hr--clear"> 1931 1932 1933 <div class="grid"> 1934 1935 1936 1937 1938 <div class="grid__item text-center"> 1939 <ul class="inline-list payment-icons"> 1940 <li> 1941 <img src="https://s3-ap-southeast-1.amazonaws.com/eesb.public/images/payment/ssl_certified.png"> 1942 </li> 1943 </ul> 1944 </div> 1945 1946 </div> 1947 1948 <div class="grid"> 1949 <div class="grid__item text-center"> 1950 1951 <img width="100px" src="https://cdn.store-assets.com/s/861942/f/8407418.png"> 1952 <img width="100px" src="https://cdn.store-assets.com/s/861942/f/8407403.png"> 1953 </div> 1954 </div> 1955 1956 <div class="grid"> 1957 <div class="grid__item text-center"> 1958 1959 1960 <p class="site-footer__links"> 1961 1962 1963 1964 <a href="/legal/refund-policy">Refund Policy</a> 1965 1966 1967 1968 1969 | <a href="/legal/privacy-policy">Privacy Policy</a> 1970 1971 1972 1973 1974 | <a href="/legal/terms-of-service">Terms of Service</a> 1975 1976 1977 1978 1979 | <a href="/legal/delivery-policy">Delivery Policy</a> 1980 1981 1982 1983 </p> 1984 1985 </div> 1986 </div> 1987 1988 </div> 1989 </footer> 1990 1991 1992<div class="footer-bar large--hide"> 1993 <div> 1994 1995 1996 1997 1998 1999 2000 <a href="/"> 2001 2002 <img src="https://cdn.easystore.blue/s/201/f/5590.png?width=150&format=webp"/> 2003 2004 <div> 2005 Home 2006 </div> 2007 </a> 2008 2009 2010 2011 2012 2013 2014 2015 2016 <a href="/collections/all"> 2017 2018 <img src="https://cdn.easystore.blue/s/201/f/5591.png?width=150&format=webp"/> 2019 2020 <div> 2021 All products 2022 </div> 2023 </a> 2024 2025 2026 2027 2028 2029 2030 2031 2032 <a href="/collections/promotion"> 2033 2034 <img src="https://cdn.store-assets.com/s/861942/f/8317616.png?width=150&format=webp"/> 2035 2036 <div> 2037 Promotion 2038 </div> 2039 </a> 2040 2041 2042 2043 2044 2045 2046 2047 2048 <a href="/account/login"> 2049 2050 <img src="https://cdn.easystore.blue/s/201/f/5593.png?width=150&format=webp"/> 2051 2052 <div> 2053 Account 2054 </div> 2055 </a> 2056 2057 2058 2059 </div> 2060</div> 2061 2062 2063 2064 2065 2066 2067 <div id="scrollTopButton" class="on-right" style="display: none"> 2068 <svg class="svg-icon" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><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> 2069 </div> 2070
2070<script> 2071 $( document ).ready(function() { 2072 var winScroll = $(this).scrollTop(), 2073 this_el = $("#scrollTopButton"); 2074 2075 // Header bar 2076 if(winScroll > 400){ 2077 this_el.fadeIn(); 2078 }else{ 2079 this_el.fadeOut(); 2080 } 2081 2082 $("#scrollTopButton").click(function() { 2083 $('html,body').animate({ scrollTop: 0 }); 2084 }); 2085 2086 $(window).scroll(function(){ 2087 var winScroll = $(this).scrollTop(); 2088 2089 // Header bar 2090 if(winScroll > 400){ 2091 this_el.fadeIn(); 2092 }else{ 2093 this_el.fadeOut(); 2094 } 2095 2096 }); 2097 }); 2098 </script>
2098 2099 2100 2101 2102 2103 2104
2104<script src="https://store-themes.easystore.co/861942/themes/2877/assets/fastclick.min.js?t=1787079718" type="text/javascript" ></script>
2104 2105
2105<script src="https://store-themes.easystore.co/861942/themes/2877/assets/timber.js?v1.1?t=1787079718" type="text/javascript" ></script>
2105 2106
2106<script src="https://store-themes.easystore.co/861942/themes/2877/assets/theme.js?t=1787079718" type="text/javascript" ></script>
2106 2107 2108 2109 2110 2111 2112 2113
2114<script src="/assets/currencies.js" type="text/javascript" ></script>
vendor: 1 bytes, line 2114
2114
2115<script src="/assets/jquery.currencies.min.js" type="text/javascript" ></script>
vendor: 1 bytes, line 2115
2115
2116<script src="/assets/currencies_format.js" type="text/javascript" ></script>
2116 2117
2118<script> 2119Currency.format = "money_with_currency_format"; 2120var shopCurrency = 'MYR'; 2121var selectedCurrency = ''; 2122 2123 2124 Currency.convert = function(amount, from, to) { 2125 return amount; 2126 }; 2127 2128 2129if( $.cookie("currency") == null ){ 2130 2131 if( selectedCurrency != false ) { 2132 2133 Currency.convertAll(shopCurrency, selectedCurrency); 2134 jQuery('.selected-currency').text(Currency.currentCurrency); 2135 2136 } 2137 2138} 2139 2140/* Sometimes merchants change their shop currency, let's tell our JavaScript file */ 2141// Currency.moneyFormats[shopCurrency].money_with_currency_format = ""; 2142// Currency.moneyFormats[shopCurrency].money_format = "RM {{amount}} "; 2143 2144/* Default currency */ 2145var defaultCurrency = 'MYR'; 2146 2147/* Cookie currency */ 2148var cookieCurrency = Currency.cookie.read(); 2149 2150 cookieCurrency = shopCurrency; 2151 2152$("input[name=current_currency]").val(cookieCurrency); 2153if(cookieCurrency == null){ 2154 cookieCurrency = shopCurrency; 2155 Currency.cookie.write(shopCurrency); 2156} 2157/* Fix for customer account pages */ 2158jQuery('span.money span.money').each(function() { 2159 jQuery(this).parents('span.money').removeClass('money'); 2160}); 2161/* Saving the current price */ 2162jQuery('span.money').each(function() { 2163 jQuery(this).attr('data-currency-MYR', jQuery(this).html()); 2164}); 2165// If there's no cookie. 2166if (cookieCurrency == null) { 2167 if (shopCurrency !== defaultCurrency) { 2168 Currency.convertAll(shopCurrency, defaultCurrency); 2169 } 2170 else { 2171 Currency.currentCurrency = defaultCurrency; 2172 } 2173} 2174// If the cookie value does not correspond to any value in the currency dropdown. 2175else if (jQuery('[name=currencies]').size() && jQuery('[name=currencies] option[value=' + cookieCurrency + ']').size() === 0) { 2176 Currency.currentCurrency = shopCurrency; 2177 Currency.cookie.write(shopCurrency); 2178} 2179else if (cookieCurrency === shopCurrency) { 2180 Currency.currentCurrency = shopCurrency; 2181 Currency.convertAll(shopCurrency, cookieCurrency); 2182} 2183else { 2184 Currency.convertAll(shopCurrency, cookieCurrency); 2185} 2186jQuery('[name=currencies]').val(Currency.currentCurrency).change(function() { 2187 var newCurrency = jQuery(this).val(); 2188 2189 2190 Currency.cookie.write(newCurrency) 2191 if ('customers' == 'cart') { 2192 const params = new URLSearchParams(window.location.search); 2193 params.set('delete_cache', 1); 2194 window.location.search = params; 2195 } else { 2196 window.location.reload(); 2197 } 2198 2199}); 2200var original_selectCallback = window.selectCallback; 2201var selectCallback = function(variant, selector) { 2202 var currencies = null; 2203 original_selectCallback(variant, selector); 2204 if(typeof jQuery('[name=currencies]').val() == "undefined"){ 2205 currencies = shopCurrency; 2206 } 2207 else{ 2208 currencies = jQuery('[name=currencies]').val(); 2209 } 2210 Currency.convertAll(shopCurrency, currencies); 2211 jQuery('.selected-currency').text(Currency.currentCurrency); 2212}; 2213$('body').on('ajaxCart.afterCartLoad', function(cart) { 2214 Currency.convertAll(shopCurrency, jQuery('[name=currencies]').val()); 2215 jQuery('.selected-currency').text(Currency.currentCurrency); 2216}); 2217jQuery('.selected-currency').text(Currency.currentCurrency); 2218</script>
2218 2219 2220 2221 2222<!-- Snippet:global/body_end: Product Label --> 2223<link href='https://apps.easystore.co/assets/css/product-label/main.css?v2.3' rel='stylesheet' type='text/css' media='screen' />
2223<script src='https://apps.easystore.co/product-labels/productlabelv2.js?shop=christiewttfg.easy.co' type='text/javascript'></script>
2223 2224<!-- /Snippet -->
2225<script> 2226 2227 /* 2228 2229 ------ 2230 Events 2231 ------ 2232 2233 pages/viewed 2234 2235 customers/signup 2236 2237 customers/login 2238 2239 products/searched 2240 2241 collections/viewed 2242 2243 products/viewed 2244 2245 products/shared 2246 2247 wishlists/item_added 2248 2249 carts/items_added 2250 2251 carts/viewed 2252 2253 carts/item_removed 2254 2255 checkouts/initiated 2256 2257 checkouts/shipping_info_added 2258 2259 checkouts/payment_info_added 2260 2261 checkouts/completed 2262 2263 orders/placed 2264 2265 orders/purchased 2266 2267 payments/captured 2268 2269 payments/failed 2270 2271 */ 2272 2273 window.__latest_cart = window.__latest_cart || null; 2274 2275 const _selector = document.querySelector.bind(document), 2276 _selectorAll = document.querySelectorAll.bind(document) 2277 2278 document.addEventListener('DOMContentLoaded', (event) => { 2279 2280 const default_currency = getCookie("currency") 2281 const customer_id = window.__st.cid 2282 const template = window.__st.p 2283 2284 onPageView() 2285 2286 //-----------------------// 2287 // Configs // 2288 //-----------------------// 2289 2290 window.dataLayer = window.dataLayer || [] 2291 2292 Array.prototype.last = Array.prototype.last || function() { 2293 return this[this.length - 1] || null 2294 } 2295 2296 Array.prototype.first = Array.prototype.first || function() { 2297 return this[0] || null 2298 } 2299 2300 //----------------------// 2301 // Triggers // 2302 //----------------------// 2303 2304 const XHR = window.XMLHttpRequest 2305 2306 function xhr() { 2307 2308 const xhr = new XHR() 2309 2310 xhr.addEventListener("readystatechange", function() { 2311 2312 if(xhr.readyState != 4) return 2313 2314 try { 2315 2316 const response_url = xhr.responseURL 2317 2318 if (response_url.includes("cart/add")) { 2319 2320 window.__latest_cart = JSON.parse(xhr.response) 2321 2322 onCartItemsAdded() // ok 2323 2324 } 2325 2326 if (response_url.includes("cart/remove_item_quantity")) { 2327 2328 window.__latest_cart = JSON.parse(xhr.response) 2329 2330 onCartItemRemoved() // ok 2331 2332 } 2333 2334 if (response_url.includes("new_cart?retrieve=true")) { 2335 2336 result = JSON.parse(xhr.response) 2337 2338 if (result.cart) { 2339 window.__latest_cart = result.cart 2340 } 2341 2342 } 2343 2344 } catch(e) { 2345 2346 console.error(e) 2347 2348 } 2349 2350 }, false); 2351 2352 return xhr 2353 2354 } 2355 2356 window.XMLHttpRequest = xhr 2357 2358 switch(template) { 2359 2360 case 'cart': onCartView() // ok 2361 break 2362 case 'product': onProductView() // ok 2363 break 2364 case 'collection': onCollectionView() // ok 2365 break 2366 case 'blog': onBlogView() 2367 break 2368 case 'article': onArticleView() 2369 break 2370 case 'payment_completed': onOrderPlace() 2371 break 2372 case 'payment_fail': onPaymentFail() 2373 break 2374 2375 } 2376 2377 // _selector('form[action="/checkout/payments"]').addEventListener("submit", onPaymentInfoAdded(_selector('form[action="/checkout/payments"]'))) 2378 if (_selector('form[action="/checkout/detail"]')) _selector('form[action="/checkout/detail"]').addEventListener("submit", ()=>{onShippingInfoAdded(_selector('form[action="/checkout/detail"]'))}) // ok 2379 if (_selector('form[action="/checkout/shipping"]')) _selector('form[action="/checkout/shipping"]').addEventListener("submit", ()=>{onShippingInfoAdded(_selector('form[action="/checkout/shipping"]'))}) // ok 2380 if (_selector('form[action="/account/register"]')) _selector('form[action="/account/register"]').addEventListener("submit", onSignUp) // ok 2381 if (_selector('form[action="/account/login"]')) _selector('form[action="/account/login"]').addEventListener("submit", onLogin) // ok 2382 if (_selector('form[action="/search"]')) _selector('form[action="/search"]').addEventListener("submit", onProductSearch()) // ok 2383 if (_selector('#line-login-btn')) _selector('#line-login-btn').addEventListener('click', onLineLogin) // ok 2384 if (_selector('#PlaceOrder')) _selector('#PlaceOrder').addEventListener("click", ()=>{onCheckoutComplete(_selector('form[action="/checkout/payments"]'))}); // ok 2385 if (_selector('#add_wishlist')) _selector('#add_wishlist').addEventListener("click", onWishlistItemAdded) // ok 2386 if (_selectorAll('a[href="/account/logout"]')) _selectorAll('a[href="/account/logout"]').forEach(logoutButton => logoutButton.addEventListener("click", onLogout)) // ok 2387 if (_selector('.CartDrawerTrigger.cart-page-link')) _selector('.CartDrawerTrigger.cart-page-link').addEventListener("click", onCartView) // ok 2388 if (_selector('.CartDrawerTrigger.cart-page-link.mobile-cart-page-link')) _selector('.CartDrawerTrigger.cart-page-link.mobile-cart-page-link').addEventListener("click", onCartView) // ok 2389 if (_selectorAll('a[class^="share-"]')) _selectorAll('a[class^="share-"]').forEach(shareButton => shareButton.addEventListener("click", ()=>{onProductShare(shareButton)}) ) // ok 2390 if (_selectorAll('[name$="checkout"]')) _selectorAll('[name$="checkout"]').forEach(checkoutButton => checkoutButton.addEventListener("click", onCheckoutInitiate)) 2391 2392 // For append elements 2393 const bodyMutationObserver = new MutationObserver(() => { 2394 if (_selector('#form__spc #PlaceOrder')) _selector('#form__spc #PlaceOrder').addEventListener("click", onSinglePageCheckout) // ok 2395 if (_selectorAll('[name$="checkout"]')) _selectorAll('[name$="checkout"]').forEach(checkoutButton => checkoutButton.addEventListener("click", onCheckoutInitiate)) 2396 }); 2397 bodyMutationObserver.observe(_selector("body"), {subtree: true, childList: true}); 2398 2399 //------------------------------// 2400 // Event handlers // 2401 //------------------------------// 2402 2403 function onPageView() { 2404 2405 EasyStore.Event.dispatch('pages/viewed', { 2406 page: { 2407 type: template, 2408 title: document.title, 2409 description: _selector('meta[name=description]') ? _selector('meta[name=description]').getAttribute('content') : null, 2410 url: location.href, 2411 } 2412 }) 2413 2414 } 2415 2416 function onSignUp() { 2417 2418 const email_regex = new RegExp(/^[a-zA-Z0-9.!#$%&"*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/) 2419 const phone_regex = new RegExp(/^(\+?6?01)[0-46-9]-*[0-9]{7,8}$/) 2420 2421 const email_or_phone = _selector(`input[name="customer[email_or_phone]"]`).value.replace("+", "").replace(/\s+/, "") 2422 2423 let data = {} 2424 2425 if (email_regex.test(email_or_phone)) { 2426 data.method = 'email' 2427 data.email = email_or_phone 2428 } 2429 2430 if (phone_regex.test(email_or_phone)) { 2431 data.method = "phone" 2432 data.phone = email_or_phone 2433 } 2434 2435 if (!data.method) return 2436 2437 EasyStore.Event.dispatch('customers/signup', data) 2438 2439 } 2440 2441 function onLogin() { 2442 2443 const email_regex = new RegExp(/^[a-zA-Z0-9.!#$%&"*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/) 2444 const phone_regex = new RegExp(/^(\+?6?01)[0-46-9]-*[0-9]{7,8}$/) 2445 2446 const email_or_phone = _selector(`input[name="customer[email_or_phone]"]`).value.replace("+", "").replace(/\s+/, "") 2447 2448 let data = {} 2449 2450 if (email_regex.test(email_or_phone)) { 2451 data.method = 'email' 2452 data.email = email_or_phone 2453 } 2454 2455 if (phone_regex.test(email_or_phone)) { 2456 data.method = "phone" 2457 data.phone = email_or_phone 2458 } 2459 2460 if (!data.method) return 2461 2462 EasyStore.Event.dispatch('customers/login', data) 2463 2464 } 2465 2466 function onLineLogin() { 2467 2468 EasyStore.Event.dispatch('customers/login', { method: 'line' }) 2469 2470 } 2471 2472 function onLogout() { 2473 2474 EasyStore.Event.dispatch('customers/logout', { customer_id }) 2475 2476 } 2477 2478 function onBlogView() { 2479 2480 const blog = "" 2481 2482 EasyStore.Event.dispatch('blogs/viewed', { blog }) 2483 2484 } 2485 2486 function onArticleView() { 2487 2488 const article = "" 2489 2490 EasyStore.Event.dispatch('articles/viewed', { article }) 2491 2492 } 2493 2494 function onProductSearch() { 2495 2496 const query = _selector('input[name=q]').value 2497 2498 if (!query) return 2499 2500 EasyStore.Event.dispatch('products/searched', { query }) 2501 2502 } 2503 2504 function onCollectionView() { 2505 2506 const collection = "" 2507 2508 EasyStore.Event.dispatch('collections/viewed', { collection }) 2509 2510 } 2511 2512 function onProductView() { 2513 2514 const product = "" 2515 2516 EasyStore.Event.dispatch("products/viewed", { product }) 2517 2518 } 2519 2520 function onProductShare(el) { 2521 2522 const product = "" 2523 2524 const channel = el.getAttribute("class").split("-").last() 2525 2526 EasyStore.Event.dispatch('products/shared', { product, channel }) 2527 2528 } 2529 2530 function onWishlistItemAdded() { 2531 2532 let product = "" 2533 const quantity = _selector("#Quantity").value 2534 2535 EasyStore.Event.dispatch('wishlists/item_added', { product }) 2536 2537 } 2538 2539 async function onCartItemsAdded() { 2540 2541 const cart = await getCart() 2542 2543 if(cart && cart.items != undefined && cart.items.length > 0) { 2544 2545 EasyStore.Event.dispatch('carts/item_added', { cart }) 2546 2547 } 2548 2549 } 2550 2551 async function onCartView() { 2552 2553 const cart = await getCart() 2554 2555 EasyStore.Event.dispatch('carts/viewed', { cart }) 2556 2557 } 2558 2559 async function onCartItemRemoved() { 2560 2561 const cart = await getCart() 2562 2563 cart.items = [] 2564 2565 if(cart) { 2566 2567 EasyStore.Event.dispatch('carts/item_removed', { cart }) 2568 2569 } 2570 2571 } 2572 2573 async function onCheckoutInitiate() { 2574 2575 const cart = await getCart() 2576 2577 EasyStore.Event.dispatch('checkouts/initiated', { cart }) 2578 2579 } 2580 2581 async function onShippingInfoAdded(form) { 2582 let checkout = getCheckout() 2583 2584 let form_data = {} 2585 new FormData(form).forEach((value, key) => form_data[key] = value) 2586 2587 let shipping_tier = null 2588 2589 if (form_data.type && form_data.type.startsWith("r_pickup")) { 2590 shipping_tier = `Pickup - ${form_data.pick_location}` 2591 } 2592 2593 if (form_data.s_id) {
2594 shipping_tier = _selector(`input[id='`+form_data.s_id+`']`).getAttribute("data-shipping-name") 2595 } 2596 2597 if (!shipping_tier) return 2598 2599 EasyStore.Event.dispatch('checkouts/shipping_info_added', { checkout, shipping_tier }) 2600 2601 } 2602 2603 async function onPaymentInfoAdded(form) { 2604 2605 let checkout = getCheckout() 2606 2607 let payment_type = new FormData(form).get('payment_method') 2608 2609 EasyStore.Event.dispatch("checkouts/payment_info_added", { checkout, payment_type }) 2610 2611 } 2612 2613 async function onOrderPlace() { 2614 2615 let cart_token = getCookie("cart_js") 2616 let previous_cart_token = getCookie("previous_cart_ga4_js") 2617 2618 if (previous_cart_token && previous_cart_token == cart_token) { 2619 // Prevent duplicate purchase tracking 2620 return 2621 } 2622 2623 let order = getOrder() 2624 2625 EasyStore.Event.dispatch('orders/placed', { order }) 2626 2627 if(order.is_manual_payment) { 2628 2629 EasyStore.Event.dispatch('orders/purchased', { order }) 2630 2631 } 2632 2633 const last_transaction = order.transactions.last() 2634 2635 if (last_transaction.status) { 2636 2637 EasyStore.Event.dispatch('orders/purchased', { order }) 2638 EasyStore.Event.dispatch('payments/captured', { order }) 2639 2640 } 2641 2642 } 2643 2644 async function onPaymentFail() { 2645 2646 const order = getOrder() 2647 2648 EasyStore.Event.dispatch('payments/failed', { order }) 2649 2650 } 2651 2652 async function onCheckoutComplete(form) { 2653 2654 onPaymentInfoAdded(form) 2655 2656 const checkout = getCheckout() 2657 2658 EasyStore.Event.dispatch('checkouts/completed', { checkout }) 2659 2660 } 2661 2662 async function onSinglePageCheckout() { 2663 2664 // let checkout = $("[data-app-checkout]").data("app-checkout") 2665 2666 let checkout = getCheckout() 2667 2668 // const payment_type = _selector("#app_spc_payment_method").find(`[class*="label-content"]`).first().find("b").first().text() 2669 const payment_type = _selector("#app_spc_payment_method").getElementsByClassName('label-content')[0].getElementsByTagName('b')[0].innerHTML 2670 2671 const shipping_method = _selector("#delivery_method").value 2672 2673 let shipping_tier = null 2674 let app_spc_customer_info_label = _selector("#app_spc_customer_info").getElementsByClassName('label-content') 2675 if (shipping_method == "shipping") { 2676 shipping_tier = app_spc_customer_info_label[app_spc_customer_info_label.length - 1].getElementsByTagName('b')[0].innerHTML 2677 } 2678 2679 if (shipping_method == "pickup") { 2680 shipping_tier = app_spc_customer_info_label[0].innerHTML 2681 } 2682 2683 if (shipping_tier) { 2684 2685 EasyStore.Event.dispatch('checkouts/shipping_info_added', { 2686 checkout, 2687 shipping_tier, 2688 }) 2689 2690 } 2691 2692 if (payment_type) { 2693 2694 EasyStore.Event.dispatch('checkouts/payment_info_added', { 2695 checkout, 2696 payment_type, 2697 }) 2698 2699 } 2700 2701 EasyStore.Event.dispatch('checkouts/completed', { checkout }) 2702 2703 } 2704 2705 }) 2706 2707 2708 //-----------------------// 2709 // Functions // 2710 //-----------------------// 2711 2712 function getCookie(name) { 2713 2714 name += "=" 2715 2716 decodedCookie = decodeURIComponent(document.cookie) 2717 2718 ca = decodedCookie.split(";") 2719 2720 for(i = 0; i < ca.length; i++) { 2721 c = ca[i] 2722 while (c.charAt(0) == " ") { 2723 c = c.substring(1) 2724 } 2725 if (c.indexOf(name) == 0) { 2726 return c.substring(name.length, c.length) 2727 } 2728 } 2729 2730 return "" 2731 2732 } 2733 2734 const parsePrice = price => { 2735 if(typeof price === 'string') { 2736 return parseFloat(price.split(',').join('')) 2737 } 2738 2739 return price 2740 } 2741 2742 const requestCart = async (method, data) => { 2743 2744 let response = await fetch('/cart.json', {method: 'GET',headers: {'Content-Type': 'application/json'}}) 2745 result = await response.json() 2746 2747 return result.cart 2748 2749 } 2750 const getCart = async (latest = false) => { 2751 2752 let cart = window.__latest_cart 2753 2754 const cart_invalid = !cart || !cart.items || (cart.total_price > 0 && !cart.items.length) 2755 2756 if(latest || cart_invalid) { 2757 cart = await requestCart() 2758 } 2759 2760 cart.items = cart.items || [] 2761 2762 return mapCart(cart) 2763 2764 } 2765 2766 const getCheckout = async () => { 2767 mapCheckout(window.__latest_cart || await requestCart()) 2768 } 2769 2770 const getOrder = async () => { 2771 mapOrder(window.__latest_cart || await requestCart()) 2772 } 2773 2774 //-----------------------// 2775 // Mappers // 2776 //-----------------------// 2777 2778 const fallbackAttribute = (object, attribute) => { 2779 2780 if(!Array.isArray(attribute)) { 2781 attribute = [attribute] 2782 } 2783 2784 let final_value = null 2785 2786 do { 2787 2788 final_value = object[attribute.shift()] 2789 2790 } while(!final_value && attribute.length) 2791 2792 return final_value 2793 2794 } 2795 2796 const map = (object, mapper) => { 2797 2798 const newObject = {} 2799 2800 for(const key in mapper) { 2801 2802 // Handle different keys between new and old format
2803 newObject[key] = fallbackAttribute(object, mapper[key]) 2804 2805 // Cast price to float 2806 if(newObject[key] && ['price', 'amount', 'discount', 'discounts'].some(x => key.endsWith(x))) { 2807 newObject[key] = parsePrice(newObject[key]) 2808 } 2809 2810 if(newObject[key] === undefined) { 2811 delete newObject[key] 2812 } 2813 2814 } 2815 2816 return newObject 2817 2818 } 2819 2820 const mapCart = cart => { 2821 2822 const oldCart = cart 2823 2824 const mapper = { 2825 id: 'id', 2826 currency: 'currency', 2827 item_count: 'item_count', 2828 items: 'items', 2829 total_price: 'total_price', 2830 latest_items: 'latest_items' 2831 } 2832 2833 cart = map(cart, mapper) 2834 2835 const discounts = (oldCart.storewide_discounts || []).concat((oldCart.voucher_discounts || [])) 2836 2837 cart.discount_applications = discounts.map(discount => ({ 2838 title: discount.voucher_code || null, 2839 value: parsePrice(discount.amount), 2840 })) 2841 2842 cart.original_total_price = cart.items.length 2843 ? cart.items 2844 .map(item => item.original_price) 2845 .reduce((sum, price) => sum + price) 2846 : 0 2847 2848 cart.total_discount = cart.discount_applications.length 2849 ? cart.discount_applications 2850 .map(discount => parsePrice(discount.value)) 2851 .reduce((sum, value) => sum + value) 2852 : 0 2853 2854 cart.items = cart.items.map(item => mapLineItem(item)) 2855 2856 return cart 2857 2858 } 2859 2860 const mapCheckout = checkout => { 2861 2862 const mapper = { 2863 note: 'note', 2864 attributes: 'note_attributes', 2865 billing_address: 'billing_address', 2866 currency: 'currency', 2867 customer_id: 'customer_id', 2868 discounts_amount: 'total_discount', 2869 id: 'id', 2870 line_items: 'order_item', 2871 order_number: 'order_number', 2872 shipping_address: 'shipping_address', 2873 shipping_price: 'shipping_tax', 2874 shipping_method: 'shipping_method_name', 2875 tax_price: 'total_tax', 2876 } 2877 2878 checkout = map(checkout, mapper) 2879 2880 checkout.requires_shipping = checkout.line_items.some(item => item.shipping_required) 2881 2882 checkout.line_items = checkout.line_items.map(item => mapLineItem(item)) 2883 2884 return checkout 2885 2886 } 2887 2888 const mapOrder = order => { 2889 2890 const mapper = { 2891 attributes: 'note_attributes', 2892 billing_address: 'billing_address', 2893 cancelled: 'is_cancelled', 2894 cancelled_at: 'cancelled_at', 2895 created_at: 'created_at', 2896 customer_id: 'customer_id', 2897 // discount_applications: 'discount_applications', 2898 email: 'email', 2899 financial_status: 'financial_status', 2900 fulfillment_status: 'fulfillment_status', 2901 line_items: 'order_item', 2902 note: 'note', 2903 order_number: 'order_number', 2904 phone: 'phone', 2905 shipping_address: 'shipping_address', 2906 shipping_methods: 'shipping_methods', 2907 shipping_price: 'total_shipping', 2908 subtotal_price: 'subtotal_price', 2909 // tax_lines: 'tax_lines', 2910 tax_price: 'total_tax', 2911 total_discounts: 'total_discount', 2912 total_net_amount: 'total_amount_include_transaction', 2913 total_price: 'total_price', 2914 transactions: 'transaction_records', 2915 is_manual_payment: 'is_manual_payment', 2916 } 2917 2918 order.email = order.billing_address.email 2919 order.phone = order.billing_address.phone 2920 order.shipping_method = order.shipping_method_name 2921 2922 order = map(order, mapper) 2923 2924 order.line_items = order.line_items.map(item => mapLineItem(item)) 2925 order.transactions = order.transactions.map(transaction => mapTransaction(transaction)) 2926 2927 return order 2928 2929 } 2930 2931 const mapLineItem = line_item => { 2932 2933 const old_line_item = line_item 2934 2935 const mapper = { 2936 final_price: 'price', 2937 image: 'img_url', 2938 message: 'message', 2939 original_line_price: 'original_line_price', 2940 original_price: 'original_price', 2941 properties: 'properties', 2942 quantity: 'quantity', 2943 requires_shipping: 'shipping_required', 2944 sku: 'sku', 2945 taxable: 'taxable', 2946 title: 'product_name', 2947 product_name: 'product_name', 2948 url: 'url', 2949 product_id: 'product_id', 2950 variant_id: 'variant_id', 2951 id: ['id', 'i_id'], 2952 } 2953 2954 line_item = map(line_item, mapper) 2955 2956 line_item.product_id = line_item.product_id || (old_line_item.product && old_line_item.product.id) || null 2957 line_item.variant_id = line_item.variant_id || (old_line_item.variant && old_line_item.variant.id) || null 2958 line_item.image = line_item.image || (old_line_item.image && old_line_item.image.url) || null 2959 2960 return line_item 2961 2962 } 2963 2964 const mapTransaction = transaction => { 2965 2966 const mapper = { 2967 amount: 'amount', 2968 created_at: 'created_at', 2969 gateway: 'gateway_type', 2970 id: 'id', 2971 status: 'status', 2972 } 2973 2974 transaction = map(transaction, mapper) 2975 2976 return transaction 2977 2978 } 2979 2980 2981</script>
2981 2982 2983</div> 2984 2985 2986 2987<style> 2988 #CartTemplate{ 2989 min-height: 80vh; 2990 } 2991 .cart-drawer .cart__row .small--one-whole, 2992 .cart-drawer .cart-sticky-button-wrapper{ 2993 width: 100%; 2994 } 2995 .cart-drawer .promotion__code-input .input-group{ 2996 margin-top: 20px; 2997 max-width: 100%; 2998 } 2999 .cart-drawer-wrapper{ 3000 display: flex; 3001 flex-wrap: wrap; 3002 flex-direction: row; 3003 } 3004 .cart-drawer-wrapper > div{ 3005 width: 100%; 3006 } 3007 vouchers-modal .vouchers-modal.active , 3008 vouchers-modal #vouchers-modal-backdrop.active{ 3009 z-index: 2147483647; 3010 } 3011</style> 3012 3013<div id="CartDrawer" class="cart-drawer" data-fetch="0"> 3014 3015 3016 <div class="cart-drawer-wrapper"> 3017 3018<!-- Snippet:cart/content_top: Google Analytics 4 --> 3019<div id="CartDataStorage" data-cart='{"item_count":0,"total_price":0,"announcements":[]}'></div> 3020 3021<!-- /Snippet --> 3022<div id="cart-promotion-top"></div> 3023 3024 3025 <div id="CartTemplate"> 3026 3027 3028 3029 3030 3031 <div id="noCartItem" class="cart-drawer-content"> 3032 <div class="cart-drawer-content-wrapper text-center"> 3033 <div class="section-header"> 3034 <span></span> 3035 <span class="CartDrawerTrigger icon icon-x"></span> 3036 </div> 3037 <div class="section-header__title h2">Your cart is currently empty.</div> 3038 <a class="btn btn--secondary" href="/collections/all">Continue shopping</a> 3039 </div> 3040 </div> 3041 3042 3043 3044 </div> 3045 3046 <link href="/assets/css/promotion.css?v2.94" rel="stylesheet" type="text/css" media="screen" /> 3047<div id="cart-promotion-section"></div> 3048
3049<script>var shop_money_format = "<span class=money data-ori-price='{{amount}}'>RM {{amount}} </span>";</script>
vendor: 1 bytes, line 3049
3049
3050<script src="/assets/js/promotion/promotion.js?v1.11" type="text/javascript"></script>
3050 3051
3052<script> 3053 3054 window.EasyStore = window.EasyStore || {}; 3055 window.EasyStore.Promotion = window.EasyStore.Promotion || {}; 3056 3057 var get_cart_promo_initial = false, 3058 current_template = 'customers'; 3059 3060 window.EasyStore.Promotion.updateCartPromotion = function (){ 3061 get_cart_promo_initial = true 3062 $.ajax({ 3063 type: "GET", 3064 dataType: 'json', 3065 url: "/new_cart/promotion", 3066 success: function(response){ 3067 $("#cart-promotion-section").html(response["cart/content_bottom"].trim()); 3068 $("#cart-promotion-top").html(response["cart/content_top"].trim()); 3069 3070 promoVariantDetailInitial() 3071 }, 3072 error: function(xhr){ 3073 } 3074 }); 3075 } 3076 3077 3078 if(current_template == 'cart') { 3079 document.addEventListener("DOMContentLoaded", function() { 3080 window.EasyStore.Promotion.updateCartPromotion() 3081 }); 3082 } 3083 3084</script>
vendor: 1 bytes, line 3084
3084
3085<script> 3086 document.addEventListener('DOMContentLoaded', function () { 3087 window._getVoucherErrorTranslation = Object.assign(window._getVoucherErrorTranslation || {}, { 3088 "condition_not_matched": "Voucher condition not matched", 3089 "promotion_unavailable": "This promotion is currently unavailable", 3090 "available_on": "Available on channels", 3091 "available_on_only": "Available on channels only", 3092 "available_with_locations": "Available on channels (locations only)", 3093 "pos_at_locations": "Retail Store at locations only", 3094 "channel_website": "Website", 3095 "channel_mobile": "Mobile Apps", 3096 "channel_pos": "Retail Store" 3097 }); 3098 }); 3099</script>
3099 3100 3101 </div> 3102 3103 3104 3105</div> 3106 3107<div id="toast"><div id="toastContent"></div></div> 3108<style> 3109 .cart-drawer .cart-drawer-content .cart-sticky-button-wrapper a.btn.CartDrawerTrigger{margin-bottom: 10px !important;} 3110 #toastContent a{color: #fff;text-decoration: underline;margin-top: 10px;display: block;} 3111 #toastContent .svg-icon{margin-right: 8px;margin-top: -1px;} 3112</style> 3113
3114<script type="text/javascript"> 3115 $('body').on("submit", "#CartForm", function() { 3116 $(this).find('[type=submit]').addClass('btn--loading'); 3117 }); 3118 3119 $("input[name=current_currency]").val($( "select.currency-picker" ).val()); 3120 $( "select.currency-picker" ).change(function(){ 3121 $("select.currency-picker").val($(this).val()); 3122 url=window.location.href; 3123 newParam="currency=" + $( "select.currency-picker" ).val(); 3124 if(url.indexOf("currency=")===-1){ 3125 separator = (url.indexOf("?")===-1)?"?":"&"; 3126 newUrl= url + separator + newParam; 3127 }else{ 3128 oldParam= new URL(url); 3129 oldParam = oldParam.searchParams.get("currency"); 3130 newParam= $(this).val(); 3131 newUrl=url.replace(oldParam,newParam); 3132 } 3133 $("input[name=current_currency]").val($( "select.currency-picker" ).val()); 3134 // window.location.href =newUrl; 3135 $('#CartDrawer').attr('data-fetch', 0); 3136 }); 3137 3138 $("body").on("click", ".cart__remove", function() { 3139 $('#CartTemplate').addClass('is-loading'); 3140 $.ajax({ 3141 type: 'POST', 3142 url: '/cart/remove_item_quantity', 3143 data: { 3144 variant_id: $(this).data( "variant-id"), 3145 item_id: $(this).data( "item-id"), 3146 quantity: $(this).data( "quantity"), 3147 i_id: $(this).data("i_id"), 3148 }, 3149 dataType: 'json', 3150 success: function(response){ 3151 3152 theme.cartDrawer(response); 3153 $('#CartTemplate').removeClass('is-loading'); 3154 3155 if (window.checkProductProperties !== undefined){ 3156 window.checkProductProperties(); 3157 } 3158 }, 3159 error: function(xhr){ 3160 console.log('error',xhr); 3161 $('#CartTemplate').removeClass('is-loading'); 3162 } 3163 }); 3164 3165 }); 3166 3167 3168 $('body').on("click", "#applycode",function() { 3169 3170 if($("input[name='voucher_code']").val() != '') { 3171 3172 $('#CartTemplate').addClass('is-loading'); 3173 3174 $.ajax({ 3175 type: 'POST', 3176 url: '/new_cart/voucher', 3177 data: { 3178 voucher_code: $("input[name='voucher_code']").val(), 3179 category: 'create' 3180 }, 3181 dataType: 'json', 3182 success: function(response){ 3183 3184 // console.log(response); 3185 3186 if(response.error != undefined){ 3187 3188 if(response.error.message != undefined) popToast(response.error.message); 3189 3190 $("input[name='voucher_code']").val('') 3191 3192 } 3193 3194 if(response.cart_content != undefined) theme.cartDrawer(response); 3195 3196 3197 $('#CartTemplate').removeClass('is-loading'); 3198 3199 }, 3200 error: function(xhr){ 3201 console.log('error',xhr); 3202 $('#CartTemplate').removeClass('is-loading'); 3203 } 3204 }); 3205 3206 } 3207 3208 }); 3209 3210 3211 $("body").on("click", ".remove_voucher_btn", function() { 3212 $('#CartTemplate').addClass('is-loading'); 3213 $.ajax({ 3214 type: 'DELETE', 3215 url: '/new_cart/voucher', 3216 data: { 3217 category: 'remove', 3218 order_discount_id: $(this).data( "discount-id") 3219 }, 3220 dataType: 'json', 3221 success: function(data){ 3222 // console.log(data); 3223 theme.cartDrawer(data); 3224 $('#CartTemplate').removeClass('is-loading'); 3225 }, 3226 error: function(xhr){ 3227 console.log('error',xhr); 3228 $('#CartTemplate').removeClass('is-loading'); 3229 } 3230 }); 3231 3232 }); 3233 3234 3235 theme.cartDrawer = function(data){ 3236 3237 $('#CartDrawer').attr('data-fetch', 1); 3238 $('#CartTemplate').addClass('is-loading'); 3239 3240 3241 if(typeof data.cart_content == 'string'){ 3242 $('#CartTemplate').html(data.cart_content); 3243 } 3244 3245 let cart_item_count = data.item_count || data.cart.item_count; 3246 3247 if(cart_item_count > 0){ 3248 $('.cart-count').removeClass('hidden-count'); 3249 }else{ 3250 $('.cart-count').addClass('hidden-count'); 3251 } 3252 3253 $('.cart-count').text(cart_item_count); 3254 $('#CartTemplate').removeClass('is-loading'); 3255 $(".cart-drawer-content").animate({ scrollTop: 0 }); 3256 3257 if(window.EasyStore != undefined && window.EasyStore.Promotion != undefined && window.EasyStore.Promotion.updateCartPromotion != undefined) window.EasyStore.Promotion.updateCartPromotion() 3258 3259 } 3260 3261 theme.fetchCartDrawer = function(data){ 3262 $('#CartTemplate').addClass('is-loading'); 3263 $.ajax({ 3264 url: '/new_cart?retrieve=true', 3265 type: 'GET', 3266 success: function(data, status) { 3267 // console.log(data); 3268 theme.cartDrawer(data); 3269 3270 $('#CartTemplate').removeClass('is-loading'); 3271 3272 if (window.checkProductProperties !== undefined){ 3273 window.checkProductProperties(); 3274 } 3275 }, 3276 error: function(XMLHttpRequest, textStatus) { 3277 console.log('error',XMLHttpRequest,textStatus); 3278 $('#CartTemplate').removeClass('is-loading'); 3279 } 3280 }); 3281 } 3282 3283 theme.updateCartDrawer = function(data){ 3284 $('#CartTemplate').addClass('is-loading'); 3285 3286 $.ajax({ 3287 url: '/new_cart/update', 3288 type: 'PUT', 3289 dataType: 'json', 3290 data: $('#CartDrawer form').serialize(), 3291 success: function(data, status) { 3292 theme.cartDrawer(data); 3293 3294 if (window.checkProductProperties !== undefined){ 3295 window.checkProductProperties(); 3296 } 3297 }, 3298 error: function(XMLHttpRequest, textStatus) { 3299 console.log('error',XMLHttpRequest,textStatus); 3300 } 3301 }); 3302 } 3303 3304 function debounce(func, wait, immediate) { 3305 var timeout; 3306 return function() { 3307 var context = this, args = arguments; 3308 var later = function() { 3309 timeout = null;
3310 if (!immediate) func.apply(context, args); 3311 }; 3312 var callNow = immediate && !timeout; 3313 clearTimeout(timeout); 3314 timeout = setTimeout(later, wait); 3315 if (callNow) func.apply(context, args); 3316 }; 3317 }; 3318 3319 $('body').on("change", 'input.cart__quantity-selector', function (){ 3320 theme.updateCartDrawer(); 3321 }); 3322 3323 3324 $('#updateCartDrawer').click(function() { 3325 theme.updateCartDrawer(); 3326 }); 3327 3328 $('body').on("click", ".btn-qty-adjust", function() { 3329 3330 var $button = $(this); 3331 var oldValue = $button.parent().find("input.cart__quantity-selector").val(); 3332 3333 if ($button.attr('data-adjust') == 1) { 3334 var newVal = parseFloat(oldValue) + 1; 3335 } else { 3336 // Don't allow decrementing below zero 3337 if (oldValue > 0) { 3338 var newVal = parseFloat(oldValue) - 1; 3339 } else { 3340 newVal = 0; 3341 } 3342 } 3343 3344 $button.parent().find("input").val(newVal); 3345 }); 3346 3347 $('body').on("click", ".btn-qty-adjust", debounce(function() { 3348 theme.updateCartDrawer(); 3349 },350)); 3350 3351 $('button.checkout').click(function() { 3352 $(this).addClass('btn--loading'); 3353 }); 3354 3355 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>'; 3356 add_cart_success_html += 'Added to cart <br><a class="CartDrawerTrigger">View cart</a>'; 3357 3358 function popToast(content) { 3359 var x = document.getElementById("toast"), 3360 y = document.getElementById("toastContent"); 3361 3362 y.innerHTML = content; 3363 x.className += " show"; 3364 3365 var hideToast = setTimeout(function(){ x.className = x.className.replace(" show", ""); }, 3000); 3366 } 3367 3368</script>
3368 3369 3370<link href="/assets/css/vouchers.css?v1.3" rel="stylesheet" type="text/css" media="screen" /> 3371<link href="/assets/account/vouchers/vouchers.css" rel="stylesheet" type="text/css" media="screen" /> 3372<link href="/assets/account/vouchers/voucher-widget.css" rel="stylesheet" type="text/css" media="screen" />
3373<script src="/assets/js/promotion/vouchers.js?v1.4" type="text/javascript" ></script>
vendor: 1 bytes, line 3373
3373
3374<script src="/assets/account/vouchers/voucher-widget.js" type="text/javascript" ></script>
3374 3375 3376<vouchers-modal> 3377 <div id="vouchers-modal-backdrop" class="vouchers-modal__close"></div> 3378 <div class="vouchers-modal-wrapper page-width"> 3379 <div id="vouchers-modal" class="vouchers-modal focus-inset" aria-modal="true" role="dialog" tabindex="-1"> 3380 <div class="vouchers-modal__header"> 3381 <div class="vouchers-modal__heading">Vouchers</div> 3382 <button type="button" class="vouchers-modal__close modal__close-button link link--text focus-inset" aria-label="accessibility.close"> 3383 <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"> 3384 <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"> 3385 </path> 3386 </svg> 3387 </button> 3388 </div> 3389 3390 <discount-input> 3391 <div class="field"> 3392 <input type="text" id="input-discount_code" class="search__input field__input" name="voucher_code" placeholder="Discount code"> 3393 <button type="button" name="apply" class="btn btn--secondary button button--secondary">Apply</button> 3394 </div> 3395 <div class="form__message hidden" tabindex="-1" autofocus> 3396 <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-error " viewBox="0 0 13 13"> 3397 <circle cx="6.5" cy="6.50049" r="5.5" stroke="white" stroke-width="2"></circle> 3398 <circle cx="6.5" cy="6.5" r="5.5" fill="#EB001B" stroke="#EB001B" stroke-width="0.7"></circle> 3399 <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> 3400 <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> 3401 </svg> 3402 <div class="js-error-content"></div> 3403 </div> 3404 </discount-input> 3405 <br> 3406 3407 3408 3409 <div class="empty-vouchers_placeholder">No available vouchers</div> 3410 3411 3412 <!-- For voucher widget --> 3413
3413<script type="text/javascript"> 3414 let settings = {"logo_use_image":"1","logo_img":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/8388694.png?width=350&format=webp","footer_logo_img":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/8082524.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\/861942\/f\/8088793.png","header_message":"","header_search_enable":true,"topbar_sticky":"1","footer_quicklinks_enable":true,"footer_quicklinks_linklist":"footer","footer_social_enable":true,"footer_show_credit_card_logo":0,"footer_show_methods_of_payment":0,"footer_visa":true,"footer_master":"1","footer_american_express":true,"footer_jcb":0,"footer_diners_club":0,"footer_discover":0,"footer_ssl":true,"show_footer_lines":"1","home_section_1":"home-content","home_section_2":"featured-product","home_section_3":"parallax-section","home_section_4":"","home_section_5":"","home_section_6":"","featured_title":"","featured_1_img":"https:\/\/cdn.store-assets.com\/s\/278885\/f\/3915939.jpeg?width=650&format=webp","featured_1_text":"DRONE","featured_1_link":"","featured_2_img":"https:\/\/cdn.store-assets.com\/s\/278885\/f\/3915945.jpeg?width=650&format=webp","featured_2_text":"TRAVEL","featured_2_link":"\/collections\/travel-pack","featured_3_img":"https:\/\/cdn.store-assets.com\/s\/278885\/f\/3915949.jpeg?width=650&format=webp","featured_3_text":"ACTION","featured_3_link":"\/collections\/action","featured_4_img":"https:\/\/cdn.store-assets.com\/s\/278885\/f\/3915973.jpeg?width=650&format=webp","featured_4_text":"STYLE","featured_4_link":"\/collections\/style","featured_5_img":"","featured_5_text":"","featured_5_link":"\/collections\/all","featured_6_img":"","featured_6_text":"","featured_6_link":"\/collections\/all","featured_7_img":"","featured_7_text":"","featured_7_link":"","featured_8_img":"","featured_8_text":"","featured_8_link":"","parallax_img":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/8235649.jpeg?width=1500&format=webp","parallax_mobile_img":"","parallax_title":"Company History","parallax_subtitle":"Tip-Top Fruits delivers fruits, vegetables and groceries to hotel, restaurant, food court and other F&B business not only in KL but all across the Klang Valley market. We do this with the fastest speeds and the most reliable delivery. If you are in need of fruits, vegetables and other grocery for your business, you can do no better than to partner with Tip- Top Fruits ...","parallax_button_text":"Why us","parallax_button_link":"\/pages\/about","parallax_full_width":"1","slider_home_auto":"1","slider_home_show_dots":"1","slider_home_rate":"5000","slider_home_transition":"slide","slider_full_screen":"0","slide_1":"1","slide_1_jpg":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/14792189.jpg?width=1500&format=webp","slide_1_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/14792191.jpg?width=900&format=webp","slide_1_link":"https:\/\/wa.me\/60183833772?text=Hello,%20I%20want%20to%20get%20quotation%20of","slide_1_alt":"","slide_1_title":"","slide_1_subtitle":"","slide_1_button_text":"order now!","slide_2":"1","slide_2_jpg":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/14792200.jpg?width=1500&format=webp","slide_2_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/14792202.jpg?width=900&format=webp","slide_2_link":"https:\/\/wa.me\/60183833772?text=Hello,%20I%20want%20to%20get%20quotation%20of","slide_2_alt":"","slide_2_title":"","slide_2_subtitle":"","slide_2_button_text":"get quotation","slide_3":"","slide_3_jpg":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/14792205.jpg?width=1500&format=webp","slide_3_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/14792208.jpg?width=900&format=webp","slide_3_link":"https:\/\/wa.me\/60183833772?text=Hello,%20I%20want%20to%20get%20quotation%20of","slide_3_alt":"","slide_3_title":"","slide_3_subtitle":"","slide_3_button_text":"","slide_4":"","slide_4_jpg":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/14792209.jpg?width=1500&format=webp","
3414slide_4_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/14792210.jpg?width=900&format=webp","slide_4_link":"https:\/\/wa.me\/60183833772?text=Hello,%20I%20want%20to%20get%20quotation%20of","slide_4_alt":"","slide_4_title":"","slide_4_subtitle":"","slide_4_button_text":"","slide_5":"","slide_5_jpg":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/14792211.jpg?width=1500&format=webp","slide_5_mobile_jpg":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/14792212.jpg?width=900&format=webp","slide_5_link":"https:\/\/wa.me\/60183833772?text=Hello,%20I%20want%20to%20get%20quotation%20of","slide_5_alt":"","slide_5_title":"","slide_5_subtitle":"","slide_5_button_text":"","slide_6":"","slide_6_jpg":"","slide_6_mobile_jpg":"","slide_6_link":"","slide_6_alt":"","slide_6_title":"","slide_6_subtitle":"","slide_6_button_text":"","testimonial_slide_img_crop":0,"testimonial_slide_1_img":"https:\/\/cdn.store-assets.com\/s\/278885\/f\/3915980.jpeg?width=1500&format=webp","testimonial_slide_1_title":"Aleksejs Bergmanis","testimonial_slide_1_content":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur non mattis dui, sit amet hendrerit nibh. Duis congue volutpat urna ut accumsan.","testimonial_slide_1_text_link":"Read more","testimonial_slide_1_link":"#","testimonial_slide_2_img":"https:\/\/cdn.store-assets.com\/s\/278885\/f\/3915981.jpeg?width=1500&format=webp","testimonial_slide_2_title":"Thiago Japyassu","testimonial_slide_2_content":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur non mattis dui, sit amet hendrerit nibh. Duis congue volutpat urna ut accumsan. Vivam mauris augue, ultrices at faucibus vitae, mattis eu lacus.","testimonial_slide_2_text_link":"Read more","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":"https:\/\/cdn.store-assets.com\/s\/278885\/f\/3916892.png?width=350&format=webp","logo_list_1_link":"\/collections\/all","logo_list_2_img":"https:\/\/cdn.store-assets.com\/s\/278885\/f\/3916893.png?width=350&format=webp","logo_list_2_link":"\/collections\/all","logo_list_3_img":"https:\/\/cdn.store-assets.com\/s\/278885\/f\/3916894.png?width=350&format=webp","logo_list_3_link":"\/collections\/all","logo_list_4_img":"https:\/\/cdn.store-assets.com\/s\/278885\/f\/3916895.png?width=350&format=webp","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":"Featured products","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.easystore.blue\/s\/201\/f\/5590.png?width=150&format=webp","footer_bar_icon_1_text":"Home","footer_bar_icon_1_link":"\/","footer_bar_icon_2":"https:\/\/cdn.easystore.blue\/s\/201\/f\/5591.png?width=150&format=webp","footer_bar_icon_2_text":"All products","footer_bar_icon_2_link":"\/collections\/all","footer_bar_icon_3":"https:\/\/cdn.store-assets.com\/s\/861942\/f\/8317616.png?width=150&format=webp","footer_bar_icon_3_text":"Promotion","footer_bar_icon_3_link":"\/collections\/promotion","footer_bar_icon_4":"https:\/\/cdn.easystore.blue\/s\/201\/f\/5593.png?width=150&format=webp","footer_bar_icon_4_text":"Account","footer_bar_icon_4_link":"\/account\/login","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":"https:\/\/www.facebook.com\/","twitter_url":"","pinterest_url":"","instagram_url":"https:\/\/instagram.com\/","tumblr_url":"","youtube_url":"https:\/\/www.youtube.com\/","vimeo_url":"","wechat_url":"https:\/\/www.wechat.com\/","whatsapp_url":"https:\/\/whatsapp.com\/","line_url":"","featured_blog":"","featured_blog_title":"Blog","articles_handle_1":"","articles_handle_2":"","articles_handle_3":"","promotion_uis":{"primary_color":"#F56F00","header_bg_color":"#F56F00","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-08-18T19:01:58.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} 3415 if (settings.promotion_uis.voucher_widget != null) { 3416 setVoucherTheme(settings.promotion_uis.voucher_widget) 3417 } 3418 var shop = { 3419 money_prefix: "", 3420 format_decimals: "" 3421 }; 3422 var _getEntitlementTranslation = { 3423 "free_shipping": "FREE SHIPPING", 3424 "free_of_charge": "FREE GIFT", 3425 } 3426 var _getTargetTypeTranslation = { 3427 "amount_credit": " CREDIT", 3428 "amount_off": " OFF", 3429 } 3430 var _getPrerequisiteTranslation = { 3431 "min_quantity": "Min formatValue item(s) purchase", 3432 "every_quantity": "Every formatValue item(s) purchase", 3433 "min_amount": "Min formatCurrency spend", 3434 "every_amount": "Every formatCurrency spend" 3435 } 3436 var _getPrerequisiteConditionTranslation = { 3437 "selected_items": "Selected Items", 3438 "selected_collections": "Selected Collections", 3439 "storewide": "Storewide", 3440 "order_subtotal": "Order Subtotal" 3441 } 3442 var _getVoucherButtonTextTranslation = { 3443 "apply": "Apply", 3444 } 3445 var _getVoucherErrorTranslation = { 3446 "condition_not_matched": "Voucher condition not matched" 3447 } 3448 </script>
3448 3449 3450 </div> 3451 </div> 3452</vouchers-modal> 3453 3454 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"> 3455<a href="https://api.whatsapp.com/send/?phone=60183833772&text&app_absent=0" 3456 style="position:fixed; 3457 width:45px; 3458 height:45px; 3459 bottom:60px; 3460 left:40px; 3461 background-color:#25d366; 3462 margin-left: -15px; 3463 background-size: 200px 200px; 3464 background-position:top 6px; 3465 background-repeat: no-repeat; 3466 color:#FFF; 3467 border-radius:50px; 3468 text-align:center; 3469 font-size:30px; 3470 box-shadow: 2px 2px 3px #999; 3471 z-index:100;" target="_blank"> 3472 <div style="margin-top:-2px;margin-right:-1px;"> 3473 <i class="fa fa-whatsapp"></i> 3474 </div> 3475</a> 3476</body> 3477</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.