PageSourceSearch

https://www.jmaker.com.tw/account/login

html jmaker.com.tw collected 2026-09-26 04:28:17 UTC 130,187 bytes, 4,113 lines download raw bytes

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<meta name="google-site-verification" content="BzRLXgHykvDBX1-1Ie1CB3uLoCw1NLShEcprYqywvxo" />
14
15  
16  <link rel="icon" href="https://cdn.store-assets.com/s/236824/f/1140397.png" />
17  
18
19  <!-- Title and description ================================================== -->
20  <title>
21  登入 &ndash; 傑森創工 - 網路商店 - Arduino、ESP32的專家,創客的好朋友
22  </title>
23
24  
25
26  <!-- Social meta ================================================== -->
27  
28
29  <meta property="og:type" content="website">
30  <meta property="og:title" content="登入">
31  <meta property="og:url" content="https://www.jmaker.com.tw/account/login">
32  
33  <meta property="og:image" content="https://cdn.store-assets.com/s/236824/f/16676111.png?width=350&format=webp">
34  <meta property="og:image:secure_url" content="https://cdn.store-assets.com/s/236824/f/16676111.png?width=350&format=webp">
35  
36
37
38<meta property="og:description" content="傑森創工,專注於Arduino、ESP32、樹莓派(Raspberry Pi)、物聯網、創客(Maker)相關商品的研究,專業銷售Arduino材料、Arduino教材、各種電子材料、開發板、Arduino套件、感測器模組,以及各類工具。更提供許多獨家的專題套件,供大學或高中職學生製作Arduino、ESP32專題。最專業的Arduino、ESP32供應商。">
39<meta property="og:site_name" content="傑森創工 - 網路商店 - Arduino、ESP32的專家,創客的好朋友">
40
41
42
43  <meta name="twitter:card" content="summary">
44
45
46
47
48
49
50
51  <!-- Helpers ================================================== -->
52  <link rel="canonical" href="https://www.jmaker.com.tw/account/login">
53  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=3.0">
54  <meta name="theme-color" content="">
55
56  <!-- CSS ================================================== -->
57  <link href="https://store-themes.easystore.co/236824/themes/2877/assets/timber.css?t=1787072460" rel="stylesheet" type="text/css" media="screen" />
58  <link href="https://store-themes.easystore.co/236824/themes/2877/assets/theme.css?t=1787072460" rel="stylesheet" type="text/css" media="screen" />
59
60  
61
62
63
64<link href="https://fonts.googleapis.com/css?family=Rajdhani:400,600&display=swap" rel="stylesheet">
65
66
67  
67<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" type="text/javascript" ></script>
67
68  <!-- Header hook for plugins ================================================== -->
69  
70<!-- ScriptTags -->
71<script>window.__st={p: "customers",cid: null,cem: null,cph: null,cfn: null,cln: null,cge: null,cdb: null,ccc: null};</script>
71<script src='/assets/events.js'></script>
71<script>(function(){function asyncLoad(){var urls=['/assets/traffic.js?v=1','https://apps.easystore.co/facebook-login/script.js?shop=jason080.easy.co','https://apps.easystore.co/mobile-messaging-share/script.js?shop=jason080.easy.co','https://apps.easystore.co/social-media-share/script.js?shop=jason080.easy.co','https://apps.easystore.co/marketplace/shopee-taiwan/script.js?shop=jason080.easy.co','https://apps.easystore.co/google-analytics/script.js?shop=jason080.easy.co'];for(var i=0;i<urls.length;i++){var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=urls[i];var x=document.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);}}window.attachEvent ? window.attachEvent('onload', asyncLoad) : window.addEventListener('load', asyncLoad, false);})();</script>
71
72<!-- /ScriptTags -->
73
74
75  
76<!--[if lt IE 9]>
77<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js" type="text/javascript" ></script>
vendor: 2 bytes, line 77
77
78<script src="https://store-themes.easystore.co/236824/themes/2877/assets/respond.min.js?t=1787072460" type="text/javascript" ></script>
78
79<link href="https://store-themes.easystore.co/236824/themes/2877/assets/respond-proxy.html" id="respond-proxy" rel="respond-proxy" />
80<link href="//www.jmaker.com.tw/search?q=69e0d300b869267cd20fa0b544e25d94" id="respond-redirect" rel="respond-redirect" />
81<script src="//www.jmaker.com.tw/search?q=69e0d300b869267cd20fa0b544e25d94" type="text/javascript"></script>
81
82<![endif]-->
83
84
85
86  
86<script src="https://store-themes.easystore.co/236824/themes/2877/assets/modernizr.min.js?t=1787072460" type="text/javascript" ></script>
86
87
88  
89  
90    
90<script src="/assets/shop_common.js" type="text/javascript" ></script>
90
91    
91<script src="/assets/customer_area.js" type="text/javascript" ></script>
91
92  
93  
93<script>
94  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
95  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
96  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
97  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
98
99  ga('create', '', 'auto','myTracker');
100  ga('myTracker.send', 'pageview');
101
102  </script>
102
103  
104<!-- Snippet:global/head: 蝦皮購物 Shopee Taiwan -->
105<link type="text/css" rel="stylesheet" href="https://apps.easystore.co/assets/css/marketplace/main.css?v1.7">
106<!-- /Snippet -->
107
108<!-- Snippet:global/head: Site Verification -->
109<meta name="google-site-verification" content="BzRLXgHykvDBX1-1Ie1CB3uLoCw1NLShEcprYqywvxo" />
110<!-- /Snippet -->
111
112</head>
113
114<body id="------" class="template-customers  " >
115
116  <ul id="MobileNav" class="mobile-nav">
117  
118  <li class="mobile-nav_icon-x">
119    
120      
121
122
123  	
124  	<span class="MobileNavTrigger icon icon-x"></span>
125  </li>
126  
127  
128  <li class="mobile-nav__link" aria-haspopup="true">
129    
130    <a href="/" >
131      首頁
132    </a>
133    
134  </li>
135  
136  
137  <li class="mobile-nav__link" aria-haspopup="true">
138    
139    
140    <a href="/collections/all" class="mobile-nav__parent-link">
141      商品類別
142    </a>
143    <span class="mobile-nav__sublist-trigger">
144      <span class="icon-fallback-text mobile-nav__sublist-expand">
145  <span class="icon icon-plus" aria-hidden="true"></span>
146  <span class="fallback-text">+</span>
147</span>
148<span class="icon-fallback-text mobile-nav__sublist-contract">
149  <span class="icon icon-minus" aria-hidden="true"></span>
150  <span class="fallback-text">-</span>
151</span>
152
153    </span>
154    <ul class="mobile-nav__sublist">
155      
156      
157      <li class="mobile-nav__sublist-link" aria-haspopup="true">
158        
159        <a href="/collections/hot-sale" >
160          熱銷新品
161        </a>
162        
163      </li>
164      
165      
166      <li class="mobile-nav__sublist-link" aria-haspopup="true">
167        
168        <a href="/collections/arduino-boards" >
169          Arduino 開發板
170        </a>
171        
172      </li>
173      
174      
175      <li class="mobile-nav__sublist-link" aria-haspopup="true">
176        
177        <a href="/collections/擴展板" >
178          Arduino 擴展板
179        </a>
180        
181      </li>
182      
183      
184      <li class="mobile-nav__sublist-link" aria-haspopup="true">
185        
186        <a href="/collections/arduino-projects" >
187          Arduino 開發套件
188        </a>
189        
190      </li>
191      
192      
193      <li class="mobile-nav__sublist-link" aria-haspopup="true">
194        
195        <a href="/collections/各類感測器" >
196          各類感測器
197        </a>
198        
199      </li>
200      
201      
202      <li class="mobile-nav__sublist-link" aria-haspopup="true">
203        
204        <a href="/collections/樹莓派開發板" >
205          樹莓派開發板
206        </a>
207        
208      </li>
209      
210      
211      <li class="mobile-nav__sublist-link" aria-haspopup="true">
212        
213        <a href="/collections/樹莓派" >
214          樹莓派週邊商品
215        </a>
216        
217      </li>
218      
219      
220      <li class="mobile-nav__sublist-link" aria-haspopup="true">
221        
222        <a href="/collections/esp8266開發板" >
223          ESP8266開發板
224        </a>
225        
226      </li>
227      
228      
229      <li class="mobile-nav__sublist-link" aria-haspopup="true">
230        
231        <a href="/collections/micro-bit相關商品" >
232          micro:bit相關商品
233        </a>
234        
235      </li>
236      
237      
238      <li class="mobile-nav__sublist-link" aria-haspopup="true">
239        
240        <a href="/collections/esp32" >
241          ESP32開發板
242        </a>
243        
244      </li>
245      
246      
247      <li class="mobile-nav__sublist-link" aria-haspopup="true">
248        
249        <a href="/collections/保護外殼" >
250          保護外殼
251        </a>
252        
253      </li>
254      
255      
256      <li class="mobile-nav__sublist-link" aria-haspopup="true">
257        
258        <a href="/collections/ic-零件" >
259          IC 零件
260        </a>
261        
262      </li>
263      
264      
265      <li class="mobile-nav__sublist-link" aria-haspopup="true">
266        
267        <a href="/collections/lcd-oled" >
268          LCD OLED 顯示器
269        </a>
270        
271      </li>
272      
273      
274      <li class="mobile-nav__sublist-link" aria-haspopup="true">
275        
276        <a href="/collections/led-發光二極體" >
277          LED 發光二極體
278        </a>
279        
280      </li>
281      
282      
283      <li class="mobile-nav__sublist-link" aria-haspopup="true">
284        
285        <a href="/collections/杜邦線-麵包線-排針-麵包板" >
286          杜邦線 麵包線 排針 麵包板
287        </a>
288        
289      </li>
290      
291      
292      <li class="mobile-nav__sublist-link" aria-haspopup="true">
293        
294        <a href="/collections/智慧車-循跡-避障" >
295          智慧車 循跡 避障
296        </a>
297        
298      </li>
299      
300      
301      <li class="mobile-nav__sublist-link" aria-haspopup="true">
302        
303        <a href="/collections/電表-測量工具" >
304          電表、測量工具
305        </a>
306        
307      </li>
308      
309      
310      <li class="mobile-nav__sublist-link" aria-haspopup="true">
311        
312        <a href="/collections/外殼-平台" >
313          外殼 平台
314        </a>
315        
316      </li>
317      
318      
319      <li class="mobile-nav__sublist-link" aria-haspopup="true">
320        
321        <a href="/collections/馬達-輪胎-水泵-驅動板" >
322          馬達 輪胎 水泵 驅動板
323        </a>
324        
325      </li>
326      
327      
328      <li class="mobile-nav__sublist-link" aria-haspopup="true">
329        
330        <a href="/collections/繼電器-升降壓模組" >
331          繼電器 升降壓模組
332        </a>
333        
334      </li>
335      
336      
337      <li class="mobile-nav__sublist-link" aria-haspopup="true">
338        
339        <a href="/collections/藍芽-bluetooth-模組" >
340          藍牙 Bluetooth 模組
341        </a>
342        
343      </li>
344      
345      
346      <li class="mobile-nav__sublist-link" aria-haspopup="true">
347        
348        <a href="/collections/電子羅盤-gy系列" >
349          電子羅盤 GY系列
350        </a>
351        
352      </li>
353      
354      
355      <li class="mobile-nav__sublist-link" aria-haspopup="true">
356        
357        <a href="/collections/無線模組-wifi" >
358          無線模組 WiFi Lora
359        </a>
360        
361      </li>
362      
363      
364      <li class="mobile-nav__sublist-link" aria-haspopup="true">
365        
366        <a href="/collections/電源供應-各類線材" >
367          電源供應 各類線材 電池盒
368        </a>
369        
370      </li>
371      
372      
373      <li class="mobile-nav__sublist-link" aria-haspopup="true">
374        
375        <a href="/collections/搖桿-控制器-鍵盤-按鈕" >
376          搖桿 控制器 鍵盤 按鈕
377        </a>
378        
379      </li>
380      
381      
382      <li class="mobile-nav__sublist-link" aria-haspopup="true">
383        
384        <a href="/collections/舵機-servo-伺服馬達" >
385          舵機 Servo 步進 伺服馬達
386        </a>
387        
388      </li>
389      
390      
391      <li class="mobile-nav__sublist-link" aria-haspopup="true">
392        
393        <a href="/collections/手工具" >
394          手工具
395        </a>
396        
397      </li>
398      
399      
400      <li class="mobile-nav__sublist-link" aria-haspopup="true">
401        
402        <a href="/collections/書籍" >
403          書籍
404        </a>
405        
406      </li>
407      
408      
409      <li class="mobile-nav__sublist-link" aria-haspopup="true">
410        
411        <a href="/collections/機械手臂" >
412          機械手臂
413        </a>
414        
415      </li>
416      
417      
418      <li class="mobile-nav__sublist-link" aria-haspopup="true">
419        
420        <a href="/collections/氣體感測" >
421          氣體感測
422        </a>
423        
424      </li>
425      
426      
427      <li class="mobile-nav__sublist-link" aria-haspopup="true">
428        
429        <a href="/collections/usb-ttl-下載器-模組" >
430          USB TTL 下載器 模組
431        </a>
432        
433      </li>
434      
435      
436      <li class="mobile-nav__sublist-link" aria-haspopup="true">
437        
438        <a href="/collections/放大鏡-顯微鏡" >
439          放大鏡、顯微鏡
440        </a>
441        
442      </li>
443      
444      
445      <li class="mobile-nav__sublist-link" aria-haspopup="true">
446        
447        <a href="/collections/各類盒子" >
448          各類盒子
449        </a>
450        
451      </li>
452      
453      
454      <li class="mobile-nav__sublist-link" aria-haspopup="true">
455        
456        <a href="/collections/航模-無人機-零組件" >
457          航模 無人機 零組件
458        </a>
459        
460      </li>
461      
462      
463      <li class="mobile-nav__sublist-link" aria-haspopup="true">
464        
465        <a href="/collections/3d列印" >
466          3D列印
467        </a>
468        
469      </li>
470      
471      
472      <li class="mobile-nav__sublist-link" aria-haspopup="true">
473        
474        <a href="/collections/diy商品" >
475          DIY商品
476        </a>
477        
478      </li>
479      
480      
481      <li class="mobile-nav__sublist-link" aria-haspopup="true">
482        
483        <a href="/collections/燈條相關商品" >
484          燈條相關商品
485        </a>
486        
487      </li>
488      
489      
490      <li class="mobile-nav__sublist-link" aria-haspopup="true">
491        
492        <a href="/collections/epaper" >
493          電子紙 E-Paper
494        </a>
495        
496      </li>
497      
498      
499      <li class="mobile-nav__sublist-link" aria-haspopup="true">
500        
501        <a href="/collections/燈條" >
502          燈條
503        </a>
504        
505      </li>
506      
507      
508      <li class="mobile-nav__sublist-link" aria-haspopup="true">
509        
510        <a href="/collections/arduino專題製作" >
511          Arduino專題製作
512        </a>
513        
514      </li>
515      
516      
517      <li class="mobile-nav__sublist-link" aria-haspopup="true">
518        
519        <a href="/collections/功放板" >
520          功放板
521        </a>
522        
523      </li>
524      
525    </ul>
526    
527  </li>
528  
529  
530  <li class="mobile-nav__link" aria-haspopup="true">
531    
532    <a href="/collections/hot-sale" >
533      熱銷新品
534    </a>
535    
536  </li>
537  
538  
539  <li class="mobile-nav__link" aria-haspopup="true">
540    
541    <a href="/pages/terms-of-service" >
542      購物須知
543    </a>
544    
545  </li>
546  
547  
548  <li class="mobile-nav__link" aria-haspopup="true">
549    
550    <a href="/pages/togo" >
551      倉庫自取須知
552    </a>
553    
554  </li>
555  
556  
557  <li class="mobile-nav__link" aria-haspopup="true">
558    
559    <a href="https://blog.jmaker.com.tw"  target="_blank" >
560      ※教學網站※
561    </a>
562    
563  </li>
564  
565  
566  <li class="mobile-nav__link" aria-haspopup="true">
567    
568    <a href="https://www.facebook.com/geeksfans/"  target="_blank" >
569      臉書粉絲團
570    </a>
571    
572  </li>
573  
574  
575  <li class="mobile-nav__link" aria-haspopup="true">
576    
577    <a href="/pages/about" >
578      公司資訊
579    </a>
580    
581  </li>
582  
583  
584  <li class="mobile-nav__link" aria-haspopup="true">
585    
586    <a href="/a/contact-form" >
587      聯絡我們
588    </a>
589    
590  </li>
591  
592  
593  <li class="mobile-nav__link" aria-haspopup="true">
594    
595    <a href="/pages/學校採購詢價" >
596      學校採購詢價
597    </a>
598    
599  </li>
600  
601  
602  <li class="mobile-nav__link" aria-haspopup="true">
603    
604    <a href="/pages/privacy-wizglyph" >
605      《書境App》隱私權政策 
606    </a>
607    
608  </li>
609  
610
611  
612
613  
614  
615  
616  <li class="mobile-nav__link">
617    <a href="/account/login">登入</a>
618  </li>
619  
620  <li class="mobile-nav__link">
621    <a href="/account/register">註冊</a>
622  </li>
623  
624  
625  
626  
627  <li class="mobile-nav__link header-bar__search-wrapper">
628    
629    <div class="header-bar__module header-bar__search mobile-nav_search">
630      
631  <form action="/search" method="get" class="header-bar__search-form clearfix" role="search">
632    
633    <button type="submit" class="btn icon-fallback-text header-bar__search-submit">
634      <span class="icon icon-search" aria-hidden="true"></span>
635      <span class="fallback-text">搜尋</span>
636    </button>
637    <input type="search" name="q" value="" aria-label="搜尋" class="header-bar__search-input" placeholder="搜尋" autocomplete="off">
638    <div class="dropdown" id="searchDropdown"></div>
639    <input type="hidden" name="search_history" id="search_history">
640  </form>
641
642
643
644
645<script>
646  var _search_history_listings = ""
647  if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings));
648
649  function clearAll() {
650    localStorage.removeItem('searchHistory');
651  
652    var customer = "";
653    if(customer) {
654      // Your logic to clear all data or call an endpoint
655      fetch('/account/search_histories', {
656          method: 'DELETE',
657          headers: {
658            "Content-Type": "application/json",
659            "X-Requested-With": "XMLHttpRequest"
660          },
661          body: JSON.stringify({
662            _token: "Mxneoo9bd7rarPFYwuExk1UUyiYX2u7nOXhKwyji"
663          }),
664      })
665      .then(response => response.json())
666    }
667  }
668  // End - store view history in local storage
669  
670  // search history dropdown  
671  var searchInputs = document.querySelectorAll('input[type=search]');
672  
673  if(searchInputs.length > 0) {
674    
675    searchInputs.forEach((searchInput)=>{
676    
677      searchInput.addEventListener('focus', function() {
678        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
679        searchDropdown.innerHTML = ''; // Clear existing items
680  
681        // retrieve data from local storage
682        var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || [];
683  
684        // Convert JSON to string
685        var search_history_json = JSON.stringify(searchHistoryData);
686  
687        // Set the value of the hidden input
688        searchInput.closest('form').querySelector("#search_history").value = search_history_json;
689  
690        // create dropdown items
691        var clearAllItem = document.createElement('div');
692        clearAllItem.className = 'dropdown-item clear-all';
693        clearAllItem.textContent = 'Clear';
694        clearAllItem.addEventListener('click', function() {
695            clearAll();
696            searchDropdown.style.display = 'none';
697            searchInput.classList.remove('is-focus');
698        });
699        searchDropdown.appendChild(clearAllItem);
700  
701        // create dropdown items
702        searchHistoryData.forEach(function(item) {
703          var dropdownItem = document.createElement('div');
704          dropdownItem.className = 'dropdown-item';
705          dropdownItem.textContent = item.term;
706          dropdownItem.addEventListener('click', function() {
707            searchInput.value = item.term;
708            searchDropdown.style.display = 'none';
709          });
710          searchDropdown.appendChild(dropdownItem);
711        });
712  
713        if(searchHistoryData.length > 0){
714          // display the dropdown
715          searchInput.classList.add('is-focus');
716          document.body.classList.add('search-input-focus');
717          searchDropdown.style.display = 'block';
718        }
719      });
720  
721      searchInput.addEventListener("focusout", (event) => {
722        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
723        searchInput.classList.remove('is-focus');
724        searchDropdown.classList.add('transparent');
725        setTimeout(()=>{
726          searchDropdown.style.display = 'none';
727          searchDropdown.classList.remove('transparent');
728          document.body.classList.remove('search-input-focus');
729        }, 400);
730      });
731    })
732  }
733  // End - search history dropdown
734</script>
734
735    </div>
736    
737  </li>
738  
739  
740</ul>
741<div id="MobileNavOutside" class="mobile-nav-outside"></div>
742
743
744<div id="PageContainer" class="page-container">
745  
746<!-- Snippet:global/body_start: Announcement Bar -->
747<link rel="stylesheet" href="https://apps.easystore.co/assets/css/annoucement-bar/slider.css?v1.01">
748
749<input type="hidden" id="total_announcement_left" name="total_announcement_left" value="1">
750<input type="hidden" id="locale" name="locale" value="zh_TW">
751
752<slider-announcement-bar-app id="announcement-bar" name="announcement-bar" style="
753    border: unset;
754    padding: 4px 0px;
755    margin: 0px;
756    z-index:2999;
757    background:rgb(233, 69, 69);
758    color:rgb(255, 255, 255);
759    
760">
761
762  <div style="
763    display: flex;
764    justify-content: space-between;
765    align-items: center;
766    padding: 0px 0px;
767    border-top: 0px;
768    border-bottom: 0px;
769    border-color: transparent;
770  ">
771    <div style="height: 24px;">
772          </div>
773
774    <ul style="flex-grow: 2; margin: 0px;">
775            <li id="announcement_bar_0" style="
776          display: flex;
777          justify-content: center;
778          align-items: center;
779          flex-wrap: wrap;
780          margin: 0px;
781          width: 100%;
782          word-wrap: break-word;
783        ">
784        學校或公司單位需要大量採購,請來信告知,我們會有專人給您報價!
785                <a class="announcement-bar-button" href="/a/contact-form" style="color: rgb(233, 69, 69); background: rgb(255, 255, 255);">採購詢價</a>
786                        <input type="hidden" id="expired_at_0" name="expired_at_0" value="2021-02-05 00:00">
787      </li>
788          </ul>
789
790    <div style="display: flex;">
791                </div>
792  </div>
793
794
795</slider-announcement-bar-app>
796
797<script>
798  $(function() {
799    var is_top_enabled =  0;
800
801    const loadScript = function(url, callback) {
802      const script = document.createElement("script");
803      script.type = "text/javascript";
804      // If the browser is Internet Explorer.
805      if (script.readyState) {
806        script.onreadystatechange = function() {
807          if (script.readyState == "loaded" || script.readyState == "complete") {
808            script.onreadystatechange = null;
809            callback();
810          }
811        };
812        // For any other browser.
813      } else {
814        script.onload = function() {
815          callback();
816        };
817      }
818      script.src = url;
819      document.getElementsByTagName("head")[0].appendChild(script);
820    };
821
822    const announcementBarAppJS = function($) {
823
824      $('#announcement-close-button').on('click', function() {
825        $('#announcement-bar, #announcement-bar-top').hide();
826        $('#easystore-section-header, .sticky-topbar').css('top', '');
827      });
828    }
829
830    if (typeof jQuery === 'undefined') {
831      loadScript('//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js', function() {
832        jQuery = jQuery.noConflict(true);
833        announcementBarAppJS(jQuery);
834      });
835    } else {
836      announcementBarAppJS(jQuery);
837    }
838
839
840    
841    if(is_top_enabled){
842      // Prevent announcement bar block header
843      setTimeout(()=>{
844        $('#easystore-section-header, .sticky-topbar').css('top', $('#announcement-bar').height()+'px');
845      }, 2000);
846    }
847  });
848
849  setInterval(function() {
850    const total_announcement = "1"
851    var total_announcement_left = $("#total_announcement_left").val();
852
853    for (let i = 0; i <= total_announcement; i++) {
854      const startDate = new Date();
855      const endDateStr = $("#expired_at_" + i).val();
856      const endDate = endDateStr == undefined ? new Date() : new Date(endDateStr.replace(/-/g, "/"));
857      const seconds = (endDate.getTime() - startDate.getTime()) / 1000;
858
859      const days = parseInt(seconds / 86400);
860      const hours = parseInt((seconds % 86400) / 3600);
861      const mins = parseInt((seconds % 86400 % 3600) / 60);
862      const secs = parseInt((seconds % 86400 % 3600) % 60);
863
864      // use to translate countdown unit
865      // (translate based on the preferred language when save announcement bar setting)
866      String.prototype.translate = function() {
867        try {
868          if ($("#locale").val() == "zh_TW") {
869            if (this.toString() === 'day') {
870              return "天";
871            }
872            if (this.toString() === 'hour') {
873              return "小時";
874            }
875            if (this.toString() === 'min') {
876              return "分鐘";
877            }
878            if (this.toString() === 'sec') {
879              return "秒";
880            }
881          } else {
882            if (this.toString() === 'day') {
883              if (days > 0) {
884                return "Days";
885              } else {
886                return "Day";
887              }
888            } else if (this.toString() === 'hour') {
889              if (hours > 0) {
890                return "Hours";
891              } else {
892                return "Hour";
893              }
894            } else if (this.toString() === 'min') {
895              if (mins > 0) {
896                return "Mins";
897              } else {
898                return "Min";
899              }
900            } else if (this.toString() === 'sec') {
901              if (secs > 0) {
902                return "Secs";
903              } else {
904                return "Sec";
905              }
906            }
907          }
908        } catch (error) {
909          console.log("Some errors heres", error);
910        }
911      };
912
913      const announcementBar_countdown = document.getElementById("announcementBar_countdown_" + i);
914      if (announcementBar_countdown && seconds > 0) {
915
916        $(announcementBar_countdown).show()
917        announcementBar_countdown.innerHTML = `
918          <div>
919            ${days} <small>${'day'.translate()}</small>
920          </div>
921          <div>
922            ${hours} <small>${'hour'.translate()}</small>
923          </div>
924          <div>
925            ${mins} <small>${'min'.translate()}</small>
926          </div>
927          <div>
928            ${secs} <small>${'sec'.translate()}</small>
929          </div>
930        `;
931
932
933      } else if (announcementBar_countdown && seconds <= 0) {
934        $("#announcement_bar_" + i).remove();
935        total_announcement_left = total_announcement_left - 1;
936        $("#total_announcement_left").val(total_announcement_left);
937      }
938    }
939
940    showOrHide(total_announcement_left);
941  }, 1000);
942
943
944  function showOrHide(total_announcement_left) {
945    if (total_announcement_left <= 1) {
946      $("#previous-announcement-bar-button,#next-announcement-bar-button").hide();
947    } else {
948      $("#previous-announcement-bar-button,#next-announcement-bar-button").show();
949    }
950
951    if (total_announcement_left == 0) {
952      $("#announcement-close-button").hide();
953      $("#announcement-bar").hide();
954      $('#announcement-bar-top').hide();
955      $('#easystore-section-header, .sticky-topbar').css('top', '');
956    }
957  };
958
959  let annoucementBarAutoMoveInterval = '';
960  class AnnouncementBarAppSlider extends HTMLElement {
961    constructor() {
962      super();
963      this.slider = this.querySelector('ul');
964      this.sliderItems = this.querySelectorAll('li');
965      this.prevButton = this.querySelector('a[name="previous"]');
966      this.nextButton = this.querySelector('a[name="next"]');
967
968      if (!this.slider || !this.nextButton) return;
969
970      const resizeObserver = new ResizeObserver(entries => this.initPages());
971      resizeObserver.observe(this.slider);
972
973      this.slider.addEventListener('scroll', this.update.bind(this));
974      this.prevButton.addEventListener('click', this.onButtonClick.bind(this));
975      this.nextButton.addEventListener('click', this.onButtonClick.bind(this));
976
977
978    }
979
980    initPages() {
981      const sliderItemsToShow = Array.from(this.sliderItems).filter(element => element.clientWidth > 0);
982      this.sliderLastItem = sliderItemsToShow[sliderItemsToShow.length - 1];
983      if (sliderItemsToShow.length === 0) return;
984      this.slidesPerPage = Math.floor(this.slider.clientWidth / sliderItemsToShow[0].clientWidth);
985      this.totalPages = sliderItemsToShow.length - this.slidesPerPage + 1;
986      this.update();
987      let self = this
988      var total_announcement_left = $("#total_announcement_left").val();
989      annoucementBarAutoMoveInterval = setInterval(function() {
990        if (total_announcement_left > 1) {
991          self.moveSlide('next')
992        }
993      }, 5000)
994    }
995
996    update() {
997      this.currentPage = Math.round(this.slider.scrollLeft / this.sliderLastItem.clientWidth) + 1;
998    }
999
1000    onButtonClick(event) {
1001      event.preventDefault();
1002      let self = this;
1003      self.moveSlide(event.currentTarget.name);
1004    }
1005
1006
1007    moveSlide(move_to) {
1008
1009      clearInterval(annoucementBarAutoMoveInterval);
1010      let self = this;
1011      annoucementBarAutoMoveInterval = setInterval(function() {
1012        self.moveSlide('next');
1013      }, 5000)
1014
1015      if (move_to === 'previous' && this.currentPage === 1) {
1016        this.slider.scrollTo({
1017          left: this.sliderLastItem.clientWidth * (this.totalPages - 1)
1018        });
1019      } else if (move_to === 'next' && this.currentPage === this.totalPages) {
1020        this.slider.scrollTo({
1021          left: 0
1022        });
1023      } else {
1024        const slideScrollPosition = move_to === 'next' ? this.slider.scrollLeft + this.sliderLastItem
1025          .clientWidth : this.slider.scrollLeft - this.sliderLastItem.clientWidth;
1026        this.slider.scrollTo({
1027          left: slideScrollPosition
1028        });
1029      }
1030    }
1031
1032  }
1033
1034  customElements.define('slider-announcement-bar-app', AnnouncementBarAppSlider);
1035</script>
1035
1036
1037<!-- /Snippet -->
1038
1039<!-- Snippet:global/body_start: Console Extension -->
1040<div id='es_console' style='display: none;'>236824</div>
1041<!-- /Snippet -->
1042
1043  
1044    <style>
1045  .search-modal__form{
1046    position: relative;
1047  }
1048  
1049  .dropdown-wrapper {
1050    position: relative;
1051  }
1052  
1053  .dropdown-wrapper:hover .dropdown {
1054    display: block;
1055  }
1056  
1057  .header-icon-nav .dropdown {
1058    left: -80px;
1059  }
1060  
1061  .dropdown {
1062    display: none;
1063    position: absolute;
1064    top: 100%;
1065    left: 0px;
1066    width: 100%;
1067    padding: 8px;
1068    background-color: #fff;
1069    z-index: 1000;
1070    border-radius: 5px;
1071    border: 1px solid rgba(var(--color-foreground), 1);
1072    border-top: none;
1073    overflow-x: hidden;
1074    overflow-y: auto;
1075    max-height: 350px;
1076    min-width: 150px;
1077    box-shadow: 0 0 5px rgba(0,0,0,0.1);
1078  }
1079    
1080  .dropdown a{
1081    text-decoration: none;
1082    color: #000 !important;
1083  }
1084  
1085  .dropdown-item {
1086    padding: 0.4rem 2rem;
1087    cursor: pointer;
1088    line-height: 1.4;
1089    overflow: hidden;
1090    text-overflow: ellipsis;
1091    white-space: nowrap;
1092  }
1093  
1094  .dropdown-item:hover{
1095    background-color: #f3f3f3;
1096  }
1097  
1098  .search__input.is-focus{
1099    border-radius: 15px;
1100    border-bottom-left-radius: 0;
1101    border-bottom-right-radius: 0;
1102    border: 1px solid rgba(var(--color-foreground), 1);
1103    border-bottom: none;
1104    box-shadow: none;
1105  }
1106  
1107  .clear-all {
1108    text-align: right;
1109    padding: 0 2rem 0.2rem;
1110    line-height: 1;
1111    font-size: 70%;
1112    margin-bottom: -2px;
1113  }
1114  
1115  .clear-all:hover{
1116    background-color: #fff;
1117  }
1118  
1119  .referral-notification {
1120    position: absolute;
1121    top: 100%;
1122    right: -12px;
1123    background: white;
1124    border: 1px solid #e0e0e0;
1125    border-radius: 8px;
1126    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1127    width: 280px;
1128    z-index: 1000;
1129    padding: 16px;
1130    margin-top: 8px;
1131    font-size: 14px;
1132    line-height: 1.4;
1133  }
1134  
1135  .referral-notification::before {
1136    content: '';
1137    position: absolute;
1138    top: -8px;
1139    right: 20px;
1140    width: 0;
1141    height: 0;
1142    border-left: 8px solid transparent;
1143    border-right: 8px solid transparent;
1144    border-bottom: 8px solid white;
1145  }
1146  
1147  .referral-notification::after {
1148    content: '';
1149    position: absolute;
1150    top: -9px;
1151    right: 20px;
1152    width: 0;
1153    height: 0;
1154    border-left: 8px solid transparent;
1155    border-right: 8px solid transparent;
1156    border-bottom: 8px solid #e0e0e0;
1157  }
1158  
1159  .referral-notification h4 {
1160    margin: 0 0 8px 0;
1161    color: #2196F3;
1162    font-size: 16px;
1163    font-weight: 600;
1164  }
1165  
1166  .referral-notification p {
1167    margin: 0 0 12px 0;
1168    color: #666;
1169  }
1170  
1171  .referral-notification .referral-code {
1172    background: #f5f5f5;
1173    padding: 8px;
1174    border-radius: 4px;
1175    font-family: monospace;
1176    font-size: 13px;
1177    text-align: center;
1178    margin: 8px 0;
1179    border: 1px solid #ddd;
1180  }
1181  
1182  .referral-notification .close-btn {
1183    position: absolute;
1184    top: 8px;
1185    right: 8px;
1186    background: none;
1187    border: none;
1188    font-size: 18px;
1189    color: #999;
1190    cursor: pointer;
1191    padding: 0;
1192    width: 20px;
1193    height: 20px;
1194    line-height: 1;
1195  }
1196  
1197  .referral-notification .close-btn:hover {
1198    color: #333;
1199  }
1200  
1201  .referral-notification .action-btn {
1202    background: #2196F3;
1203    color: white;
1204    border: none;
1205    padding: 8px 16px;
1206    border-radius: 4px;
1207    cursor: pointer;
1208    font-size: 12px;
1209    margin-right: 8px;
1210    margin-top: 8px;
1211  }
1212  
1213  .referral-notification .action-btn:hover {
1214    background: #1976D2;
1215  }
1216  
1217  .referral-notification .dismiss-btn {
1218    background: transparent;
1219    color: #666;
1220    border: 1px solid #ddd;
1221    padding: 8px 16px;
1222    border-radius: 4px;
1223    cursor: pointer;
1224    font-size: 12px;
1225    margin-top: 8px;
1226  }
1227  
1228  .referral-notification .dismiss-btn:hover {
1229    background: #f5f5f5;
1230  }
1231  .referral-modal__dialog {
1232    transform: translate(-50%, 0);
1233    transition: transform var(--duration-default) ease, visibility 0s;
1234    z-index: 10000;
1235    position: fixed;
1236    top: 20vh;
1237    left: 50%;
1238    width: 100%;
1239    max-width: 350px;
1240    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1241    border-radius: 12px;
1242    background-color: #fff;
1243    color: #000;
1244    padding: 20px;
1245    text-align: center;
1246  }
1247  .modal-overlay.referral-modal-overlay {
1248    position: fixed;
1249    top: 0;
1250    left: 0;
1251    width: 100%;
1252    height: 100%;
1253    background-color: rgba(0, 0, 0, 0.7);
1254    z-index: 2001;
1255    display: block;
1256    opacity: 1;
1257    transition: opacity var(--duration-default) ease, visibility 0s;
1258  }
1259</style>
1260
1261<header class="header-bar  sticky-topbar">
1262  <div class="header-bg-wrapper">
1263    <div class="header-wrapper wrapper">
1264      
1265
1266      <div class="logo-header" role="banner">
1267
1268              
1269                    <div class="h1 site-header__logo" itemscope itemtype="http://schema.org/Organization">
1270              
1271                    
1272                        
1273                      	
1274                          <a href="/" class="logo-wrapper" itemprop="url">
1275                            <img src="https://cdn.store-assets.com/s/236824/f/16676111.png?width=350&format=webp" alt="傑森創工 - 網路商店 - Arduino、ESP32的專家,創客的好朋友" itemprop="logo">
1276                          </a>
1277                        
1278
1279                    
1280              
1281                </div>
1282              
1283
1284      </div>
1285
1286      <div class="header-nav-bar medium-down--hide">
1287          
1288<ul class="site-nav large--text-center" id="AccessibleNav">
1289  
1290    
1291    
1292      <li >
1293        <a href="/"  class="site-nav__link">首頁</a>
1294      </li>
1295    
1296  
1297    
1298    
1299      
1300      <li class="site-nav--has-dropdown" aria-haspopup="true">
1301        <a href="/collections/all"  class="site-nav__link">
1302          商品類別
1303          <span class="arrow-icon">
1304            <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>
1305          </span>
1306        </a>
1307        <ul class="site-nav__dropdown">
1308          
1309            
1310            
1311              <li >
1312                <a href="/collections/hot-sale"  class="site-nav__link">熱銷新品</a>
1313              </li>
1314            
1315          
1316            
1317            
1318              <li >
1319                <a href="/collections/arduino-boards"  class="site-nav__link">Arduino 開發板</a>
1320              </li>
1321            
1322          
1323            
1324            
1325              <li >
1326                <a href="/collections/擴展板"  class="site-nav__link">Arduino 擴展板</a>
1327              </li>
1328            
1329          
1330            
1331            
1332              <li >
1333                <a href="/collections/arduino-projects"  class="site-nav__link">Arduino 開發套件</a>
1334              </li>
1335            
1336          
1337            
1338            
1339              <li >
1340                <a href="/collections/各類感測器"  class="site-nav__link">各類感測器</a>
1341              </li>
1342            
1343          
1344            
1345            
1346              <li >
1347                <a href="/collections/樹莓派開發板"  class="site-nav__link">樹莓派開發板</a>
1348              </li>
1349            
1350          
1351            
1352            
1353              <li >
1354                <a href="/collections/樹莓派"  class="site-nav__link">樹莓派週邊商品</a>
1355              </li>
1356            
1357          
1358            
1359            
1360              <li >
1361                <a href="/collections/esp8266開發板"  class="site-nav__link">ESP8266開發板</a>
1362              </li>
1363            
1364          
1365            
1366            
1367              <li >
1368                <a href="/collections/micro-bit相關商品"  class="site-nav__link">micro:bit相關商品</a>
1369              </li>
1370            
1371          
1372            
1373            
1374              <li >
1375                <a href="/collections/esp32"  class="site-nav__link">ESP32開發板</a>
1376              </li>
1377            
1378          
1379            
1380            
1381              <li >
1382                <a href="/collections/保護外殼"  class="site-nav__link">保護外殼</a>
1383              </li>
1384            
1385          
1386            
1387            
1388              <li >
1389                <a href="/collections/ic-零件"  class="site-nav__link">IC 零件</a>
1390              </li>
1391            
1392          
1393            
1394            
1395              <li >
1396                <a href="/collections/lcd-oled"  class="site-nav__link">LCD OLED 顯示器</a>
1397              </li>
1398            
1399          
1400            
1401            
1402              <li >
1403                <a href="/collections/led-發光二極體"  class="site-nav__link">LED 發光二極體</a>
1404              </li>
1405            
1406          
1407            
1408            
1409              <li >
1410                <a href="/collections/杜邦線-麵包線-排針-麵包板"  class="site-nav__link">杜邦線 麵包線 排針 麵包板</a>
1411              </li>
1412            
1413          
1414            
1415            
1416              <li >
1417                <a href="/collections/智慧車-循跡-避障"  class="site-nav__link">智慧車 循跡 避障</a>
1418              </li>
1419            
1420          
1421            
1422            
1423              <li >
1424                <a href="/collections/電表-測量工具"  class="site-nav__link">電表、測量工具</a>
1425              </li>
1426            
1427          
1428            
1429            
1430              <li >
1431                <a href="/collections/外殼-平台"  class="site-nav__link">外殼 平台</a>
1432              </li>
1433            
1434          
1435            
1436            
1437              <li >
1438                <a href="/collections/馬達-輪胎-水泵-驅動板"  class="site-nav__link">馬達 輪胎 水泵 驅動板</a>
1439              </li>
1440            
1441          
1442            
1443            
1444              <li >
1445                <a href="/collections/繼電器-升降壓模組"  class="site-nav__link">繼電器 升降壓模組</a>
1446              </li>
1447            
1448          
1449            
1450            
1451              <li >
1452                <a href="/collections/藍芽-bluetooth-模組"  class="site-nav__link">藍牙 Bluetooth 模組</a>
1453              </li>
1454            
1455          
1456            
1457            
1458              <li >
1459                <a href="/collections/電子羅盤-gy系列"  class="site-nav__link">電子羅盤 GY系列</a>
1460              </li>
1461            
1462          
1463            
1464            
1465              <li >
1466                <a href="/collections/無線模組-wifi"  class="site-nav__link">無線模組 WiFi Lora</a>
1467              </li>
1468            
1469          
1470            
1471            
1472              <li >
1473                <a href="/collections/電源供應-各類線材"  class="site-nav__link">電源供應 各類線材 電池盒</a>
1474              </li>
1475            
1476          
1477            
1478            
1479              <li >
1480                <a href="/collections/搖桿-控制器-鍵盤-按鈕"  class="site-nav__link">搖桿 控制器 鍵盤 按鈕</a>
1481              </li>
1482            
1483          
1484            
1485            
1486              <li >
1487                <a href="/collections/舵機-servo-伺服馬達"  class="site-nav__link">舵機 Servo 步進 伺服馬達</a>
1488              </li>
1489            
1490          
1491            
1492            
1493              <li >
1494                <a href="/collections/手工具"  class="site-nav__link">手工具</a>
1495              </li>
1496            
1497          
1498            
1499            
1500              <li >
1501                <a href="/collections/書籍"  class="site-nav__link">書籍</a>
1502              </li>
1503            
1504          
1505            
1506            
1507              <li >
1508                <a href="/collections/機械手臂"  class="site-nav__link">機械手臂</a>
1509              </li>
1510            
1511          
1512            
1513            
1514              <li >
1515                <a href="/collections/氣體感測"  class="site-nav__link">氣體感測</a>
1516              </li>
1517            
1518          
1519            
1520            
1521              <li >
1522                <a href="/collections/usb-ttl-下載器-模組"  class="site-nav__link">USB TTL 下載器 模組</a>
1523              </li>
1524            
1525          
1526            
1527            
1528              <li >
1529                <a href="/collections/放大鏡-顯微鏡"  class="site-nav__link">放大鏡、顯微鏡</a>
1530              </li>
1531            
1532          
1533            
1534            
1535              <li >
1536                <a href="/collections/各類盒子"  class="site-nav__link">各類盒子</a>
1537              </li>
1538            
1539          
1540            
1541            
1542              <li >
1543                <a href="/collections/航模-無人機-零組件"  class="site-nav__link">航模 無人機 零組件</a>
1544              </li>
1545            
1546          
1547            
1548            
1549              <li >
1550                <a href="/collections/3d列印"  class="site-nav__link">3D列印</a>
1551              </li>
1552            
1553          
1554            
1555            
1556              <li >
1557                <a href="/collections/diy商品"  class="site-nav__link">DIY商品</a>
1558              </li>
1559            
1560          
1561            
1562            
1563              <li >
1564                <a href="/collections/燈條相關商品"  class="site-nav__link">燈條相關商品</a>
1565              </li>
1566            
1567          
1568            
1569            
1570              <li >
1571                <a href="/collections/epaper"  class="site-nav__link">電子紙 E-Paper</a>
1572              </li>
1573            
1574          
1575            
1576            
1577              <li >
1578                <a href="/collections/燈條"  class="site-nav__link">燈條</a>
1579              </li>
1580            
1581          
1582            
1583            
1584              <li >
1585                <a href="/collections/arduino專題製作"  class="site-nav__link">Arduino專題製作</a>
1586              </li>
1587            
1588          
1589            
1590            
1591              <li >
1592                <a href="/collections/功放板"  class="site-nav__link">功放板</a>
1593              </li>
1594            
1595          
1596        </ul>
1597      </li>
1598    
1599  
1600    
1601    
1602      <li >
1603        <a href="/collections/hot-sale"  class="site-nav__link">熱銷新品</a>
1604      </li>
1605    
1606  
1607    
1608    
1609      <li >
1610        <a href="/pages/terms-of-service"  class="site-nav__link">購物須知</a>
1611      </li>
1612    
1613  
1614    
1615    
1616      <li >
1617        <a href="/pages/togo"  class="site-nav__link">倉庫自取須知</a>
1618      </li>
1619    
1620  
1621    
1622    
1623      <li >
1624        <a href="https://blog.jmaker.com.tw"  target="_blank"  class="site-nav__link">※教學網站※</a>
1625      </li>
1626    
1627  
1628    
1629    
1630      <li >
1631        <a href="https://www.facebook.com/geeksfans/"  target="_blank"  class="site-nav__link">臉書粉絲團</a>
1632      </li>
1633    
1634  
1635    
1636    
1637      <li >
1638        <a href="/pages/about"  class="site-nav__link">公司資訊</a>
1639      </li>
1640    
1641  
1642    
1643    
1644      <li >
1645        <a href="/a/contact-form"  class="site-nav__link">聯絡我們</a>
1646      </li>
1647    
1648  
1649    
1650    
1651      <li >
1652        <a href="/pages/學校採購詢價"  class="site-nav__link">學校採購詢價</a>
1653      </li>
1654    
1655  
1656    
1657    
1658      <li >
1659        <a href="/pages/privacy-wizglyph"  class="site-nav__link">《書境App》隱私權政策 </a>
1660      </li>
1661    
1662  
1663  
1664  
1665      
1666        
1667          
1668        
1669          
1670        
1671      
1672  
1673  
1674  
1675</ul>
1676
1677      </div>
1678
1679      <div class="desktop-header-nav medium-down--hide">
1680
1681
1682        <div class="header-subnav">
1683          
1684
1685
1686
1687
1688          <div class="header-icon-nav">
1689
1690                
1691
1692                
1693
1694
1695                
1696                  
1697                    <div class="header-bar__module">
1698                      
1699  <a class="popup-with-form" href="#search-form">
1700    
1701
1702
1703
1704	<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>    
1705
1706  
1707
1708  </a>
1709
1710
1711
1712<!-- form itself -->
1713<div id="search-form" class="white-popup-block mfp-hide popup-search">
1714  <div class="popup-search-content">
1715    <form action="/search" method="get" class="input-group search-bar" role="search">
1716      
1717      <input type="search" name="q" value="" placeholder="搜尋" class="input-group-field" aria-label="搜尋" placeholder="搜尋" autocomplete="off">
1718      <div class="dropdown" id="searchDropdown"></div>
1719      <input type="hidden" name="search_history" id="search_history">
1720      <span class="input-group-btn">
1721        <button type="submit" class="btn icon-fallback-text">
1722          <span class="icon icon-search" aria-hidden="true"></span>
1723          <span class="fallback-text">搜尋</span>
1724        </button>
1725      </span>
1726    </form>
1727  </div>
1728</div>
1729
1730<script src="https://store-themes.easystore.co/236824/themes/2877/assets/magnific-popup.min.js?t=1787072460" type="text/javascript" ></script>
vendor: 1 bytes, line 1730
1730
1731<script>
1732$(document).ready(function() {
1733	$('.popup-with-form').magnificPopup({
1734		type: 'inline',
1735		preloader: false,
1736		focus: '#name',
1737      	mainClass: 'popup-search-bg-wrapper',
1738
1739		// When elemened is focused, some mobile browsers in some cases zoom in
1740		// It looks not nice, so we disable it:
1741		callbacks: {
1742			beforeOpen: function() {
1743				if($(window).width() < 700) {
1744					this.st.focus = false;
1745				} else {
1746					this.st.focus = '#name';
1747				}
1748			}
1749		}
1750	});
1751  	$('.popup-search-content').click(function(event) {
1752      	if($(event.target).attr('class') == "popup-search-content") {
1753          $.magnificPopup.close();
1754        }
1755    });
1756});
1757</script>
1757
1758
1759
1760<script>
1761  var _search_history_listings = ""
1762  if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings));
1763
1764  function clearAll() {
1765    localStorage.removeItem('searchHistory');
1766  
1767    var customer = "";
1768    if(customer) {
1769      // Your logic to clear all data or call an endpoint
1770      fetch('/account/search_histories', {
1771          method: 'DELETE',
1772          headers: {
1773            "Content-Type": "application/json",
1774            "X-Requested-With": "XMLHttpRequest"
1775          },
1776          body: JSON.stringify({
1777            _token: "Mxneoo9bd7rarPFYwuExk1UUyiYX2u7nOXhKwyji"
1778          }),
1779      })
1780      .then(response => response.json())
1781    }
1782  }
1783  // End - store view history in local storage
1784  
1785  // search history dropdown  
1786  var searchInputs = document.querySelectorAll('input[type=search]');
1787  
1788  if(searchInputs.length > 0) {
1789    
1790    searchInputs.forEach((searchInput)=>{
1791    
1792      searchInput.addEventListener('focus', function() {
1793        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
1794        searchDropdown.innerHTML = ''; // Clear existing items
1795  
1796        // retrieve data from local storage
1797        var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || [];
1798  
1799        // Convert JSON to string
1800        var search_history_json = JSON.stringify(searchHistoryData);
1801  
1802        // Set the value of the hidden input
1803        searchInput.closest('form').querySelector("#search_history").value = search_history_json;
1804  
1805        // create dropdown items
1806        var clearAllItem = document.createElement('div');
1807        clearAllItem.className = 'dropdown-item clear-all';
1808        clearAllItem.textContent = 'Clear';
1809        clearAllItem.addEventListener('click', function() {
1810            clearAll();
1811            searchDropdown.style.display = 'none';
1812            searchInput.classList.remove('is-focus');
1813        });
1814        searchDropdown.appendChild(clearAllItem);
1815  
1816        // create dropdown items
1817        searchHistoryData.forEach(function(item) {
1818          var dropdownItem = document.createElement('div');
1819          dropdownItem.className = 'dropdown-item';
1820          dropdownItem.textContent = item.term;
1821          dropdownItem.addEventListener('click', function() {
1822            searchInput.value = item.term;
1823            searchDropdown.style.display = 'none';
1824          });
1825          searchDropdown.appendChild(dropdownItem);
1826        });
1827  
1828        if(searchHistoryData.length > 0){
1829          // display the dropdown
1830          searchInput.classList.add('is-focus');
1831          document.body.classList.add('search-input-focus');
1832          searchDropdown.style.display = 'block';
1833        }
1834      });
1835  
1836      searchInput.addEventListener("focusout", (event) => {
1837        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
1838        searchInput.classList.remove('is-focus');
1839        searchDropdown.classList.add('transparent');
1840        setTimeout(()=>{
1841          searchDropdown.style.display = 'none';
1842          searchDropdown.classList.remove('transparent');
1843          document.body.classList.remove('search-input-focus');
1844        }, 400);
1845      });
1846    })
1847  }
1848  // End - search history dropdown
1849</script>
1849
1850                    </div>
1851                  
1852                
1853
1854
1855
1856
1857                
1858                  <div class="header-bar__module dropdown-wrapper">
1859                    
1860                      <a href="/account/login">
1861
1862
1863
1864    <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>
1865
1866  
1867</a>
1868
1869                      <!-- Referral Notification Popup for Desktop -->
1870                      <div id="referralNotification" class="referral-notification" style="display: none;">
1871                        <button class="close-btn" onclick="dismissReferralNotification()">&times;</button>
1872                        <div style="text-align: center; margin-bottom: 16px;">
1873                          <div style="width: 100px; height: 100px; margin: 0 auto;">
1874                            <img src="https://resources.easystore.co/storefront/icons/channels/vector_referral_program.svg">
1875                          </div>
1876                        </div>
1877                        <p id="referralSignupMessage" style="text-align: center; font-size: 14px; color: #666; margin: 0 0 20px 0;">
1878                          您的好友送您   回饋金!立即註冊領取。
1879                        </p>
1880                        <div style="text-align: center;">
1881                          <button class="btn" onclick="goToSignupPage()" style="width: 100%; color: #fff;">
1882                            註冊
1883                          </button>
1884                        </div>
1885                      </div>
1886                    
1887                  </div>
1888                
1889
1890                <div class="header-bar__module cart-page-link-wrapper">
1891                  <span class="header-bar__sep" aria-hidden="true"></span>
1892                  <a class="CartDrawerTrigger cart-page-link">
1893                    
1894
1895
1896
1897	<svg class="svg-icon" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><title>icon-bag</title><path d="M91.78,93.11,84.17,24.44a3.5,3.5,0,0,0-3.48-3.11H69.06C67.53,10.94,59.57,3,50,3S32.47,10.94,30.94,21.33H19.31a3.5,3.5,0,0,0-3.48,3.11L8.22,93.11A3.49,3.49,0,0,0,11.69,97H88.31a3.49,3.49,0,0,0,3.47-3.89ZM50,10c5.76,0,10.6,4.83,12,11.33H38.05C39.4,14.83,44.24,10,50,10ZM15.6,90l6.84-61.67h8.23v9.84a3.5,3.5,0,0,0,7,0V28.33H62.33v9.84a3.5,3.5,0,0,0,7,0V28.33h8.23L84.4,90Z"/></svg>	
1898
1899  
1900
1901                    <span class="cart-count header-bar__cart-count hidden-count">0</span>
1902                  </a>
1903                </div>
1904
1905          </div>
1906        </div>
1907
1908
1909
1910      </div>
1911      
1912	  <div class="mobile-header-icons large--hide">
1913        
1914        <div class="large--hide">
1915          
1916  <a class="popup-with-form" href="#search-form">
1917    
1918
1919
1920
1921	<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>    
1922
1923  
1924
1925  </a>
1926
1927
1928
1929<!-- form itself -->
1930<div id="search-form" class="white-popup-block mfp-hide popup-search">
1931  <div class="popup-search-content">
1932    <form action="/search" method="get" class="input-group search-bar" role="search">
1933      
1934      <input type="search" name="q" value="" placeholder="搜尋" class="input-group-field" aria-label="搜尋" placeholder="搜尋" autocomplete="off">
1935      <div class="dropdown" id="searchDropdown"></div>
1936      <input type="hidden" name="search_history" id="search_history">
1937      <span class="input-group-btn">
1938        <button type="submit" class="btn icon-fallback-text">
1939          <span class="icon icon-search" aria-hidden="true"></span>
1940          <span class="fallback-text">搜尋</span>
1941        </button>
1942      </span>
1943    </form>
1944  </div>
1945</div>
1946
1947<script src="https://store-themes.easystore.co/236824/themes/2877/assets/magnific-popup.min.js?t=1787072460" type="text/javascript" ></script>
vendor: 1 bytes, line 1947
1947
1948<script>
1949$(document).ready(function() {
1950	$('.popup-with-form').magnificPopup({
1951		type: 'inline',
1952		preloader: false,
1953		focus: '#name',
1954      	mainClass: 'popup-search-bg-wrapper',
1955
1956		// When elemened is focused, some mobile browsers in some cases zoom in
1957		// It looks not nice, so we disable it:
1958		callbacks: {
1959			beforeOpen: function() {
1960				if($(window).width() < 700) {
1961					this.st.focus = false;
1962				} else {
1963					this.st.focus = '#name';
1964				}
1965			}
1966		}
1967	});
1968  	$('.popup-search-content').click(function(event) {
1969      	if($(event.target).attr('class') == "popup-search-content") {
1970          $.magnificPopup.close();
1971        }
1972    });
1973});
1974</script>
1974
1975
1976
1977<script>
1978  var _search_history_listings = ""
1979  if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings));
1980
1981  function clearAll() {
1982    localStorage.removeItem('searchHistory');
1983  
1984    var customer = "";
1985    if(customer) {
1986      // Your logic to clear all data or call an endpoint
1987      fetch('/account/search_histories', {
1988          method: 'DELETE',
1989          headers: {
1990            "Content-Type": "application/json",
1991            "X-Requested-With": "XMLHttpRequest"
1992          },
1993          body: JSON.stringify({
1994            _token: "Mxneoo9bd7rarPFYwuExk1UUyiYX2u7nOXhKwyji"
1995          }),
1996      })
1997      .then(response => response.json())
1998    }
1999  }
2000  // End - store view history in local storage
2001  
2002  // search history dropdown  
2003  var searchInputs = document.querySelectorAll('input[type=search]');
2004  
2005  if(searchInputs.length > 0) {
2006    
2007    searchInputs.forEach((searchInput)=>{
2008    
2009      searchInput.addEventListener('focus', function() {
2010        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
2011        searchDropdown.innerHTML = ''; // Clear existing items
2012  
2013        // retrieve data from local storage
2014        var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || [];
2015  
2016        // Convert JSON to string
2017        var search_history_json = JSON.stringify(searchHistoryData);
2018  
2019        // Set the value of the hidden input
2020        searchInput.closest('form').querySelector("#search_history").value = search_history_json;
2021  
2022        // create dropdown items
2023        var clearAllItem = document.createElement('div');
2024        clearAllItem.className = 'dropdown-item clear-all';
2025        clearAllItem.textContent = 'Clear';
2026        clearAllItem.addEventListener('click', function() {
2027            clearAll();
2028            searchDropdown.style.display = 'none';
2029            searchInput.classList.remove('is-focus');
2030        });
2031        searchDropdown.appendChild(clearAllItem);
2032  
2033        // create dropdown items
2034        searchHistoryData.forEach(function(item) {
2035          var dropdownItem = document.createElement('div');
2036          dropdownItem.className = 'dropdown-item';
2037          dropdownItem.textContent = item.term;
2038          dropdownItem.addEventListener('click', function() {
2039            searchInput.value = item.term;
2040            searchDropdown.style.display = 'none';
2041          });
2042          searchDropdown.appendChild(dropdownItem);
2043        });
2044  
2045        if(searchHistoryData.length > 0){
2046          // display the dropdown
2047          searchInput.classList.add('is-focus');
2048          document.body.classList.add('search-input-focus');
2049          searchDropdown.style.display = 'block';
2050        }
2051      });
2052  
2053      searchInput.addEventListener("focusout", (event) => {
2054        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
2055        searchInput.classList.remove('is-focus');
2056        searchDropdown.classList.add('transparent');
2057        setTimeout(()=>{
2058          searchDropdown.style.display = 'none';
2059          searchDropdown.classList.remove('transparent');
2060          document.body.classList.remove('search-input-focus');
2061        }, 400);
2062      });
2063    })
2064  }
2065  // End - search history dropdown
2066</script>
2066
2067        </div>
2068
2069
2070        <!--  Mobile cart  -->
2071        <div class="large--hide">
2072          <a class="CartDrawerTrigger cart-page-link mobile-cart-page-link">
2073            
2074
2075
2076
2077	<svg class="svg-icon" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><title>icon-bag</title><path d="M91.78,93.11,84.17,24.44a3.5,3.5,0,0,0-3.48-3.11H69.06C67.53,10.94,59.57,3,50,3S32.47,10.94,30.94,21.33H19.31a3.5,3.5,0,0,0-3.48,3.11L8.22,93.11A3.49,3.49,0,0,0,11.69,97H88.31a3.49,3.49,0,0,0,3.47-3.89ZM50,10c5.76,0,10.6,4.83,12,11.33H38.05C39.4,14.83,44.24,10,50,10ZM15.6,90l6.84-61.67h8.23v9.84a3.5,3.5,0,0,0,7,0V28.33H62.33v9.84a3.5,3.5,0,0,0,7,0V28.33h8.23L84.4,90Z"/></svg>	
2078
2079  
2080
2081            <span class="cart-count hidden-count">0</span>
2082          </a>
2083        </div>
2084
2085        <!--  Mobile hamburger  -->
2086        <div class="large--hide">
2087          <a class="mobile-nav-trigger MobileNavTrigger">
2088            
2089
2090
2091
2092    <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>
2093
2094  
2095
2096          </a>
2097        </div>
2098      
2099        
2100          
2101          <!-- Referral Notification Modal for Mobile -->
2102          <details-modal class="referral-modal" id="referralMobileModal">
2103            <details>
2104              <summary class="referral-modal__toggle" aria-haspopup="dialog" aria-label="Open referral modal" style="display: none;">
2105              </summary>
2106              <div class="modal-overlay referral-modal-overlay"></div>
2107              <div class="referral-modal__dialog" role="dialog" aria-modal="true" aria-label="Referral notification">
2108                <div class="referral-modal__content">
2109                  <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;">
2110                    &times;
2111                  </button>
2112
2113                  <div style="margin-bottom: 24px;">
2114                    <div style="width: 120px; height: 120px; margin: 0 auto 20px;">
2115                      <img src="https://resources.easystore.co/storefront/icons/channels/vector_referral_program.svg" style="width: 100%; height: 100%;">
2116                    </div>
2117                  </div>
2118
2119                  <p id="referralSignupMessageMobile" style="font-size: 16px; color: #333; margin: 0 0 30px 0; line-height: 1.5;">
2120                    您的好友送您   回饋金!立即註冊領取。
2121                  </p>
2122
2123                  <button type="button" class="btn" onclick="goToSignupPageFromMobile()" style="width: 100%; color: #fff;">
2124                    註冊
2125                  </button>
2126                </div>
2127              </div>
2128            </details>
2129          </details-modal>
2130          
2131        
2132      
2133      </div>
2134
2135
2136    </div>
2137  </div>
2138</header>
2139
2140
2141
2142
2143
2144
2145    
2146    <main class="wrapper main-content" role="main">
2147      <div class="grid">
2148          <div class="grid__item">
vendor: 100 bytes, lines 2148-2152
2148
2149            
2150  
2151            
2152<script src="https://www.recaptcha.net/recaptcha/enterprise.js?render=
21526LdMNdIqAAAAALegJp7y4weVcCIlnwmIN8TWseEF
vendor: 12 bytes, line 2152
2152"></script>
2153<link rel="preload" href="https://store-themes.easystore.co/236824/themes/2877/assets/customer.css?t=1787072460" as="style" onload="this.onload=null;this.rel='stylesheet'">
2154<style>
2155  main.main-content .field > label{
2156    display: none;
2157  }
2158  .h3{
2159    font-size: 18px;
2160  }
2161  .button--full-width{
2162    width: 100%;
2163  }
2164  .tab-wrapper{
2165    display: inline-flex;
2166    justify-content: center;
2167    align-items: center;
2168    margin: 10px auto 20px;
2169    background-color: #eaeaea;
2170    border-radius: 200px;
2171    padding: 5px;
2172    gap: 10px;
2173  }
2174  .tab-wrapper .tab-label {
2175    display: inline-block;
2176    min-width: 130px;
2177    padding: 8px 15px;
2178    border-radius: 100px;
2179    cursor: pointer;
2180    font-size: 17px;
2181    line-height: 1.1;
2182    user-select: none;
2183    margin: 0;
2184    color: #000;
2185  }
2186  #register-tos a {
2187    display: inline;
2188  }
2189  @media screen and (max-width: 400px){
2190    .tab-wrapper .tab-label {
2191      min-width: 110px;
2192    }
2193  }
2194  .tab-wrapper input[type='radio']:checked + .tab-label {
2195    background-color: #fff;
2196    box-shadow: 2px 2px 25px -10px #333;
2197  }
2198
2199  @media screen and (min-width: 500px){
2200    .large--five-twelfths{
2201      min-width: 420px;
2202    }
2203  }
2204</style>
2205
2206
2207
2208
2209<div class="customer login section-width-control small-width large--five-twelfths text-center wrapper">
2210  <div class="card">
2211    <h1 id="login" tabindex="-1" class="mb-0">
2212      歡迎
2213    </h1>
2214    <p class="h3 mt-0">
2215      
2216        註冊或登入以繼續
2217      
2218    </p>
2219    <div>
2220      
2221
2222      
2223
2224      
2225
2226      
2227
2228      
2229
2230      
2231
2232      
2233
2234      
2235
2236      
2237      <div class="tab-wrapper">
2238        <div>
2239          <input type="radio" name="type" id="tab-register" class="hide hidden" checked>
2240          <label for="tab-register" class="tab-label">
2241            註冊帳號
2242          </label>
2243        </div>
2244        <div>
2245          <input type="radio" name="type" id="tab-login" class="hide hidden">
2246          <label for="tab-login" class="tab-label">
2247            登入
2248          </label>
2249        </div>
2250      </div>
2251      
2252
2253      <form id="form-login" action="/account/auth" method="post" class="mt-2">
2254        <input type="hidden" name="_token" value="Mxneoo9bd7rarPFYwuExk1UUyiYX2u7nOXhKwyji">
2255        <input type="hidden" name="location_id" value="">
2256        <input type="hidden" name="staff_id" value="">
2257        <input type="hidden" id="recaptchaResponse" name="g-recaptcha-response">
2258
2259        
2260        <div id="error-content"></div>
2261
2262        <div class="field">
2263          <input
2264            type="text"
2265            name="customer[email_or_phone]"
2266            id="CustomerDetail"
2267            autocorrect="off"
2268            autocapitalize="off"
2269            placeholder="電子郵件地址"
2270            required
2271          >
2272          <label for="CustomerDetail">
2273            電子郵件地址
2274          </label>
2275        </div>
2276
2277        <button
2278          type="submit"
2279          form="form-login"
2280          class="btn button--full-width g-recaptcha">
2281          繼續
2282        </button>
2283
2284        <div class="button-snippet">
2285          
2286<!-- Snippet:login/button: Facebook Login -->
2287                <style>
2288                    #fb-login-btn.btn{
2289                        background-color: #fff;
2290                        color: #000;
2291                        padding: 0;
2292                        overflow: hidden;
2293                        display: flex;
2294                        justify-content: center;
2295                        align-items: center;
2296                        width: 100%;
2297                        margin: 15px auto;
2298                        font-size: 14px;
2299                        border: 1px solid currentColor;
2300                        box-shadow: none;
2301                    }
2302                    #fb-login-btn.btn:hover{
2303                        background-color: #fff;
2304                    }
2305                    #fb-login-btn.btn svg{
2306                        width: 45px;
2307                        vertical-align: middle;
2308                        padding: 5px;
2309                    }
2310                    #fb-login-btn.btn .fb-login-text{
2311                        padding: 13px 75px 13px 30px;
2312                        display: inline-block;
2313                        width: calc(100% - 52px);
2314                    }
2315                    @media screen and (max-width: 500px) {
2316                      #fb-login-btn.btn .fb-login-text{
2317                        padding: 13px 25px 13px 8px;
2318                        font-size: 13px;
2319                      }
2320                    }
2321                </style>
2322                <button id="fb-login-btn" type="button"  class="btn"  onclick="fb_login()" style="background-color: #fff; color: #000; font-weight: normal;">
2323                  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 700 700"><g><path d="M650,350C650,184.32,515.68,50,350,50S50,184.32,50,350c0,140.69,96.86,258.74,227.53,291.17V441.68H215.66V350h61.87V310.5c0-102.11,46.2-149.44,146.4-149.44,19,0,51.81,3.72,65.22,7.45V251.6c-7.08-.74-19.38-1.12-34.65-1.12-49.2,0-68.2,18.64-68.2,67.08V350h98.1l-16.8,91.68H386.35V647.8C534.88,629.86,650,503.38,650,350Z" fill="#0866ff"/><path d="M467.5,441.68,484.4,350h-98V317.6c0-48.44,19-67.08,68.19-67.08,15.28,0,27.6.37,34.66,1.12V168.51c-13.42-3.73-46.21-7.45-65.22-7.45-100.25,0-146.4,47.33-146.4,149.44V350H2
232315.66v91.68h61.87V641.17a301.61,301.61,0,0,0,108.82,6.63V441.68Z" fill="#fff"/></g></svg>
2324                  <span class="fb-login-text">以 Facebook 帳號繼續</span> 
2325                </button>
2326
2327                
2327<script>
2328                    function fb_login(){
2329                        location.href = 'https://apps.easystore.co/facebook-login/run?domain='+window.location.protocol+'//'+window.location.hostname+'&shop=jason080.easy.co';
2330                    }
2331                </script>
2331
2332<!-- /Snippet -->
2333                
2334        </div>
2335
2336        
2337
2338        <div id="register-tos">
2339          一旦點擊註冊,即表示你同意傑森創工 - 網路商店 - Arduino、ESP32的專家,創客的好朋友的 <a target="_blank" href="/pages/terms-of-service">購物須知</a>。
2340        </div>
2341
2342      </form>
2343    </div>
2344  </div>
2345
2346</div>
2347
2348
2349
2350<script>
2351  const register_tab = document.querySelector('#tab-register');
2352  const login_tab = document.querySelector('#tab-login');
2353  const register_tos = document.querySelector('#register-tos');
2354  const isRegistrationEnabled = "1";
2355
2356  if (register_tab) {
2357    register_tab.addEventListener('click', function() {
2358      if (register_tos) {
2359        register_tos.style.display = 'block';
2360      }
2361    });
2362  }
2363  if (login_tab) {
2364    login_tab.addEventListener('click', function() {
2365      if (register_tos) {
2366        register_tos.style.display = 'none';
2367      }
2368    });
2369  }
2370
2371  const methodSwitchBtn = document.getElementById('phone-login-btn');
2372  if (methodSwitchBtn) {
2373    methodSwitchBtn.onclick = function () {
2374      var type = (register_tab && register_tab.checked) ? 'register' : 'login';
2375      window.location.href = '/account/login?method=phone&type=' + type;
2376    };
2377  }
2378
2379  let lastPathSegment = window.location.pathname.split('/').filter(segment => segment.length > 0).pop();
2380  
2381  // Redirect to login if trying to access register when self registration is disabled
2382  if (!isRegistrationEnabled) {
2383    if (lastPathSegment === 'register') {
2384      window.location.href = '/account/login';
2385    } else if (lastPathSegment === 'login' || lastPathSegment === 'auth') {
2386      if (register_tos) {
2387        register_tos.style.display = 'none';
2388      }
2389    } 
2390  } else {
2391    // Only proceed with tab logic if not redirecting
2392    if(lastPathSegment === 'login') {
2393      if (login_tab) {
2394        login_tab.checked = true;
2395      }
2396      if (register_tos) {
2397        register_tos.style.display = 'none';
2398      }
2399    } else {
2400      if (register_tos) {
2401        register_tos.style.display = 'block';
2402      }
2403    }
2404  }
2405
2406  const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
2407  const phonePattern = /^(?:\+?\d{1,3}[\s-]?)?(?:\d{1,14}[\s-]?){1,5}$/;
2408
2409  let form = document.querySelector('#form-login'),
2410      input = document.querySelector('#CustomerDetail'),
2411      error_content = document.querySelector('#error-content');
2412
2413
2414  // One attempt at a time: the reCAPTCHA wait below is async, so without
2415  // this a double-click starts two continuations and posts the form twice.
2416  var submitting = false;
2417
2418  form.addEventListener('submit', async function (event) {
2419    // preventDefault FIRST: a re-entrant submit must still be cancelled, or the
2420    // browser performs a native post with no captcha token.
2421    event.preventDefault();
2422    if (submitting) return;
2423
2424    let input_value = input.value
2425    error_content.innerHTML = '';
2426    if (!input_value.match(emailPattern) && !input_value.match(phonePattern)) {
2427      error_content.innerHTML = `<div class="errors note">Invalid Email or Phone</div>`;
2428      return false;
2429    }
2430
2431    submitting = true;
2432    document.querySelector('#form-login .btn').classList.add('btn--loading','loading');
2433
2434    // reCAPTCHA is unreachable from some regions (google.com is blocked in
2435    // mainland China). Fail open the same way checkout and forgot-password do:
2436    // submit without a token rather than leave the button spinning forever.
2437    try {
2438      if (window.grecaptcha && typeof window.grecaptcha.enterprise === 'object') {
2439        // The loader defines a stub {ready} synchronously and fetches the real
2440        // implementation asynchronously, so execute() may not exist yet.
2441        // ready() queues until it does; the timeout stops a bundle that never
2442        // arrives from hanging the button.
2443        await new Promise(function (resolve) {
2444          setTimeout(resolve, 3000);
2445          try { grecaptcha.enterprise.ready(resolve); } catch (e) { resolve(); }
2446        });
2447
2448        const token = await grecaptcha.enterprise.execute('6LdMNdIqAAAAALegJp7y4weVcCIlnwmIN8TWseEF', { action: 'LOGIN' });
2449        document.getElementById('recaptchaResponse').value = token;
2450      }
2451    } catch (e) { /* fail open */ }
2452
2453    document.getElementById('form-login').submit();
2454  });
2455
2456
2457</script>
2457
2458
2459  
2460            
2461          </div>
2462      </div>
2463      
2464      
2465  
2466    </main>
2467  
2468    <footer class="site-footer small--text-center" role="contentinfo">
2469      
2470      
2471      
2472      <div class="wrapper">
2473  
2474        <div class="grid-uniform">
2475  
2476          
2477          
2478          
2479          
2480          
2481          
2482            
2483          
2484          
2485          
2486  
2487          
2488              
2489            
2490  
2491          
2492      
2493          
2494          
2495          <div class="grid__item large--one-half ">
2496            <a href="/" class="logo-wrapper" itemprop="url" >
2497              
2498                <img style="max-width: 250px" src="https://cdn.store-assets.com/s/236824/f/1140401.png?width=350&format=webp" alt="傑森創工 - 網路商店 - Arduino、ESP32的專家,創客的好朋友" itemprop="logo">
2499              
2500            </a>
2501            <p class="site-footer__links">Copyright 2026 ©   傑森創工  JMaker Workshop</p>
2502          </div>
2503          
2504          
2505  
2506          
2507            <div class="grid__item large--one-half">
2508              <h4>關注我們</h4>
2509                
2510                <ul class="inline-list social-icons">
2511  
2512  
2513    <li>
2514      <a class="icon-fallback-text" href="https://www.facebook.com/geeksfans/" title="傑森創工 - 網路商店 - Arduino、ESP32的專家,創客的好朋友在Facebook上" target="_blank">
2515        
2516
2517
2518
2519    <svg xmlns="http://www.w3.org/2000/svg" class="facebook-icon-svg social-icon-svg" viewBox="0 0 1024 1024">
2520        <title>icon-facebook</title>
2521        <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"/>
2522    </svg>
2523
2524  
2525
2526        <span class="fallback-text">Facebook</span>
2527      </a>
2528    </li>
2529  
2530  
2531  
2532  
2533  
2534    <li>
2535      <a class="icon-fallback-text" href="https://www.youtube.com/channel/UC81gFCuXzmRt6HVvAiPBpcA" title="傑森創工 - 網路商店 - Arduino、ESP32的專家,創客的好朋友在YouTube上" target="_blank">
2536        
2537
2538
2539
2540    <svg xmlns="http://www.w3.org/2000/svg" class="youtube-icon-svg social-icon-svg" viewBox="0 0 1024 1024">
2541        <title>icon-youtube</title>
2542        <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"/>
2543    </svg>
2544
2545  
2546
2547        <span class="fallback-text">YouTube</span>
2548      </a>
2549    </li>
2550  
2551  
2552  
2553  
2554  
2555  
2556    <li>
2557      <a class="icon-fallback-text" href="https://blog.jmaker.com.tw/" title="傑森創工 - 網路商店 - Arduino、ESP32的專家,創客的好朋友在RSS上" target="_blank">
2558        <span class="icon icon-rss" aria-hidden="true"></span>
2559        <span class="fallback-text">RSS</span>
2560      </a>
2561    </li>
2562  
2563  
2564</ul>
2565
2566            </div>
2567          
2568        </div>
2569  
2570        <hr class="hr--small hr--clear">
2571  
2572        
2573          <div class="grid">
2574            
2575             <div class="grid__item text-center">
2576               <ul class="inline-list payment-icons">
2577                  
2578                    <li>
2579                      <span class="icon-fallback-text">
2580                        <span class="icon icon-visa" aria-hidden="true"></span>
2581                        <span class="fallback-text">Visa</span>
2582                      </span>
2583                    </li>
2584                  
2585                  
2586                    <li>
2587                      <span class="icon-fallback-text">
2588                        <span class="icon icon-master" aria-hidden="true"></span>
2589                        <span class="fallback-text">Master</span>
2590                      </span>
2591                    </li>
2592                  
2593                  
2594                  
2595                  
2596                  
2597               </ul>
2598             </div>
2599             
2600             
2601           
2602           </div>
2603         
2604  
2605         <div class="grid">
2606           <div class="grid__item text-center">
2607             
2608             
2609             <p class="site-footer__links">
2610              
2611              
2612                
2613                  <a href="/pages/terms-of-service">購物須知</a>
2614                
2615                
2616              
2617             </p>
2618             
2619           </div>
2620         </div>
2621  
2622      </div>
2623    </footer>
2624    
2625      
2626<div class="footer-bar large--hide">
2627  <div>
2628    
2629        
2630        
2631        
2632    
2633        
2634        <a href="/">
2635          
2636          	<img src="https://cdn.easystore.blue/s/201/f/5590.png?width=150&format=webp"/>
2637          
2638            <div>
2639              首頁
2640            </div>
2641        </a>
2642        
2643
2644    
2645        
2646        
2647        
2648    
2649        
2650        <a href="/collections/all">
2651          
2652          	<img src="https://cdn.easystore.blue/s/201/f/5591.png?width=150&format=webp"/>
2653          
2654            <div>
2655              所有商品
2656            </div>
2657        </a>
2658        
2659
2660    
2661        
2662        
2663        
2664    
2665        
2666        <a href="/collections/all">
2667          
2668          	<img src="https://cdn.easystore.blue/s/201/f/5592.png?width=150&format=webp"/>
2669          
2670            <div>
2671              熱銷商品
2672            </div>
2673        </a>
2674        
2675
2676    
2677        
2678        
2679        
2680    
2681        
2682        <a href="/account/login">
2683          
2684          	<img src="https://cdn.easystore.blue/s/201/f/5593.png?width=150&format=webp"/>
2685          
2686            <div>
2687              會員中心
2688            </div>
2689        </a>
2690        
2691
2692    
2693  </div>
2694</div>
2695
2696
2697    
2698
2699    
2700    
2701      <div id="scrollTopButton" class="on-right" style="display: none">
2702        <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>
2703      </div>
2704      
2704<script>
2705        $( document ).ready(function() {
2706          var winScroll = $(this).scrollTop(),
2707          this_el = $("#scrollTopButton");
2708
2709          // Header bar
2710          if(winScroll > 400){
2711            this_el.fadeIn();
2712          }else{
2713            this_el.fadeOut();
2714          }
2715
2716          $("#scrollTopButton").click(function() {
2717            $('html,body').animate({ scrollTop: 0 });
2718          });
2719
2720          $(window).scroll(function(){
2721            var winScroll = $(this).scrollTop();
2722
2723            // Header bar
2724            if(winScroll > 400){
2725              this_el.fadeIn();
2726            }else{
2727              this_el.fadeOut();
2728            }
2729
2730          });
2731        });
2732      </script>
2732
2733    
2734
2735  
2736    
2737  
2738    
2738<script src="https://store-themes.easystore.co/236824/themes/2877/assets/fastclick.min.js?t=1787072460" type="text/javascript" ></script>
2738
2739    
2739<script src="https://store-themes.easystore.co/236824/themes/2877/assets/timber.js?v1.1?t=1787072460" type="text/javascript" ></script>
2739
2740    
2740<script src="https://store-themes.easystore.co/236824/themes/2877/assets/theme.js?t=1787072460" type="text/javascript" ></script>
2740
2741  
2742    
2743  
2744    
2745  
2746    
2747
2748<script src="/assets/currencies.js" type="text/javascript" ></script>
vendor: 1 bytes, line 2748
2748
2749<script src="/assets/jquery.currencies.min.js" type="text/javascript" ></script>
vendor: 1 bytes, line 2749
2749
2750<script src="/assets/currencies_format.js" type="text/javascript" ></script>
2750
2751
2752<script>
2753Currency.format = "money_with_currency_format";
2754var shopCurrency = 'TWD';
2755var selectedCurrency = '';
2756
2757
2758  Currency.convert = function(amount, from, to) {
2759    return amount;
2760  };
2761
2762  
2763if( $.cookie("currency") == null ){
2764  
2765  if( selectedCurrency != false ) {
2766
2767  Currency.convertAll(shopCurrency, selectedCurrency);
2768  jQuery('.selected-currency').text(Currency.currentCurrency);  
2769
2770  }
2771
2772}
2773
2774/* Sometimes merchants change their shop currency, let's tell our JavaScript file */
2775// Currency.moneyFormats[shopCurrency].money_with_currency_format = "";
2776// Currency.moneyFormats[shopCurrency].money_format = "NT$ {{amount}} ";
2777  
2778/* Default currency */
2779var defaultCurrency = 'TWD';
2780  
2781/* Cookie currency */
2782var cookieCurrency = Currency.cookie.read();
2783
2784  cookieCurrency = shopCurrency;
2785
2786$("input[name=current_currency]").val(cookieCurrency);
2787if(cookieCurrency == null){
2788  cookieCurrency = shopCurrency;
2789  Currency.cookie.write(shopCurrency);
2790}
2791/* Fix for customer account pages */
2792jQuery('span.money span.money').each(function() {
2793  jQuery(this).parents('span.money').removeClass('money');
2794});
2795/* Saving the current price */
2796jQuery('span.money').each(function() {
2797  jQuery(this).attr('data-currency-TWD', jQuery(this).html());
2798});
2799// If there's no cookie.
2800if (cookieCurrency == null) {
2801  if (shopCurrency !== defaultCurrency) {
2802    Currency.convertAll(shopCurrency, defaultCurrency);
2803  }
2804  else {
2805    Currency.currentCurrency = defaultCurrency;
2806  }
2807}
2808// If the cookie value does not correspond to any value in the currency dropdown.
2809else if (jQuery('[name=currencies]').size() && jQuery('[name=currencies] option[value=' + cookieCurrency + ']').size() === 0) {
2810  Currency.currentCurrency = shopCurrency;
2811  Currency.cookie.write(shopCurrency);
2812}
2813else if (cookieCurrency === shopCurrency) {
2814  Currency.currentCurrency = shopCurrency;
2815  Currency.convertAll(shopCurrency, cookieCurrency);
2816}
2817else {
2818  Currency.convertAll(shopCurrency, cookieCurrency);
2819}
2820jQuery('[name=currencies]').val(Currency.currentCurrency).change(function() {
2821  var newCurrency = jQuery(this).val();
2822  
2823  
2824    Currency.cookie.write(newCurrency)
2825    if ('customers' == 'cart') {
2826      const params = new URLSearchParams(window.location.search);
2827      params.set('delete_cache', 1);
2828      window.location.search = params;
2829    } else {
2830      window.location.reload();
2831    }
2832  
2833});
2834var original_selectCallback = window.selectCallback;
2835var selectCallback = function(variant, selector) {
2836  var currencies = null;
2837  original_selectCallback(variant, selector);
2838  if(typeof jQuery('[name=currencies]').val() == "undefined"){
2839    currencies = shopCurrency;
2840  }
2841  else{
2842    currencies = jQuery('[name=currencies]').val();
2843  }
2844  Currency.convertAll(shopCurrency, currencies);
2845  jQuery('.selected-currency').text(Currency.currentCurrency);
2846};
2847$('body').on('ajaxCart.afterCartLoad', function(cart) {
2848  Currency.convertAll(shopCurrency, jQuery('[name=currencies]').val());
2849  jQuery('.selected-currency').text(Currency.currentCurrency);  
2850});
2851jQuery('.selected-currency').text(Currency.currentCurrency);
2852</script>
2852
2853
2854
2855  
2856<!-- Snippet:global/body_end: Product Label -->
2857<script>
2858		$(".product-label-badge").parent().find(".badge--sale").remove();
2859		</script>
2859
2860		
2861		<style>
2862		.product-label-badge-text {
2863			display: table-cell;
2864			vertical-align: middle;
2865			padding: 2px 8px 0;
2866			border-radius: 50%;
2867		}
2868		.product-label-badge{
2869			display: table;
2870			position: absolute;
2871			width: 60px;
2872			height: 60px;
2873			border-radius: 50%;
2874			font-weight: bold;
2875			text-align: center;
2876			font-size: .75em;
2877			line-height: 1.1;
2878			z-index: 10;
2879		}
2880
2881		.product-label-position{
2882			top: -12px;
2883			right: -12px;
2884		}
2885		</style>
2886<!-- /Snippet -->
2887<script>
2888
2889  /*
2890
2891    ------
2892    Events
2893    ------
2894
2895    pages/viewed
2896
2897    customers/signup
2898
2899    customers/login
2900
2901    products/searched
2902
2903    collections/viewed
2904
2905    products/viewed
2906
2907    products/shared
2908
2909    wishlists/item_added
2910
2911    carts/items_added
2912
2913    carts/viewed
2914
2915    carts/item_removed
2916
2917    checkouts/initiated
2918
2919    checkouts/shipping_info_added
2920
2921    checkouts/payment_info_added
2922
2923    checkouts/completed
2924
2925    orders/placed
2926
2927    orders/purchased
2928
2929    payments/captured
2930
2931    payments/failed
2932
2933  */
2934
2935  window.__latest_cart = window.__latest_cart || null;
2936
2937  const _selector = document.querySelector.bind(document),
2938        _selectorAll = document.querySelectorAll.bind(document)
2939
2940  document.addEventListener('DOMContentLoaded', (event) => {
2941
2942    const default_currency = getCookie("currency")
2943    const customer_id = window.__st.cid
2944    const template    = window.__st.p
2945
2946    onPageView()
2947
2948    //-----------------------//
2949    //        Configs        //
2950    //-----------------------//
2951
2952    window.dataLayer = window.dataLayer || []
2953
2954    Array.prototype.last = Array.prototype.last || function() {
2955      return this[this.length - 1] || null
2956    }
2957
2958    Array.prototype.first = Array.prototype.first || function() {
2959      return this[0] || null
2960    }
2961
2962    //----------------------//
2963    //       Triggers       //
2964    //----------------------//
2965
2966    const XHR = window.XMLHttpRequest
2967
2968    function xhr() {
2969
2970      const xhr = new XHR()
2971
2972      xhr.addEventListener("readystatechange", function() {
2973
2974        if(xhr.readyState != 4) return
2975
2976        try {
2977
2978          const response_url = xhr.responseURL
2979
2980          if (response_url.includes("cart/add")) {
2981
2982            window.__latest_cart = JSON.parse(xhr.response)
2983
2984            onCartItemsAdded() // ok
2985
2986          }
2987
2988          if (response_url.includes("cart/remove_item_quantity")) {
2989
2990            window.__latest_cart = JSON.parse(xhr.response)
2991
2992            onCartItemRemoved() // ok
2993
2994          }
2995
2996          if (response_url.includes("new_cart?retrieve=true")) {
2997
2998            result = JSON.parse(xhr.response)
2999
3000            if (result.cart) {
3001              window.__latest_cart = result.cart
3002            }
3003
3004          }
3005
3006        } catch(e) {
3007
3008          console.error(e)
3009
3010        }
3011
3012      }, false);
3013
3014      return xhr
3015
3016    }
3017
3018    window.XMLHttpRequest = xhr
3019
3020    switch(template) {
3021
3022      case 'cart': onCartView() // ok
3023      break
3024      case 'product': onProductView() // ok
3025      break
3026      case 'collection': onCollectionView() // ok
3027      break
3028      case 'blog': onBlogView()
3029      break
3030      case 'article': onArticleView()
3031      break
3032      case 'payment_completed': onOrderPlace()
3033      break
3034      case 'payment_fail': onPaymentFail()
3035      break
3036
3037    }
3038
3039    // _selector('form[action="/checkout/payments"]').addEventListener("submit", onPaymentInfoAdded(_selector('form[action="/checkout/payments"]')))
3040    if (_selector('form[action="/checkout/detail"]'))                            _selector('form[action="/checkout/detail"]').addEventListener("submit", ()=>{onShippingInfoAdded(_selector('form[action="/checkout/detail"]'))})  // ok
3041    if (_selector('form[action="/checkout/shipping"]'))                          _selector('form[action="/checkout/shipping"]').addEventListener("submit", ()=>{onShippingInfoAdded(_selector('form[action="/checkout/shipping"]'))})  // ok
3042    if (_selector('form[action="/account/register"]'))                           _selector('form[action="/account/register"]').addEventListener("submit", onSignUp)  // ok
3043    if (_selector('form[action="/account/login"]'))                              _selector('form[action="/account/login"]').addEventListener("submit", onLogin)  // ok
3044    if (_selector('form[action="/search"]'))                                     _selector('form[action="/search"]').addEventListener("submit", onProductSearch()) // ok
3045    if (_selector('#line-login-btn'))                                            _selector('#line-login-btn').addEventListener('click', onLineLogin) // ok
3046    if (_selector('#PlaceOrder'))                                                _selector('#PlaceOrder').addEventListener("click", ()=>{onCheckoutComplete(_selector('form[action="/checkout/payments"]'))});  // ok
3047    if (_selector('#add_wishlist'))                                              _selector('#add_wishlist').addEventListener("click", onWishlistItemAdded) // ok
3048    if (_selectorAll('a[href="/account/logout"]'))                               _selectorAll('a[href="/account/logout"]').forEach(logoutButton => logoutButton.addEventListener("click", onLogout)) // ok
3049    if (_selector('.CartDrawerTrigger.cart-page-link'))                          _selector('.CartDrawerTrigger.cart-page-link').addEventListener("click", onCartView) // ok
3050    if (_selector('.CartDrawerTrigger.cart-page-link.mobile-cart-page-link'))    _selector('.CartDrawerTrigger.cart-page-link.mobile-cart-page-link').addEventListener("click", onCartView) // ok
3051    if (_selectorAll('a[class^="share-"]'))                                      _selectorAll('a[class^="share-"]').forEach(shareButton => shareButton.addEventListener("click", ()=>{onProductShare(shareButton)}) ) // ok
3052    if (_selectorAll('[name$="checkout"]'))                                      _selectorAll('[name$="checkout"]').forEach(checkoutButton => checkoutButton.addEventListener("click", onCheckoutInitiate))
3053
3054    // For append elements
3055    const bodyMutationObserver = new MutationObserver(() => {
3056      if (_selector('#form__spc #PlaceOrder'))             _selector('#form__spc #PlaceOrder').addEventListener("click", onSinglePageCheckout) // ok
3057      if (_selectorAll('[name$="checkout"]'))              _selectorAll('[name$="checkout"]').forEach(checkoutButton => checkoutButton.addEventListener("click", onCheckoutInitiate))
3058    });
3059    bodyMutationObserver.observe(_selector("body"), {subtree: true, childList: true});
3060
3061    //------------------------------//
3062    //        Event handlers        //
3063    //------------------------------//
3064
3065    function onPageView() {
3066
3067      EasyStore.Event.dispatch('pages/viewed', {
3068        page: {
3069          type: template,
3070          title: document.title,
3071          description: _selector('meta[name=description]') ? _selector('meta[name=description]').getAttribute('content') : null,
3072          url: location.href,
3073        }
3074      })
3075
3076    }
3077
3078    function onSignUp() {
3079
3080      const email_regex = new RegExp(/^[a-zA-Z0-9.!#$%&"*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)
3081      const phone_regex = new RegExp(/^(\+?6?01)[0-46-9]-*[0-9]{7,8}$/)
3082
3083      const email_or_phone = _selector(`input[name="customer[email_or_phone]"]`).value.replace("+", "").replace(/\s+/, "")
3084
3085      let data = {}
3086
3087      if (email_regex.test(email_or_phone)) {
3088        data.method = 'email'
3089        data.email = email_or_phone
3090      }
3091
3092      if (phone_regex.test(email_or_phone)) {
3093        data.method = "phone"
3094        data.phone = email_or_phone
3095      }
3096
3097      if (!data.method) return
3098
3099      EasyStore.Event.dispatch('customers/signup', data)
3100
3101    }
3102
3103    function onLogin() {
3104
3105      const email_regex = new RegExp(/^[a-zA-Z0-9.!#$%&"*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)
3106      const phone_regex = new RegExp(/^(\+?6?01)[0-46-9]-*[0-9]{7,8}$/)
3107
3108      const email_or_phone = _selector(`input[name="customer[email_or_phone]"]`).value.replace("+", "").replace(/\s+/, "")
3109
3110      let data = {}
3111
3112      if (email_regex.test(email_or_phone)) {
3113        data.method = 'email'
3114        data.email = email_or_phone
3115      }
3116
3117      if (phone_regex.test(email_or_phone)) {
3118        data.method = "phone"
3119        data.phone = email_or_phone
3120      }
3121
3122      if (!data.method) return
3123
3124      EasyStore.Event.dispatch('customers/login', data)
3125
3126    }
3127
3128    function onLineLogin() {
3129
3130      EasyStore.Event.dispatch('customers/login', { method: 'line' })
3131
3132    }
3133
3134    function onLogout() {
3135
3136      EasyStore.Event.dispatch('customers/logout', { customer_id })
3137
3138    }
3139
3140    function onBlogView() {
3141
3142      const blog = ""
3143
3144      EasyStore.Event.dispatch('blogs/viewed', { blog })
3145
3146    }
3147
3148    function onArticleView() {
3149
3150      const article = ""
3151
3152      EasyStore.Event.dispatch('articles/viewed', { article })
3153
3154    }
3155
3156    function onProductSearch() {
3157
3158      const query = _selector('input[name=q]').value
3159
3160      if (!query) return
3161
3162      EasyStore.Event.dispatch('products/searched', { query })
3163
3164    }
3165
3166    function onCollectionView() {
3167
3168      const collection = ""
3169
3170      EasyStore.Event.dispatch('collections/viewed', { collection })
3171
3172    }
3173
3174    function onProductView() {
3175
3176      const product = ""
3177
3178      EasyStore.Event.dispatch("products/viewed", { product })
3179
3180    }
3181
3182    function onProductShare(el) {
3183
3184      const product = ""
3185
3186      const channel = el.getAttribute("class").split("-").last()
3187
3188      EasyStore.Event.dispatch('products/shared', { product, channel })
3189
3190    }
3191
3192    function onWishlistItemAdded() {
3193
3194      let product  = ""
3195      const quantity = _selector("#Quantity").value
3196
3197      EasyStore.Event.dispatch('wishlists/item_added', { product })
3198
3199    }
3200
3201    async function onCartItemsAdded() {
3202
3203      const cart = await getCart()
3204
3205      if(cart && cart.items != undefined && cart.items.length > 0) {
3206
3207        EasyStore.Event.dispatch('carts/item_added', { cart })
3208
3209      }
3210
3211    }
3212
3213    async function onCartView() {
3214
3215      const cart = await getCart()
3216
3217      EasyStore.Event.dispatch('carts/viewed', { cart })
3218
3219    }
3220
3221    async function onCartItemRemoved() {
3222
3223      const cart = await getCart()
3224
3225      cart.items = []
3226
3227      if(cart) {
3228
3229        EasyStore.Event.dispatch('carts/item_removed', { cart })
3230
3231      }
3232
3233    }
3234
3235    async function onCheckoutInitiate() {
3236
3237      const cart = await getCart()
3238
3239      EasyStore.Event.dispatch('checkouts/initiated', { cart })
3240
3241    }
3242
3243    async function onShippingInfoAdded(form) {
3244      let checkout = getCheckout()
3245
3246      let form_data = {}
3247      new FormData(form).forEach((value, key) => form_data[key] = value)
3248
3249      let shipping_tier = null
3250
3251      if (form_data.type && form_data.type.startsWith("r_pickup")) {
3252        shipping_tier = `Pickup - ${form_data.pick_location}`
3253      }
3254
3255      if (form_data.s_id) {
3256        shipping_tier = _selector(`input[id='`+form_data.s_id+`']`).getAttribute("data-shipping-name")
3257      }
3258
3259      if (!shipping_tier) return
3260
3261      EasyStore.Event.dispatch('checkouts/shipping_info_added', { checkout, shipping_tier })
3262
3263    }
3264
3265    async function onPaymentInfoAdded(form) {
3266
3267      let checkout = getCheckout()
3268
3269      let payment_type = new FormData(form).get('payment_method')
3270
3271      EasyStore.Event.dispatch("checkouts/payment_info_added", { checkout, payment_type })
3272
3273    }
3274
3275    async function onOrderPlace() {
3276
3277      let cart_token  = getCookie("cart_js")
3278      let previous_cart_token = getCookie("previous_cart_ga4_js")
3279
3280      if (previous_cart_token && previous_cart_token == cart_token) {
3281        // Prevent duplicate purchase tracking
3282        return
3283      }
3284
3285      let order = getOrder()
3286
3287      EasyStore.Event.dispatch('orders/placed', { order })
3288
3289      if(order.is_manual_payment) {
3290
3291        EasyStore.Event.dispatch('orders/purchased', { order })
3292
3293      }
3294
3295      const last_transaction = order.transactions.last()
3296
3297      if (last_transaction.status) {
3298
3299        EasyStore.Event.dispatch('orders/purchased', { order })
3300        EasyStore.Event.dispatch('payments/captured', { order })
3301
3302      }
3303
3304    }
3305
3306    async function onPaymentFail() {
3307
3308      const order = getOrder()
3309
3310      EasyStore.Event.dispatch('payments/failed', { order })
3311
3312    }
3313
3314    async function onCheckoutComplete(form) {
3315
3316      onPaymentInfoAdded(form)
3317
3318      const checkout = getCheckout()
3319
3320      EasyStore.Event.dispatch('checkouts/completed', { checkout })
3321
3322    }
3323
3324    async function onSinglePageCheckout() {
3325
3326      // let checkout = $("[data-app-checkout]").data("app-checkout")
3327
3328      let checkout = getCheckout()
3329
3330      // const payment_type = _selector("#app_spc_payment_method").find(`[class*="label-content"]`).first().find("b").first().text()
3331      const payment_type = _selector("#app_spc_payment_method").getElementsByClassName('label-content')[0].getElementsByTagName('b')[0].innerHTML
3332
3333      const shipping_method = _selector("#delivery_method").value
3334
3335      let shipping_tier = null
3336      let app_spc_customer_info_label = _selector("#app_spc_customer_info").getElementsByClassName('label-content')
3337      if (shipping_method == "shipping") {
3338        shipping_tier = app_spc_customer_info_label[app_spc_customer_info_label.length - 1].getElementsByTagName('b')[0].innerHTML
3339      }
3340
3341      if (shipping_method == "pickup") {
3342        shipping_tier = app_spc_customer_info_label[0].innerHTML
3343      }
3344
3345      if (shipping_tier) {
3346
3347        EasyStore.Event.dispatch('checkouts/shipping_info_added', {
3348          checkout,
3349          shipping_tier,
3350        })
3351
3352      }
3353
3354      if (payment_type) {
3355
3356        EasyStore.Event.dispatch('checkouts/payment_info_added', {
3357          checkout,
3358          payment_type,
3359        })
3360
3361      }
3362
3363      EasyStore.Event.dispatch('checkouts/completed', { checkout })
3364
3365    }
3366
3367  })
3368
3369
3370  //-----------------------//
3371  //       Functions       //
3372  //-----------------------//
3373
3374  function getCookie(name) {
3375
3376    name += "="
3377
3378    decodedCookie = decodeURIComponent(document.cookie)
3379
3380    ca = decodedCookie.split(";")
3381
3382    for(i = 0; i < ca.length; i++) {
3383      c = ca[i]
3384      while (c.charAt(0) == " ") {
3385        c = c.substring(1)
3386      }
3387      if (c.indexOf(name) == 0) {
3388        return c.substring(name.length, c.length)
3389      }
3390    }
3391
3392    return ""
3393
3394  }
3395
3396  const parsePrice = price => {
3397    if(typeof price === 'string') {
3398      return parseFloat(price.split(',').join(''))
3399    }
3400
3401    return price
3402  }
3403
3404  const requestCart = async (method, data) => {
3405
3406  let response = await fetch('/cart.json', {method: 'GET',headers: {'Content-Type': 'application/json'}})
3407    result = await response.json()
3408
3409    return result.cart
3410
3411  }
3412  const getCart = async (latest = false) => {
3413
3414    let cart = window.__latest_cart
3415
3416    const cart_invalid = !cart || !cart.items || (cart.total_price > 0 && !cart.items.length)
3417
3418    if(latest || cart_invalid) {
3419      cart = await requestCart()
3420    }
3421
3422    cart.items = cart.items || []
3423
3424    return mapCart(cart)
3425
3426  }
3427
3428  const getCheckout = async () => {
3429    mapCheckout(window.__latest_cart || await requestCart())
3430  }
3431
3432  const getOrder = async () => {
3433    mapOrder(window.__latest_cart || await requestCart())
3434  }
3435
3436  //-----------------------//
3437  //        Mappers        //
3438  //-----------------------//
3439
3440  const fallbackAttribute = (object, attribute) => {
3441
3442    if(!Array.isArray(attribute)) {
3443      attribute = [attribute]
3444    }
3445
3446    let final_value = null
3447
3448    do {
3449
3450      final_value = object[attribute.shift()]
3451
3452    } while(!final_value && attribute.length)
3453
3454    return final_value
3455
3456  }
3457
3458  const map = (object, mapper) => {
3459
3460    const newObject = {}
3461
3462    for(const key in mapper) {
3463
3464      // Handle different keys between new and old format
3465      newObject[key] = fallbackAttribute(object, mapper[key])
3466
3467      // Cast price to float
3468      if(newObject[key] && ['price', 'amount', 'discount', 'discounts'].some(x => key.endsWith(x))) {
3469        newObject[key] = parsePrice(newObject[key])
3470      }
3471
3472      if(newObject[key] === undefined) {
3473        delete newObject[key]
3474      }
3475
3476    }
3477
3478    return newObject
3479
3480  }
3481
3482  const mapCart = cart => {
3483
3484    const oldCart = cart
3485
3486    const mapper = {
3487      id: 'id',
3488      currency: 'currency',
3489      item_count: 'item_count',
3490      items: 'items',
3491      total_price: 'total_price',
3492      latest_items: 'latest_items'
3493    }
3494
3495    cart = map(cart, mapper)
3496
3497    const discounts = (oldCart.storewide_discounts || []).concat((oldCart.voucher_discounts || []))
3498
3499    cart.discount_applications = discounts.map(discount => ({
3500      title: discount.voucher_code || null,
3501      value: parsePrice(discount.amount),
3502    }))
3503
3504    cart.original_total_price = cart.items.length
3505    ? cart.items
3506      .map(item => item.original_price)
3507      .reduce((sum, price) => sum + price)
3508    : 0
3509
3510    cart.total_discount = cart.discount_applications.length
3511    ? cart.discount_applications
3512      .map(discount => parsePrice(discount.value))
3513      .reduce((sum, value) => sum + value)
3514    : 0
3515
3516    cart.items = cart.items.map(item => mapLineItem(item))
3517
3518    return cart
3519
3520  }
3521
3522  const mapCheckout = checkout => {
3523
3524    const mapper = {
3525      note: 'note',
3526      attributes: 'note_attributes',
3527      billing_address: 'billing_address',
3528      currency: 'currency',
3529      customer_id: 'customer_id',
3530      discounts_amount: 'total_discount',
3531      id: 'id',
3532      line_items: 'order_item',
3533      order_number: 'order_number',
3534      shipping_address: 'shipping_address',
3535      shipping_price: 'shipping_tax',
3536      shipping_method: 'shipping_method_name',
3537      tax_price: 'total_tax',
3538    }
3539
3540    checkout = map(checkout, mapper)
3541
3542    checkout.requires_shipping = checkout.line_items.some(item => item.shipping_required)
3543
3544    checkout.line_items = checkout.line_items.map(item => mapLineItem(item))
3545
3546    return checkout
3547
3548  }
3549
3550  const mapOrder = order => {
3551
3552    const mapper = {
3553      attributes: 'note_attributes',
3554      billing_address: 'billing_address',
3555      cancelled: 'is_cancelled',
3556      cancelled_at: 'cancelled_at',
3557      created_at: 'created_at',
3558      customer_id: 'customer_id',
3559      // discount_applications: 'discount_applications',
3560      email: 'email',
3561      financial_status: 'financial_status',
3562      fulfillment_status: 'fulfillment_status',
3563      line_items: 'order_item',
3564      note: 'note',
3565      order_number: 'order_number',
3566      phone: 'phone',
3567      shipping_address: 'shipping_address',
3568      shipping_methods: 'shipping_methods',
3569      shipping_price: 'total_shipping',
3570      subtotal_price: 'subtotal_price',
3571      // tax_lines: 'tax_lines',
3572      tax_price: 'total_tax',
3573      total_discounts: 'total_discount',
3574      total_net_amount: 'total_amount_include_transaction',
3575      total_price: 'total_price',
3576      transactions: 'transaction_records',
3577      is_manual_payment: 'is_manual_payment',
3578    }
3579
3580    order.email = order.billing_address.email
3581    order.phone = order.billing_address.phone
3582    order.shipping_method = order.shipping_method_name
3583
3584    order = map(order, mapper)
3585
3586    order.line_items = order.line_items.map(item => mapLineItem(item))
3587    order.transactions = order.transactions.map(transaction => mapTransaction(transaction))
3588
3589    return order
3590
3591  }
3592
3593  const mapLineItem = line_item => {
3594
3595    const old_line_item = line_item
3596
3597    const mapper = {
3598      final_price: 'price',
3599      image: 'img_url',
3600      message: 'message',
3601      original_line_price: 'original_line_price',
3602      original_price: 'original_price',
3603      properties: 'properties',
3604      quantity: 'quantity',
3605      requires_shipping: 'shipping_required',
3606      sku: 'sku',
3607      taxable: 'taxable',
3608      title: 'product_name',
3609      product_name: 'product_name',
3610      url: 'url',
3611      product_id: 'product_id',
3612      variant_id: 'variant_id',
3613      id: ['id', 'i_id'],
3614    }
3615
3616    line_item = map(line_item, mapper)
3617
3618    line_item.product_id = line_item.product_id || (old_line_item.product && old_line_item.product.id) || null
3619    line_item.variant_id = line_item.variant_id || (old_line_item.variant && old_line_item.variant.id) || null
3620    line_item.image      = line_item.image || (old_line_item.image && old_line_item.image.url) || null
3621
3622    return line_item
3623
3624  }
3625
3626  const mapTransaction = transaction => {
3627
3628    const mapper = {
3629      amount: 'amount',
3630      created_at: 'created_at',
3631      gateway: 'gateway_type',
3632      id: 'id',
3633      status: 'status',
3634    }
3635
3636    transaction = map(transaction, mapper)
3637
3638    return transaction
3639
3640  }
3641
3642
3643</script>
3643
3644
3645</div>
3646
3647  
3648    
3649<style>
3650  #CartTemplate{
3651    min-height: 80vh;
3652  }
3653  .cart-drawer .cart__row .small--one-whole,
3654  .cart-drawer .cart-sticky-button-wrapper{
3655    width: 100%;
3656  }
3657  .cart-drawer .promotion__code-input .input-group{
3658    margin-top: 20px;
3659    max-width: 100%;
3660  }
3661  .cart-drawer-wrapper{
3662    display: flex;
3663    flex-wrap: wrap;
3664    flex-direction: row;
3665  }
3666  .cart-drawer-wrapper > div{
3667    width: 100%;
3668  }
3669  vouchers-modal .vouchers-modal.active ,
3670  vouchers-modal #vouchers-modal-backdrop.active{
3671    z-index: 2147483647;
3672  }
3673</style>
3674
3675<div id="CartDrawer" class="cart-drawer" data-fetch="0">
3676  
3677
3678  <div class="cart-drawer-wrapper">
3679    <div id="cart-promotion-top"></div>
3680
3681
3682    <div id="CartTemplate">
3683      
3684
3685
3686  
3687
3688  <div id="noCartItem" class="cart-drawer-content">
3689    <div class="cart-drawer-content-wrapper text-center">
3690      <div class="section-header">
3691        <span></span>
3692        <span class="CartDrawerTrigger icon icon-x"></span>
3693      </div>
3694      <div class="section-header__title h2">您的購物車目前還是空的。</div>
3695      <a class="btn btn--secondary" href="/collections/all">繼續購物</a>
3696    </div>
3697  </div>
3698
3699
3700
3701    </div>
3702
3703    <link href="/assets/css/promotion.css?v2.94" rel="stylesheet" type="text/css" media="screen" />
3704<div id="cart-promotion-section"></div>
3705
3706<script>var shop_money_format = "<span class=money data-ori-price='{{amount}}'>NT$ {{amount}} </span>";</script>
vendor: 1 bytes, line 3706
3706
3707<script src="/assets/js/promotion/promotion.js?v1.11" type="text/javascript"></script>
3707
3708
3709<script>
3710
3711    window.EasyStore = window.EasyStore || {};
3712    window.EasyStore.Promotion = window.EasyStore.Promotion || {};
3713
3714    var get_cart_promo_initial = false,
3715        current_template = 'customers';
3716
3717    window.EasyStore.Promotion.updateCartPromotion = function (){
3718        get_cart_promo_initial = true
3719        $.ajax({
3720        type: "GET",
3721        dataType: 'json',
3722        url: "/new_cart/promotion",
3723        success: function(response){
3724            $("#cart-promotion-section").html(response["cart/content_bottom"].trim());
3725            $("#cart-promotion-top").html(response["cart/content_top"].trim());
3726
3727            promoVariantDetailInitial()
3728        },
3729        error: function(xhr){
3730        }
3731        });
3732    }
3733
3734
3735    if(current_template == 'cart') {
3736        document.addEventListener("DOMContentLoaded", function() {
3737            window.EasyStore.Promotion.updateCartPromotion()
3738        });
3739    }
3740
3741</script>
vendor: 1 bytes, line 3741
3741
3742<script>
3743  document.addEventListener('DOMContentLoaded', function () {
3744    window._getVoucherErrorTranslation = Object.assign(window._getVoucherErrorTranslation || {}, {
3745      "condition_not_matched":    "優惠代碼條件不匹配",
3746      "promotion_unavailable":    "此優惠目前不可用",
3747      "available_on":             "可在 channels 使用",
3748      "available_on_only":        "僅限在 channels 使用",
3749      "available_with_locations": "可在 channels 使用(僅限 locations)",
3750      "pos_at_locations":         "僅限 locations 門市使用",
3751      "channel_website":          "網站",
3752      "channel_mobile":           "應用程式",
3753      "channel_pos":              "門市"
3754    });
3755  });
3756</script>
3756
3757
3758  </div>
3759  
3760
3761  
3762</div>
3763
3764<div id="toast"><div id="toastContent"></div></div>
3765<style>
3766  .cart-drawer .cart-drawer-content .cart-sticky-button-wrapper a.btn.CartDrawerTrigger{margin-bottom: 10px !important;}
3767  #toastContent a{color: #fff;text-decoration: underline;margin-top: 10px;display: block;}
3768  #toastContent .svg-icon{margin-right: 8px;margin-top: -1px;}
3769</style>
3770
3771<script type="text/javascript">
3772  $('body').on("submit", "#CartForm", function() {
3773    $(this).find('[type=submit]').addClass('btn--loading');
3774  });
3775  
3776  $("input[name=current_currency]").val($( "select.currency-picker" ).val());
3777  $( "select.currency-picker" ).change(function(){
3778    $("select.currency-picker").val($(this).val());
3779    url=window.location.href;
3780    newParam="currency=" + $( "select.currency-picker" ).val();
3781    if(url.indexOf("currency=")===-1){
3782      separator = (url.indexOf("?")===-1)?"?":"&";
3783      newUrl= url + separator + newParam;
3784    }else{
3785      oldParam= new URL(url);
3786      oldParam = oldParam.searchParams.get("currency");
3787      newParam= $(this).val();
3788      newUrl=url.replace(oldParam,newParam);
3789    }
3790    $("input[name=current_currency]").val($( "select.currency-picker" ).val());
3791    // window.location.href =newUrl;
3792    $('#CartDrawer').attr('data-fetch', 0);
3793  });
3794
3795  $("body").on("click", ".cart__remove", function() {
3796    $('#CartTemplate').addClass('is-loading');
3797    $.ajax({
3798      type: 'POST',
3799      url: '/cart/remove_item_quantity',
3800      data: {
3801        variant_id: $(this).data( "variant-id"),
3802        item_id: $(this).data( "item-id"),
3803        quantity: $(this).data( "quantity"),
3804        i_id: $(this).data("i_id"),
3805      },
3806      dataType: 'json',
3807      success: function(response){
3808
3809        theme.cartDrawer(response);
3810        $('#CartTemplate').removeClass('is-loading');
3811
3812        if (window.checkProductProperties !== undefined){
3813          window.checkProductProperties();
3814        }      
3815      },
3816      error: function(xhr){
3817        console.log('error',xhr);
3818        $('#CartTemplate').removeClass('is-loading');
3819      }
3820    });
3821
3822  });
3823
3824
3825  $('body').on("click", "#applycode",function() {
3826    
3827    if($("input[name='voucher_code']").val() != '') {
3828
3829      $('#CartTemplate').addClass('is-loading');
3830
3831      $.ajax({
3832        type: 'POST',
3833        url: '/new_cart/voucher',
3834        data: {
3835          voucher_code: $("input[name='voucher_code']").val(),
3836          category: 'create'
3837        },
3838        dataType: 'json',
3839        success: function(response){
3840
3841          // console.log(response);
3842
3843          if(response.error != undefined){
3844            
3845            if(response.error.message != undefined) popToast(response.error.message); 
3846          
3847            $("input[name='voucher_code']").val('')
3848          
3849          } 
3850          
3851          if(response.cart_content != undefined) theme.cartDrawer(response); 
3852
3853          
3854          $('#CartTemplate').removeClass('is-loading');
3855          
3856        },
3857        error: function(xhr){
3858          console.log('error',xhr);
3859          $('#CartTemplate').removeClass('is-loading');
3860        }
3861      });
3862
3863    }
3864
3865  });
3866
3867
3868  $("body").on("click", ".remove_voucher_btn", function() {
3869        $('#CartTemplate').addClass('is-loading');
3870        $.ajax({
3871          type: 'DELETE',
3872          url: '/new_cart/voucher',
3873          data: {
3874            category: 'remove',
3875            order_discount_id: $(this).data( "discount-id")
3876          },
3877          dataType: 'json',
3878          success: function(data){
3879            // console.log(data);
3880            theme.cartDrawer(data);
3881            $('#CartTemplate').removeClass('is-loading');
3882          },
3883          error: function(xhr){
3884            console.log('error',xhr);
3885            $('#CartTemplate').removeClass('is-loading');
3886          }
3887        });
3888
3889    });
3890  
3891
3892  theme.cartDrawer = function(data){
3893    
3894      $('#CartDrawer').attr('data-fetch', 1);
3895      $('#CartTemplate').addClass('is-loading');
3896
3897      
3898      if(typeof data.cart_content  == 'string'){
3899        $('#CartTemplate').html(data.cart_content);
3900      }
3901
3902      let cart_item_count = data.item_count || data.cart.item_count;
3903
3904      if(cart_item_count > 0){
3905        $('.cart-count').removeClass('hidden-count');
3906      }else{
3907        $('.cart-count').addClass('hidden-count');
3908      }
3909
3910      $('.cart-count').text(cart_item_count);
3911      $('#CartTemplate').removeClass('is-loading');
3912      $(".cart-drawer-content").animate({ scrollTop: 0 });
3913
3914      if(window.EasyStore != undefined && window.EasyStore.Promotion != undefined && window.EasyStore.Promotion.updateCartPromotion != undefined) window.EasyStore.Promotion.updateCartPromotion()
3915
3916  }
3917
3918  theme.fetchCartDrawer = function(data){
3919      $('#CartTemplate').addClass('is-loading');
3920      $.ajax({
3921        url: '/new_cart?retrieve=true',
3922        type: 'GET',
3923        success: function(data, status) {
3924          // console.log(data);
3925          theme.cartDrawer(data);
3926
3927          $('#CartTemplate').removeClass('is-loading');
3928
3929          if (window.checkProductProperties !== undefined){
3930            window.checkProductProperties();
3931          }
3932        },
3933        error: function(XMLHttpRequest, textStatus) {
3934          console.log('error',XMLHttpRequest,textStatus);
3935          $('#CartTemplate').removeClass('is-loading');
3936        }
3937      });
3938  }
3939
3940  theme.updateCartDrawer = function(data){
3941    $('#CartTemplate').addClass('is-loading');
3942
3943    $.ajax({
3944      url: '/new_cart/update',
3945      type: 'PUT',
3946      dataType: 'json',
3947      data: $('#CartDrawer form').serialize(),
3948      success: function(data, status) {
3949        theme.cartDrawer(data);
3950
3951        if (window.checkProductProperties !== undefined){
3952          window.checkProductProperties();
3953        }
3954      },
3955      error: function(XMLHttpRequest, textStatus) {
3956        console.log('error',XMLHttpRequest,textStatus);
3957      }
3958    });
3959  }
3960
3961  function debounce(func, wait, immediate) {
3962    var timeout;
3963    return function() {
3964        var context = this, args = arguments;
3965        var later = function() {
3966            timeout = null;
3967            if (!immediate) func.apply(context, args);
3968        };
3969        var callNow = immediate && !timeout;
3970        clearTimeout(timeout);
3971        timeout = setTimeout(later, wait);
3972        if (callNow) func.apply(context, args);
3973    };
3974  };
3975
3976  $('body').on("change", 'input.cart__quantity-selector', function (){
3977    theme.updateCartDrawer();
3978  });
3979
3980
3981  $('#updateCartDrawer').click(function() {
3982    theme.updateCartDrawer();
3983  });
3984
3985  $('body').on("click", ".btn-qty-adjust", function() {
3986
3987    var $button = $(this);
3988    var oldValue = $button.parent().find("input.cart__quantity-selector").val();
3989
3990    if ($button.attr('data-adjust') == 1) {
3991      var newVal = parseFloat(oldValue) + 1;
3992    } else {
3993    // Don't allow decrementing below zero
3994      if (oldValue > 0) {
3995        var newVal = parseFloat(oldValue) - 1;
3996      } else {
3997        newVal = 0;
3998      }
3999    }
4000
4001    $button.parent().find("input").val(newVal);
4002  });
4003    
4004  $('body').on("click", ".btn-qty-adjust", debounce(function() {
4005    theme.updateCartDrawer();
4006  },350));
4007
4008  $('button.checkout').click(function() {
4009    $(this).addClass('btn--loading');
4010  });
4011
4012  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>';
4013      add_cart_success_html += '已加入購物車 <br><a class="CartDrawerTrigger">查看購物車</a>';
4014
4015  function popToast(content) {
4016    var x = document.getElementById("toast"),
4017        y = document.getElementById("toastContent");
4018
4019    y.innerHTML = content;
4020    x.className += " show";
4021    
4022    var hideToast = setTimeout(function(){ x.className = x.className.replace(" show", ""); }, 3000);
4023  }
4024
4025</script>
4025
4026
4027<link href="/assets/css/vouchers.css?v1.2" rel="stylesheet" type="text/css" media="screen" />
4028<link href="/assets/account/vouchers/vouchers.css" rel="stylesheet" type="text/css" media="screen" />
4029<link href="/assets/account/vouchers/voucher-widget.css" rel="stylesheet" type="text/css" media="screen" />
4030<script src="/assets/js/promotion/vouchers.js?v1.3" type="text/javascript" ></script>
vendor: 1 bytes, line 4030
4030
4031<script src="/assets/account/vouchers/voucher-widget.js" type="text/javascript" ></script>
4031
4032
4033<vouchers-modal>
4034  <div id="vouchers-modal-backdrop" class="vouchers-modal__close"></div>
4035  <div class="vouchers-modal-wrapper page-width">
4036    <div id="vouchers-modal" class="vouchers-modal focus-inset" aria-modal="true" role="dialog" tabindex="-1">
4037      <div class="vouchers-modal__header">
4038        <div class="vouchers-modal__heading">優惠券</div>
4039        <button type="button" class="vouchers-modal__close modal__close-button link link--text focus-inset" aria-label="accessibility.close">
4040          <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">
4041            <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">
4042            </path>
4043          </svg>
4044        </button>
4045      </div>
4046
4047      <discount-input>
4048        <div class="field">
4049          <input type="text" id="input-discount_code" class="search__input field__input" name="voucher_code" placeholder="折扣碼">
4050          <button type="button" name="apply" class="btn btn--secondary button button--secondary">套用</button>
4051        </div>
4052        <div class="form__message hidden" tabindex="-1" autofocus>
4053          <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-error " viewBox="0 0 13 13">
4054            <circle cx="6.5" cy="6.50049" r="5.5" stroke="white" stroke-width="2"></circle>
4055            <circle cx="6.5" cy="6.5" r="5.5" fill="#EB001B" stroke="#EB001B" stroke-width="0.7"></circle>
4056            <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>
4057            <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>
4058          </svg>
4059          <div class="js-error-content"></div>
4060        </div>
4061      </discount-input>
4062      <br>
4063
4064      
4065      
4066        <div class="empty-vouchers_placeholder">目前無可用的優惠券</div>
4067      
4068
4069       <!-- For voucher widget -->
4070      
4070<script type="text/javascript">
4071        let settings = {"logo_use_image":"1","logo_img":"https:\/\/cdn.store-assets.com\/s\/236824\/f\/16676111.png?width=350&format=webp","footer_logo_img":"https:\/\/cdn.store-assets.com\/s\/236824\/f\/1140401.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\/236824\/f\/1140397.png","header_message":"","header_search_enable":true,"topbar_sticky":"1","footer_quicklinks_enable":true,"footer_quicklinks_linklist":"footer","footer_social_enable":"1","footer_show_credit_card_logo":"1","footer_show_methods_of_payment":"0","footer_visa":"1","footer_master":"1","footer_american_express":"0","footer_jcb":"0","footer_diners_club":"0","footer_discover":"0","footer_ssl":"0","show_footer_lines":"1","home_section_1":"highlight-section","home_section_2":"featured-product","home_section_3":"","home_section_4":"","home_section_5":"","home_section_6":"","featured_title":"","featured_1_img":"https:\/\/cdn.store-assets.com\/s\/236824\/f\/17552634.png?width=650&format=webp","featured_1_text":"","featured_1_link":"https:\/\/wizsubs.com\/","featured_2_img":"https:\/\/cdn.store-assets.com\/s\/236824\/f\/4537198.jpeg?width=650&format=webp","featured_2_text":"","featured_2_link":"https:\/\/www.jmaker.com.tw\/collections\/arduino-projects","featured_3_img":"https:\/\/cdn.store-assets.com\/s\/236824\/f\/4216066.png?width=650&format=webp","featured_3_text":"","featured_3_link":"https:\/\/blog.jmaker.com.tw\/","featured_4_img":"","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\/278885\/f\/3915149.jpeg?width=1500&format=webp","parallax_mobile_img":"","parallax_title":"Sign Up for 50% OFF","parallax_subtitle":"For new member only","parallax_button_text":"Sign Up Now","parallax_button_link":"\/account\/register","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\/236824\/f\/4537190.jpeg?width=1500&format=webp","slide_1_mobile_jpg":"","slide_1_link":"\/account\/register","slide_1_alt":"","slide_1_title":"","slide_1_subtitle":"","slide_1_button_text":"","slide_2":"1","slide_2_jpg":"https:\/\/cdn.store-assets.com\/s\/236824\/f\/4537198.jpeg?width=1500&format=webp","slide_2_mobile_jpg":"","slide_2_link":"h\/collections\/arduino-projects","slide_2_alt":"","slide_2_title":"","slide_2_subtitle":"","slide_2_button_text":"","slide_3":"","slide_3_jpg":"https:\/\/cdn.store-assets.com\/s\/236824\/f\/4216066.png?width=1500&format=webp","slide_3_mobile_jpg":"","slide_3_link":"https:\/\/blog.jmaker.com.tw\/","slide_3_alt":"","slide_3_title":"","slide_3_subtitle":"","slide_3_button_text":"","slide_4":"","slide_4_jpg":"","slide_4_mobile_jpg":"","slide_4_link":"","slide_4_alt":"","slide_4_title":"","slide_4_subtitle":"","slide_4_button_text":"","slide_5":"","slide_5_jpg":"","slide_5_mobile_jpg":"","slide_5_link":"","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_
40711_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":"1","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":"5","product_page_float_btn":"1","product_page_variants_tag":"1","featured_product_title":"","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":"\u9996\u9801","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":"\u6240\u6709\u5546\u54c1","footer_bar_icon_2_link":"\/collections\/all","footer_bar_icon_3":"https:\/\/cdn.easystore.blue\/s\/201\/f\/5592.png?width=150&format=webp","footer_bar_icon_3_text":"\u71b1\u92b7\u5546\u54c1","footer_bar_icon_3_link":"\/collections\/all","footer_bar_icon_4":"https:\/\/cdn.easystore.blue\/s\/201\/f\/5593.png?width=150&format=webp","footer_bar_icon_4_text":"\u6703\u54e1\u4e2d\u5fc3","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\/geeksfans\/","twitter_url":"","pinterest_url":"","instagram_url":"","tumblr_url":"","youtube_url":"https:\/\/www.youtube.com\/channel\/UC81gFCuXzmRt6HVvAiPBpcA","vimeo_url":"","wechat_url":"","whatsapp_url":"","line_url":"","featured_blog":"https:\/\/blog.jmaker.com.tw\/","promotion_uis":{"primary_color":"#EB3333","header_bg_color":"#EB3333","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":"TWD ","theme_id":2877,"theme_is_edited":1,"theme_updated_at":"2026-08-18T17:01:00.000Z","phone_account_enabled":false,"line_login_enabled":false,"apple_login_enabled":false,"timezone":"Asia\/Taipei","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}
4072        if (settings.promotion_uis.voucher_widget != null) {
4073          setVoucherTheme(settings.promotion_uis.voucher_widget)
4074        }
4075        var shop = {
4076          money_prefix: "",
4077          format_decimals: ""
4078        };
4079        var _getEntitlementTranslation = {
4080          "free_shipping": "免運費",
4081          "free_of_charge": "免費贈品",
4082        }
4083        var _getTargetTypeTranslation = {
4084          "amount_credit": " 回饋金",
4085          "amount_off": " 折扣",
4086        }
4087        var _getPrerequisiteTranslation = {
4088          "min_quantity": "至少購買 formatValue 件商品",
4089          "every_quantity": "每購買 formatValue 件商品",
4090          "min_amount": "最低消費 formatCurrency",
4091          "every_amount": "每消費 formatCurrency"
4092        }
4093        var _getPrerequisiteConditionTranslation = {
4094          "selected_items": "指定商品",
4095          "selected_collections": "指定分類",
4096          "storewide": "全店",
4097          "order_subtotal": "訂單金額"
4098        }
4099        var _getVoucherButtonTextTranslation = {
4100          "apply": "套用",
4101        }
4102        var _getVoucherErrorTranslation = {
4103          "condition_not_matched": "優惠代碼條件不匹配"
4104        }
4105      </script>
4105
4106
4107    </div>
4108  </div>
4109</vouchers-modal>
4110  
4111  
4112</body>
4113</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.