PageSourceSearch

https://www.sunyours.com.tw/blogs/tsaifu-calligraphy

html sunyours.com.tw collected 2026-09-30 23:46:33 UTC 80,056 bytes, 2,422 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  <!-- Facebook Pixel Code -->
9<script>
vendor: 399 bytes, lines 9-18
9
10!function(f,b,e,v,n,t,s)
11{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
12n.callMethod.apply(n,arguments):n.queue.push(arguments)};
13if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
14n.queue=[];t=b.createElement(e);t.async=!0;
15t.src=v;s=b.getElementsByTagName(e)[0];
16s.parentNode.insertBefore(t,s)}(window, document,'script',
17'https://connect.facebook.net/en_US/fbevents.js');
18fbq('init', '
18388838182692732
vendor: 30 bytes, lines 18-19
18');
19fbq('track', 'PageView');
20</script>
20
21<noscript><img height="1" width="1" style="display:none"
22src="https://www.facebook.com/tr?id=388838182692732&ev=PageView&noscript=1"
23/></noscript>
24<!-- End Facebook Pixel Code -->
25  <!-- Global site tag (gtag.js) - Google Ads: 793750852 -->
vendor: 64 bytes, lines 25-26
25
26<script async src="https://www.googletagmanager.com/gtag/js?id=
26AW-793750852
vendor: 12 bytes, line 26
26"></script>
27<script>
28  
vendor: 134 bytes, lines 28-32
28window.dataLayer = window.dataLayer || [];
29  function gtag(){dataLayer.push(arguments);}
30  gtag('js', new Date());
31
32  gtag('config', '
32AW-793750852
vendor: 4 bytes, line 32
32');
33</script>
33
34
35  <!-- Global site tag (gtag.js) - Google Analytics -->
vendor: 64 bytes, lines 35-36
35
36<script async src="https://www.googletagmanager.com/gtag/js?id=
36UA-124909880-1
vendor: 12 bytes, line 36
36"></script>
37<script>
38  
vendor: 134 bytes, lines 38-42
38window.dataLayer = window.dataLayer || [];
39  function gtag(){dataLayer.push(arguments);}
40  gtag('js', new Date());
41
42  gtag('config', '
42UA-124909880-1
vendor: 4 bytes, line 42
42');
43</script>
43
44  <meta name="google-site-verification" content="UZPxBQ89kGZH-0esLepNMLEBLhYCy5AXEnplB7eQzRA" />
45
46  <!-- Basic page needs ================================================== -->
47  <meta charset="utf-8">
48  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
49
50  
51  <link rel="icon" href="https://cdn.store-assets.com/s/227019/f/3850237.png" />
52  
53
54  <!-- Title and description ================================================== -->
55  <title>
56  東石蔡甫_書法作品 &ndash; 上友鋼模彫刻工藝社
57  </title>
58
59  
60  <meta name="description" content="上友鋼模工藝社創始人:東石蔡甫_書法作品">
61  
62
63  <!-- Social meta ================================================== -->
64  
65
66    <meta property="og:type" content="blog">
67    <meta property="og:title" content="東石蔡甫_書法作品">
68    <meta property="og:url" content="https://www.sunyours.com.tw/blogs/tsaifu-calligraphy">
69
70
71<meta property="og:description" content="上友鋼模工藝社創始人:東石蔡甫_書法作品">
72<meta property="og:site_name" content="上友鋼模彫刻工藝社">
73
74
75
76  <meta name="twitter:card" content="summary">
77
78
79
80
81  <meta name="twitter:title" content="東石蔡甫_書法作品">
82  <meta name="twitter:description" content="上友鋼模工藝社創始人:東石蔡甫_書法作品">
83
84
85
86
87  <!-- Helpers ================================================== -->
88  <link rel="canonical" href="https://www.sunyours.com.tw/blogs/tsaifu-calligraphy">
89  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
90  <meta name="theme-color" content="">
91
92  <!-- CSS ================================================== -->
93  <link href="https://store-themes.easystore.co/227019/themes/1592/assets/timber.css?v2?t=1787072457" rel="stylesheet" type="text/css" media="screen" />
94  <link href="https://store-themes.easystore.co/227019/themes/1592/assets/theme.css?v2?t=1787072457" rel="stylesheet" type="text/css" media="screen" />
95
96  
97
98
99
100
101  
101<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" type="text/javascript" ></script>
101
102  <!-- Header hook for plugins ================================================== -->
103  
104<!-- ScriptTags -->
105<script>window.__st={p: "blog",cid: null,cem: null,cph: null,cfn: null,cln: null,cge: null,cdb: null,ccc: null};</script>
105<script src='/assets/events.js'></script>
105<script>(function(){function asyncLoad(){var urls=['/assets/facebook-pixel.js?v=1.2.1724319536','/assets/traffic.js?v=1','https://apps.easystore.co/facebook-login/script.js?shop=staysunyours.easy.co&t=1724319481','https://apps.easystore.co/instagram-feed/script.js?shop=staysunyours.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>
105
106<!-- /ScriptTags -->
107
108
109  
110<!--[if lt IE 9]>
111<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js" type="text/javascript" ></script>
vendor: 2 bytes, line 111
111
112<script src="https://store-themes.easystore.co/227019/themes/1592/assets/respond.min.js?t=1787072457" type="text/javascript" ></script>
112
113<link href="https://store-themes.easystore.co/227019/themes/1592/assets/respond-proxy.html" id="respond-proxy" rel="respond-proxy" />
114<link href="//www.sunyours.com.tw/search?q=828ebd0ff12b4859ae7dfa681bd42716" id="respond-redirect" rel="respond-redirect" />
115<script src="//www.sunyours.com.tw/search?q=828ebd0ff12b4859ae7dfa681bd42716" type="text/javascript"></script>
115
116<![endif]-->
117
118
119
120  
120<script src="https://store-themes.easystore.co/227019/themes/1592/assets/modernizr.min.js?t=1787072457" type="text/javascript" ></script>
120
121
122  
123  
124  
124<script>
125  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
126  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
127  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
128  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
129
130  ga('create', '', 'auto','myTracker');
131  ga('myTracker.send', 'pageview');
132
133  </script>
133
134  
135<!-- Snippet:global/head: Instagram Feed -->
136<link rel="stylesheet" href="https://apps.easystore.co/assets/css/instagram-feed/insta-feed-style.css">
137<!-- /Snippet -->
138
139</head>
140
141<body id="-------------------------" class="template-blog" >
142<!-- Live Chat Widget powered by https://keyreply.com/chat/ -->
143<!-- Advanced options: -->
144<!-- data-align="left" -->
145<!-- data-overlay="true" -->
146<script data-align="right" data-overlay="false" id="keyreply-script" src="//keyreply.com/chat/widget.js" data-color="#03A9F4" data-apps="JTdCJTIybGluZSUyMjolMjJodHRwczovL2xpbmUubWUvUi90aS9wLyUyNTQwdHZpNDQ1NWglMjIsJTIycGhvbmUlMjI6JTIyMDIyOTU4MzIyMyUyMiwlMjJmYWNlYm9vayUyMjolMjJAc3VueW91cnMlMjIsJTIyZW1haWwlMjI6JTIyc3RheXN1bnlvdXJzQGdtYWlsLmNvbSUyMiU3RA=="></script>
146
147  <ul id="MobileNav" class="mobile-nav large--hide">
148
149  
150  
151  <li class="mobile-nav__link" aria-haspopup="true">
152    
153    <a href="/" >
154      最新消息
155    </a>
156    
157  </li>
158  
159  
160  <li class="mobile-nav__link" aria-haspopup="true">
161    
162    
163    <a href="/pages/工藝社介紹" class="mobile-nav__parent-link">
164      創始人介紹
165    </a>
166    <span class="mobile-nav__sublist-trigger">
167      <span class="icon-fallback-text mobile-nav__sublist-expand">
168  <span class="icon icon-plus" aria-hidden="true"></span>
169  <span class="fallback-text">+</span>
170</span>
171<span class="icon-fallback-text mobile-nav__sublist-contract">
172  <span class="icon icon-minus" aria-hidden="true"></span>
173  <span class="fallback-text">-</span>
174</span>
175
176    </span>
177    <ul class="mobile-nav__sublist">
178      
179      
180      <li class="mobile-nav__sublist-link" aria-haspopup="true">
181        
182        <a href="/pages/甫藝墨樂" >
183          甫藝墨樂
184        </a>
185        
186      </li>
187      
188      
189      <li class="mobile-nav__sublist-link" aria-haspopup="true">
190        
191        <a href="/blogs/tsaifu-calligraphy" >
192          東石蔡甫書法作品
193        </a>
194        
195      </li>
196      
197    </ul>
198    
199  </li>
200  
201  
202  <li class="mobile-nav__link" aria-haspopup="true">
203    
204    
205    <a href="/collections/all" class="mobile-nav__parent-link">
206      產品介紹
207    </a>
208    <span class="mobile-nav__sublist-trigger">
209      <span class="icon-fallback-text mobile-nav__sublist-expand">
210  <span class="icon icon-plus" aria-hidden="true"></span>
211  <span class="fallback-text">+</span>
212</span>
213<span class="icon-fallback-text mobile-nav__sublist-contract">
214  <span class="icon icon-minus" aria-hidden="true"></span>
215  <span class="fallback-text">-</span>
216</span>
217
218    </span>
219    <ul class="mobile-nav__sublist">
220      
221      
222      <li class="mobile-nav__sublist-link" aria-haspopup="true">
223        
224        <a href="/collections/鋼印" >
225          證書鋼印
226        </a>
227        
228      </li>
229      
230      
231      <li class="mobile-nav__sublist-link" aria-haspopup="true">
232        
233        <a href="/collections/手打鋼印" >
234          手打鋼印
235        </a>
236        
237      </li>
238      
239      
240      <li class="mobile-nav__sublist-link" aria-haspopup="true">
241        
242        <a href="/collections/手工金屬印章" >
243          手工金屬印章
244        </a>
245        
246      </li>
247      
248      
249      <li class="mobile-nav__sublist-link" aria-haspopup="true">
250        
251        <a href="/collections/branding-iron" >
252          訂製烙印系列產品
253        </a>
254        
255      </li>
256      
257    </ul>
258    
259  </li>
260  
261  
262  <li class="mobile-nav__link" aria-haspopup="true">
263    
264    <a href="/blogs/blog" >
265      成品分享
266    </a>
267    
268  </li>
269  
270  
271  <li class="mobile-nav__link" aria-haspopup="true">
272    
273    <a href="/pages/|友好實刻|" >
274      |友好實刻|
275    </a>
276    
277  </li>
278  
279  
280  <li class="mobile-nav__link" aria-haspopup="true">
281    
282    <a href="/pages/location" >
283      工廠位置
284    </a>
285    
286  </li>
287  
288
289  
290
291  
292  
293  
294  <li class="mobile-nav__link">
295    <a href="/account/login">登入</a>
296  </li>
297  
298  <li class="mobile-nav__link">
299    <a href="/account/register">加入會員</a>
300  </li>
301  
302  
303  
304  
305  
306    <li class="mobile-nav__link">
307      
308
309
310<label class="currency-picker__wrapper">
311  <!-- <span class="currency-picker__label">Pick a currency</span> -->
312  <select class="currency-picker" name="currencies" style="display: inline; width: auto; vertical-align: inherit;">
313  <option value="TWD" selected="selected">TWD</option>
314  
315    
316  
317    
318    <option value="HKD">HKD</option>
319    
320  
321    
322  
323  </select>
324</label>
325
326
327
328
329
330    </li>
331  
332  
333  <li class="mobile-nav__link header-bar__search-wrapper">
334    
335    <div class="header-bar__module header-bar__search">
336      
337  <a class="popup-with-form medium-down--hide" href="#test-form">
338    <span class="icon icon-search" aria-hidden="true"></span>
339  </a>
340  <form action="/search" method="get" class="header-bar__search-form clearfix large--hide" role="search">
341    
342    <button type="submit" class="btn icon-fallback-text header-bar__search-submit">
343      <span class="icon icon-search" aria-hidden="true"></span>
344      <span class="fallback-text">搜尋</span>
345    </button>
346    <input type="search" name="q" value="" aria-label="搜尋" class="header-bar__search-input" placeholder="搜尋" autocomplete="off">
347    <div class="dropdown" id="searchDropdown"></div>
348    <input type="hidden" name="search_history" id="search_history">
349  </form>
350
351
352
353<!-- form itself -->
354<div id="test-form" class="white-popup-block mfp-hide popup-search">
355  <div class="popup-search-content">
356    <form action="/search" method="get" class="input-group search-bar" role="search">
357      
358      <input type="search" name="q" value="" placeholder="搜尋" class="input-group-field" aria-label="搜尋" placeholder="搜尋" autocomplete="off">
359      <div class="dropdown" id="searchDropdown"></div>
360      <input type="hidden" name="search_history" id="search_history">
361      <span class="input-group-btn">
362        <button type="submit" class="btn icon-fallback-text">
363          <span class="icon icon-search" aria-hidden="true"></span>
364          <span class="fallback-text">搜尋</span>
365        </button>
366      </span>
367    </form>
368  </div>
369</div>
370
371<script src="https://store-themes.easystore.co/227019/themes/1592/assets/magnific-popup.min.js?t=1787072457" type="text/javascript" ></script>
vendor: 1 bytes, line 371
371
372<script>
373$(document).ready(function() {
374	$('.popup-with-form').magnificPopup({
375		type: 'inline',
376		preloader: false,
377		focus: '#name',
378      	mainClass: 'popup-search-bg-wrapper',
379
380		// When elemened is focused, some mobile browsers in some cases zoom in
381		// It looks not nice, so we disable it:
382		callbacks: {
383			beforeOpen: function() {
384				if($(window).width() < 700) {
385					this.st.focus = false;
386				} else {
387					this.st.focus = '#name';
388				}
389			}
390		}
391	});
392});
393</script>
393
394
395
396<script>
397  var _search_history_listings = ""
398  if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings));
399
400  function clearAll() {
401    localStorage.removeItem('searchHistory');
402  
403    var customer = "";
404    if(customer) {
405      // Your logic to clear all data or call an endpoint
406      fetch('/account/search_histories', {
407          method: 'DELETE',
408          headers: {
409            "Content-Type": "application/json",
410            "X-Requested-With": "XMLHttpRequest"
411          },
412          body: JSON.stringify({
413            _token: "7ZKuJSqc8S2mL6uu3u1Im8DzJfNgAS8dk72D4zRQ"
414          }),
415      })
416      .then(response => response.json())
417    }
418  }
419  // End - store view history in local storage
420  
421  // search history dropdown  
422  var searchInputs = document.querySelectorAll('input[type=search]');
423  
424  if(searchInputs.length > 0) {
425    
426    searchInputs.forEach((searchInput)=>{
427    
428      searchInput.addEventListener('focus', function() {
429        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
430        searchDropdown.innerHTML = ''; // Clear existing items
431  
432        // retrieve data from local storage
433        var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || [];
434  
435        // Convert JSON to string
436        var search_history_json = JSON.stringify(searchHistoryData);
437  
438        // Set the value of the hidden input
439        searchInput.closest('form').querySelector("#search_history").value = search_history_json;
440  
441        // create dropdown items
442        var clearAllItem = document.createElement('div');
443        clearAllItem.className = 'dropdown-item clear-all';
444        clearAllItem.textContent = 'Clear';
445        clearAllItem.addEventListener('click', function() {
446            clearAll();
447            searchDropdown.style.display = 'none';
448            searchInput.classList.remove('is-focus');
449        });
450        searchDropdown.appendChild(clearAllItem);
451  
452        // create dropdown items
453        searchHistoryData.forEach(function(item) {
454          var dropdownItem = document.createElement('div');
455          dropdownItem.className = 'dropdown-item';
456          dropdownItem.textContent = item.term;
457          dropdownItem.addEventListener('click', function() {
458            searchInput.value = item.term;
459            searchDropdown.style.display = 'none';
460          });
461          searchDropdown.appendChild(dropdownItem);
462        });
463  
464        if(searchHistoryData.length > 0){
465          // display the dropdown
466          searchInput.classList.add('is-focus');
467          document.body.classList.add('search-input-focus');
468          searchDropdown.style.display = 'block';
469        }
470      });
471  
472      searchInput.addEventListener("focusout", (event) => {
473        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
474        searchInput.classList.remove('is-focus');
475        searchDropdown.classList.add('transparent');
476        setTimeout(()=>{
477          searchDropdown.style.display = 'none';
478          searchDropdown.classList.remove('transparent');
479          document.body.classList.remove('search-input-focus');
480        }, 400);
481      });
482    })
483  }
484  // End - search history dropdown
485</script>
485
486    </div>
487    
488  </li>
489  
490  
491</ul>
492<div id="MobileNavOutside" class="mobile-nav-outside"></div>
493
494
495<div id="PageContainer" class="page-container">
496  
497<!-- Snippet:global/body_start: Console Extension -->
498<div id='es_console' style='display: none;'>227019</div>
499<!-- /Snippet -->
500
501  
502    <style>
503  .search-modal__form{
504    position: relative;
505  }
506  
507  .dropdown-wrapper {
508    position: relative;
509  }
510  
511  .dropdown-wrapper:hover .dropdown {
512    display: block;
513  }
514  
515  .header-icon-nav .dropdown {
516    left: -80px;
517  }
518  
519  .dropdown {
520    display: none;
521    position: absolute;
522    top: 100%;
523    left: 0px;
524    width: 100%;
525    padding: 8px;
526    background-color: #fff;
527    z-index: 1000;
528    border-radius: 5px;
529    border: 1px solid rgba(var(--color-foreground), 1);
530    border-top: none;
531    overflow-x: hidden;
532    overflow-y: auto;
533    max-height: 350px;
534    min-width: 150px;
535    box-shadow: 0 0 5px rgba(0,0,0,0.1);
536  }
537    
538  .dropdown a{
539    text-decoration: none;
540    color: #000 !important;
541  }
542  
543  .dropdown-item {
544    padding: 0.4rem 2rem;
545    cursor: pointer;
546    line-height: 1.4;
547    overflow: hidden;
548    text-overflow: ellipsis;
549    white-space: nowrap;
550  }
551  
552  .dropdown-item:hover{
553    background-color: #f3f3f3;
554  }
555  
556  .search__input.is-focus{
557    border-radius: 15px;
558    border-bottom-left-radius: 0;
559    border-bottom-right-radius: 0;
560    border: 1px solid rgba(var(--color-foreground), 1);
561    border-bottom: none;
562    box-shadow: none;
563  }
564  
565  .clear-all {
566    text-align: right;
567    padding: 0 2rem 0.2rem;
568    line-height: 1;
569    font-size: 70%;
570    margin-bottom: -2px;
571  }
572  
573  .clear-all:hover{
574    background-color: #fff;
575  }
576  
577  .referral-notification {
578    position: absolute;
579    top: 100%;
580    right: -12px;
581    background: white;
582    border: 1px solid #e0e0e0;
583    border-radius: 8px;
584    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
585    width: 280px;
586    z-index: 1000;
587    padding: 16px;
588    margin-top: 8px;
589    font-size: 14px;
590    line-height: 1.4;
591  }
592  
593  .referral-notification::before {
594    content: '';
595    position: absolute;
596    top: -8px;
597    right: 20px;
598    width: 0;
599    height: 0;
600    border-left: 8px solid transparent;
601    border-right: 8px solid transparent;
602    border-bottom: 8px solid white;
603  }
604  
605  .referral-notification::after {
606    content: '';
607    position: absolute;
608    top: -9px;
609    right: 20px;
610    width: 0;
611    height: 0;
612    border-left: 8px solid transparent;
613    border-right: 8px solid transparent;
614    border-bottom: 8px solid #e0e0e0;
615  }
616  
617  .referral-notification h4 {
618    margin: 0 0 8px 0;
619    color: #2196F3;
620    font-size: 16px;
621    font-weight: 600;
622  }
623  
624  .referral-notification p {
625    margin: 0 0 12px 0;
626    color: #666;
627  }
628  
629  .referral-notification .referral-code {
630    background: #f5f5f5;
631    padding: 8px;
632    border-radius: 4px;
633    font-family: monospace;
634    font-size: 13px;
635    text-align: center;
636    margin: 8px 0;
637    border: 1px solid #ddd;
638  }
639  
640  .referral-notification .close-btn {
641    position: absolute;
642    top: 8px;
643    right: 8px;
644    background: none;
645    border: none;
646    font-size: 18px;
647    color: #999;
648    cursor: pointer;
649    padding: 0;
650    width: 20px;
651    height: 20px;
652    line-height: 1;
653  }
654  
655  .referral-notification .close-btn:hover {
656    color: #333;
657  }
658  
659  .referral-notification .action-btn {
660    background: #2196F3;
661    color: white;
662    border: none;
663    padding: 8px 16px;
664    border-radius: 4px;
665    cursor: pointer;
666    font-size: 12px;
667    margin-right: 8px;
668    margin-top: 8px;
669  }
670  
671  .referral-notification .action-btn:hover {
672    background: #1976D2;
673  }
674  
675  .referral-notification .dismiss-btn {
676    background: transparent;
677    color: #666;
678    border: 1px solid #ddd;
679    padding: 8px 16px;
680    border-radius: 4px;
681    cursor: pointer;
682    font-size: 12px;
683    margin-top: 8px;
684  }
685  
686  .referral-notification .dismiss-btn:hover {
687    background: #f5f5f5;
688  }
689  .referral-modal__dialog {
690    transform: translate(-50%, 0);
691    transition: transform var(--duration-default) ease, visibility 0s;
692    z-index: 10000;
693    position: fixed;
694    top: 20vh;
695    left: 50%;
696    width: 100%;
697    max-width: 350px;
698    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
699    border-radius: 12px;
700    background-color: #fff;
701    color: #000;
702    padding: 20px;
703    text-align: center;
704  }
705  .modal-overlay.referral-modal-overlay {
706    position: fixed;
707    top: 0;
708    left: 0;
709    width: 100%;
710    height: 100%;
711    background-color: rgba(0, 0, 0, 0.7);
712    z-index: 2001;
713    display: block;
714    opacity: 1;
715    transition: opacity var(--duration-default) ease, visibility 0s;
716  }
717</style>
718
719<header class="header-bar">
720  <div class="header-wrapper wrapper">
721
722    <!--  Mobile hamburger  -->
723    <div class="large--hide">
724      <button type="button" class="mobile-nav-trigger" id="MobileNavTrigger">
725        <span class="icon icon-hamburger" aria-hidden="true"></span>
726      </button>
727    </div>
728    
729    <div class="logo-header" role="banner">
730
731            
732                  <div class="h1 site-header__logo" itemscope itemtype="http://schema.org/Organization">
733            
734                  
735                    
736                    
737                        
738                          <a href="/" class="logo-wrapper" itemprop="url">
739                            <img src="https://cdn.store-assets.com/s/227019/f/3850260.png?width=350&format=webp" alt="上友鋼模彫刻工藝社" itemprop="logo">
740                          </a>
741                        
742                    
743                    
744                  
745            
746              </div>
747            
748        
749    </div>
750    
751    <div class="desktop-header-nav medium-down--hide">
752      
753      <div class="header-nav-bar">
754          
755<ul class="site-nav" id="AccessibleNav">
756  
757    
758    
759      <li >
760        <a href="/"  class="site-nav__link">最新消息</a>
761      </li>
762    
763  
764    
765    
766      
767      <li class="site-nav--has-dropdown" aria-haspopup="true">
768        <a href="/pages/工藝社介紹"  class="site-nav__link">
769          創始人介紹
770          <span class="icon-fallback-text">
771            <span class="icon icon-arrow-down" aria-hidden="true"></span>
772          </span>
773        </a>
774        <ul class="site-nav__dropdown">
775          
776            
777            
778              <li >
779                <a href="/pages/甫藝墨樂"  class="site-nav__link">甫藝墨樂</a>
780              </li>
781            
782          
783            
784            
785              <li >
786                <a href="/blogs/tsaifu-calligraphy"  class="site-nav__link">東石蔡甫書法作品</a>
787              </li>
788            
789          
790        </ul>
791      </li>
792    
793  
794    
795    
796      
797      <li class="site-nav--has-dropdown" aria-haspopup="true">
798        <a href="/collections/all"  class="site-nav__link">
799          產品介紹
800          <span class="icon-fallback-text">
801            <span class="icon icon-arrow-down" aria-hidden="true"></span>
802          </span>
803        </a>
804        <ul class="site-nav__dropdown">
805          
806            
807            
808              <li >
809                <a href="/collections/鋼印"  class="site-nav__link">證書鋼印</a>
810              </li>
811            
812          
813            
814            
815              <li >
816                <a href="/collections/手打鋼印"  class="site-nav__link">手打鋼印</a>
817              </li>
818            
819          
820            
821            
822              <li >
823                <a href="/collections/手工金屬印章"  class="site-nav__link">手工金屬印章</a>
824              </li>
825            
826          
827            
828            
829              <li >
830                <a href="/collections/branding-iron"  class="site-nav__link">訂製烙印系列產品</a>
831              </li>
832            
833          
834        </ul>
835      </li>
836    
837  
838    
839    
840      <li >
841        <a href="/blogs/blog"  class="site-nav__link">成品分享</a>
842      </li>
843    
844  
845    
846    
847      <li >
848        <a href="/pages/|友好實刻|"  class="site-nav__link">|友好實刻|</a>
849      </li>
850    
851  
852    
853    
854      <li >
855        <a href="/pages/location"  class="site-nav__link">工廠位置</a>
856      </li>
857    
858  
859  
860  
861      
862        
863          
864        
865          
866        
867      
868  
869  
870  
871</ul>
872
873      </div>
874
875      <div class="header-subnav">
876        
877
878
879<label class="currency-picker__wrapper">
880  <!-- <span class="currency-picker__label">Pick a currency</span> -->
881  <select class="currency-picker" name="currencies" style="display: inline; width: auto; vertical-align: inherit;">
882  <option value="TWD" selected="selected">TWD</option>
883  
884    
885  
886    
887    <option value="HKD">HKD</option>
888    
889  
890    
891  
892  </select>
893</label>
894
895
896
897
898
899        
900        
901        <div class="header-icon-nav">
902        
903              
904        
905              
906            
907              
908              
909                
910                  <div class="header-bar__module">
911                    
912  <a class="popup-with-form medium-down--hide" href="#test-form">
913    <span class="icon icon-search" aria-hidden="true"></span>
914  </a>
915  <form action="/search" method="get" class="header-bar__search-form clearfix large--hide" role="search">
916    
917    <button type="submit" class="btn icon-fallback-text header-bar__search-submit">
918      <span class="icon icon-search" aria-hidden="true"></span>
919      <span class="fallback-text">搜尋</span>
920    </button>
921    <input type="search" name="q" value="" aria-label="搜尋" class="header-bar__search-input" placeholder="搜尋" autocomplete="off">
922    <div class="dropdown" id="searchDropdown"></div>
923    <input type="hidden" name="search_history" id="search_history">
924  </form>
925
926
927
928<!-- form itself -->
929<div id="test-form" class="white-popup-block mfp-hide popup-search">
930  <div class="popup-search-content">
931    <form action="/search" method="get" class="input-group search-bar" role="search">
932      
933      <input type="search" name="q" value="" placeholder="搜尋" class="input-group-field" aria-label="搜尋" placeholder="搜尋" autocomplete="off">
934      <div class="dropdown" id="searchDropdown"></div>
935      <input type="hidden" name="search_history" id="search_history">
936      <span class="input-group-btn">
937        <button type="submit" class="btn icon-fallback-text">
938          <span class="icon icon-search" aria-hidden="true"></span>
939          <span class="fallback-text">搜尋</span>
940        </button>
941      </span>
942    </form>
943  </div>
944</div>
945
946<script src="https://store-themes.easystore.co/227019/themes/1592/assets/magnific-popup.min.js?t=1787072457" type="text/javascript" ></script>
vendor: 1 bytes, line 946
946
947<script>
948$(document).ready(function() {
949	$('.popup-with-form').magnificPopup({
950		type: 'inline',
951		preloader: false,
952		focus: '#name',
953      	mainClass: 'popup-search-bg-wrapper',
954
955		// When elemened is focused, some mobile browsers in some cases zoom in
956		// It looks not nice, so we disable it:
957		callbacks: {
958			beforeOpen: function() {
959				if($(window).width() < 700) {
960					this.st.focus = false;
961				} else {
962					this.st.focus = '#name';
963				}
964			}
965		}
966	});
967});
968</script>
968
969
970
971<script>
972  var _search_history_listings = ""
973  if(_search_history_listings != "") localStorage.setItem('searchHistory', JSON.stringify(_search_history_listings));
974
975  function clearAll() {
976    localStorage.removeItem('searchHistory');
977  
978    var customer = "";
979    if(customer) {
980      // Your logic to clear all data or call an endpoint
981      fetch('/account/search_histories', {
982          method: 'DELETE',
983          headers: {
984            "Content-Type": "application/json",
985            "X-Requested-With": "XMLHttpRequest"
986          },
987          body: JSON.stringify({
988            _token: "7ZKuJSqc8S2mL6uu3u1Im8DzJfNgAS8dk72D4zRQ"
989          }),
990      })
991      .then(response => response.json())
992    }
993  }
994  // End - store view history in local storage
995  
996  // search history dropdown  
997  var searchInputs = document.querySelectorAll('input[type=search]');
998  
999  if(searchInputs.length > 0) {
1000    
1001    searchInputs.forEach((searchInput)=>{
1002    
1003      searchInput.addEventListener('focus', function() {
1004        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
1005        searchDropdown.innerHTML = ''; // Clear existing items
1006  
1007        // retrieve data from local storage
1008        var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || [];
1009  
1010        // Convert JSON to string
1011        var search_history_json = JSON.stringify(searchHistoryData);
1012  
1013        // Set the value of the hidden input
1014        searchInput.closest('form').querySelector("#search_history").value = search_history_json;
1015  
1016        // create dropdown items
1017        var clearAllItem = document.createElement('div');
1018        clearAllItem.className = 'dropdown-item clear-all';
1019        clearAllItem.textContent = 'Clear';
1020        clearAllItem.addEventListener('click', function() {
1021            clearAll();
1022            searchDropdown.style.display = 'none';
1023            searchInput.classList.remove('is-focus');
1024        });
1025        searchDropdown.appendChild(clearAllItem);
1026  
1027        // create dropdown items
1028        searchHistoryData.forEach(function(item) {
1029          var dropdownItem = document.createElement('div');
1030          dropdownItem.className = 'dropdown-item';
1031          dropdownItem.textContent = item.term;
1032          dropdownItem.addEventListener('click', function() {
1033            searchInput.value = item.term;
1034            searchDropdown.style.display = 'none';
1035          });
1036          searchDropdown.appendChild(dropdownItem);
1037        });
1038  
1039        if(searchHistoryData.length > 0){
1040          // display the dropdown
1041          searchInput.classList.add('is-focus');
1042          document.body.classList.add('search-input-focus');
1043          searchDropdown.style.display = 'block';
1044        }
1045      });
1046  
1047      searchInput.addEventListener("focusout", (event) => {
1048        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
1049        searchInput.classList.remove('is-focus');
1050        searchDropdown.classList.add('transparent');
1051        setTimeout(()=>{
1052          searchDropdown.style.display = 'none';
1053          searchDropdown.classList.remove('transparent');
1054          document.body.classList.remove('search-input-focus');
1055        }, 400);
1056      });
1057    })
1058  }
1059  // End - search history dropdown
1060</script>
1060
1061                  </div>
1062                
1063              
1064              
1065              
1066                <div class="header-bar__module dropdown-wrapper">
1067                  
1068                    <a href="/account/login">
1069
1070
1071
1072    <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>
1073
1074  
1075</a>
1076                  
1077
1078                  <!-- Referral Notification Popup for Desktop -->
1079                  <div id="referralNotification" class="referral-notification" style="display: none;">
1080                    <button class="close-btn" onclick="dismissReferralNotification()">&times;</button>
1081                    <div style="text-align: center; margin-bottom: 16px;">
1082                      <div style="width: 100px; height: 100px; margin: 0 auto;">
1083                        <img src="https://resources.easystore.co/storefront/icons/channels/vector_referral_program.svg">
1084                      </div>
1085                    </div>
1086                    <p id="referralSignupMessage" style="text-align: center; font-size: 14px; color: #666; margin: 0 0 20px 0;">
1087                      您的好友送您   回饋金!立即註冊領取。
1088                    </p>
1089                    <div style="text-align: center;">
1090                      <button class="btn" onclick="goToSignupPage()" style="width: 100%; color: #fff;">
1091                        註冊
1092                      </button>
1093                    </div>
1094                  </div>
1095                </div>
1096              
1097              
1098              <div class="header-bar__module cart-page-link-wrapper">
1099                <span class="header-bar__sep" aria-hidden="true"></span>
1100                <a href="/cart" class="cart-page-link">
1101                  <span class="icon icon-cart header-bar__cart-icon" aria-hidden="true"></span>
1102                  <span class="cart-count header-bar__cart-count hidden-count">0</span>
1103                </a>
1104              </div>
1105        
1106        
1107              
1108                
1109              
1110        
1111          
1112        </div>
1113      </div>
1114
1115      
1116      
1117    </div>
1118    
1119    
1120
1121    <!--  Mobile cart  -->
1122    <div class="large--hide">
1123      <a href="/cart" class="cart-page-link mobile-cart-page-link">
1124        <span class="icon icon-cart header-bar__cart-icon" aria-hidden="true"></span>
1125        <span class="cart-count  hidden-count">0</span>
1126      </a>
1127    </div>
1128    
1129  </div>
1130  
1131  
1132  
1133</header>
1134
1135
1136
1137
1138    
1139    <main class="wrapper main-content" role="main">
1140      <div class="grid">
1141          <div class="grid__item">
1142            
1143  
1144            <!-- paginate blog.articles by 5 %} -->
1145
1146<div class="grid">
1147
1148  <div class="grid__item large--four-fifths">
1149
1150    <div class="grid">
1151      <div class="grid__item large--ten-twelfths">
1152
1153        
1154        <header class="section-header">
1155          <h1 class="section-header__title h3">
1156            
1157              東石蔡甫_書法作品
1158            
1159          </h1>
1160        </header>
1161        
1162
1163        
1164          
1165
1166
1167          <div class="article">
1168
1169            <h2><a href="/blogs/tsaifu-calligraphy/蔡甫書法">蔡甫書法</a></h2>
1170            <p class="blog-date">
1171              <time datetime="2024-09-24">Sep 24, 24</time>
1172               
1173                 <span class="meta-sep">&#8226;</span>
1174                蔡甫
1175                              
1176            </p>
1177            
1178              
1179              <div><a href="/blogs/tsaifu-calligraphy/蔡甫書法"><img src="https://cdn.store-assets.com/s/227019/f/14013488.jpg?width=1200&format=webp" alt="蔡甫書法" class="article__image" /></a></div>
1180            
1181            <p>02 </p>
1182
1183            
1184            <div class="rte">
1185              
1186                <p></p>
1187              
1188            </div>
1189
1190            <p><a href="/blogs/tsaifu-calligraphy/蔡甫書法">閱讀更多 &rarr;</a></p>
1191
1192          </div>
1193        
1194
1195<!--  -->
1196
1197        
1198          
1199            <hr>
1200          
1201
1202
1203          <div class="article">
1204
1205            <h2><a href="/blogs/tsaifu-calligraphy/東石蔡甫-神清氣爽-草書作品">東石蔡甫-神清氣爽 草書作品</a></h2>
1206            <p class="blog-date">
1207              <time datetime="2024-09-23">Sep 23, 24</time>
1208               
1209                 <span class="meta-sep">&#8226;</span>
1210                MOMO
1211                              
1212            </p>
1213            
1214              
1215              <div><a href="/blogs/tsaifu-calligraphy/東石蔡甫-神清氣爽-草書作品"><img src="https://cdn.store-assets.com/s/227019/f/14006481.jpg?width=1200&format=webp" alt="東石蔡甫-神清氣爽 草書作品" class="article__image" /></a></div>
1216            
1217            <p>神清氣爽 2024.9.23</p>
1218
1219            
1220            <div class="rte">
1221              
1222                <p></p>
1223              
1224            </div>
1225
1226            <p><a href="/blogs/tsaifu-calligraphy/東石蔡甫-神清氣爽-草書作品">閱讀更多 &rarr;</a></p>
1227
1228          </div>
1229        
1230
1231<!-- <hr> -->
1232
1233        
1234
1235        
1236      </div>
1237    </div>
1238  </div>
1239
1240  <aside class="sidebar grid__item large--one-fifth">
1241    <h4>最新文章</h4>
1242
1243  <p>
1244    <a href="/blogs/tsaifu-calligraphy/蔡甫書法">蔡甫書法</a>
1245    <br>
1246    <time pubdate datetime="2024-09-24">
1247      <em class="text-light">Sep 24, 24</em>
1248    </time>
1249  </p>
1250
1251  <p>
1252    <a href="/blogs/tsaifu-calligraphy/東石蔡甫-神清氣爽-草書作品">東石蔡甫-神清氣爽 草書作品</a>
1253    <br>
1254    <time pubdate datetime="2024-09-23">
1255      <em class="text-light">Sep 23, 24</em>
1256    </time>
1257  </p>
1258
1259
1260
1261
1262  </aside>
1263
1264</div>
1265
1266 <!-- endpaginate %} -->
1267
1268  
1269            
1270          </div>
1271      </div>
1272  
1273    </main>
1274  
1275    <footer class="site-footer small--text-center" role="contentinfo">
1276  
1277      <div class="wrapper">
1278  
1279        <div class="grid-uniform">
1280  
1281          
1282          
1283          
1284          
1285            
1286          
1287          
1288          
1289            
1290          
1291          
1292          
1293  
1294          
1295              
1296            
1297  
1298          
1299  
1300          
1301            <div class="grid__item large--one-half medium--one-half">
1302              
1303              <h4>快速連結</h4>
1304              
1305              <ul class="site-footer__links">
1306                
1307                  <li><a href="https://www.facebook.com/sunyours/"  target="_blank" >上友 Facebook 粉絲頁</a></li>
1308                
1309                  <li><a href="/a/contact-form" >填寫匯款資料</a></li>
1310                
1311                  <li><a href="/pages/terms-of-service" >隱私政策</a></li>
1312                
1313                  <li><a href="/pages/return-policy" >退貨退款須知 Return policy</a></li>
1314                
1315                
1316              </ul>
1317            </div>
1318          
1319  
1320          
1321            <div class="grid__item large--one-half medium--one-half">
1322              <h4>關注我們</h4>
1323                
1324                <ul class="inline-list social-icons">
1325  
1326  
1327    <li>
1328      <a class="icon-fallback-text" href="https://www.facebook.com/sunyours/" title="上友鋼模彫刻工藝社在Facebook上" target="_blank">
1329        
1330
1331
1332
1333    <svg xmlns="http://www.w3.org/2000/svg" class="facebook-icon-svg social-icon-svg" viewBox="0 0 1024 1024">
1334        <title>icon-facebook</title>
1335        <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"/>
1336    </svg>
1337
1338  
1339
1340        <span class="fallback-text">Facebook</span>
1341      </a>
1342    </li>
1343  
1344  
1345    <li>
1346      <a class="icon-fallback-text" href="/" title="上友鋼模彫刻工藝社在Pinterest上" target="_blank">
1347         
1348
1349
1350
1351    <svg xmlns="http://www.w3.org/2000/svg" class="pinterest-icon-svg social-icon-svg" viewBox="0 0 1024 1024">
1352        <title>icon-pinterest</title>
1353        <path d="M787.12,295.62a346.51,346.51,0,0,0-113.57-94.17A342,342,0,0,0,564.26,166c-11.07-1.63-22.29-2.24-33.44-3.34-1.28-.13-2.54-.42-3.82-.63H497c-4.12.4-8.24.88-12.36,1.19a341.51,341.51,0,0,0-84.22,17.08A351,351,0,0,0,179.12,403.9a338.83,338.83,0,0,0-15.93,80.74c-.31,4.12-.79,8.24-1.19,12.36v30c.4,4.23.88,8.44,1.2,12.67a343.46,343.46,0,0,0,30.9,118.86A351.6,351.6,0,0,0,367.73,831c1.09.49,2.21.92,3.47,1.45,0-3.85.08-7.39,0-10.93-.81-29.78,3.57-58.84,10.64-87.73,13.78-56.39,26.84-113,40.16-169.46a7.16,7.16,0,0,0-.06-4.13,139.39,139.39,0,0,1-10.34-48.77c-.82-22.4,3.24-43.66,14.94-63,9.35-15.48,22-27.2,40.11-31.32S501,416,513.88,430.31c7.49,8.32,10.75,18.59,12,29.56,1.73,15.4-1.28,30.32-5.37,45-6.57,23.53-13.84,46.87-20.57,70.36-2.83,9.86-6.05,19.69-6.08,30.16-.07,26.81,18.3,48.76,44.77,53.23,24,4,44.94-3.17,63.34-18.43C618.64,626.31,630,608.5,638.86,589c10.39-22.91,16.49-47,19.79-71.92a298.29,298.29,0,0,0,2.8-47.58c-1-34.14-11.28-64.73-35.48-89.64-15.55-16-34.53-26.45-55.82-32.8-22.86-6.81-46.22-8.56-69.91-6.81-31.57,2.34-60.78,11.65-86.75,30-35.94,25.37-57.85,60-66.35,103a186.22,186.22,0,0,0-3.44,33.39c-.38,26.17,6.25,50.28,24,70.37,4.93,5.58,6.11,11.53,4,18.68-2.63,8.88-4.64,17.94-6.9,26.93-2.46,9.74-9.3,13.23-18.54,9.33-25.82-10.91-43.45-30.07-55.21-55.07-8.33-17.72-12.86-36.47-14.65-55.89-6.26-67.88,17.3-124.76,64.82-172.21,31.05-31,69-50.2,111.44-60.63a303.41,303.41,0,0,1,61.72-8.24c38.59-1.41,75.89,4.33,111.14,20.42,54.54,24.88,92.86,65,112.39,122.18,7.6,22.26,9.88,45.26,9.12,68.72-1,30.24-5.47,59.85-14.85,88.64-11,33.93-27.81,64.58-53.14,90C653,696.1,621.75,712.66,585,718.24c-20.28,3.08-40.44,3.26-60.21-3.2-18.27-6-34.52-15.13-46.79-30.36-1.83-2.27-3.38-4.77-5.32-7.54-2.33,9.24-4.55,18.1-6.82,26.94-5.75,22.5-11.32,45-17.34,67.47-7.05,26.23-19.43,50.08-33.58,73.07-.48.79-1,1.56-1.44,2.36a7.1,7.1,0,0,0-.27,1c7,1.77,13.93,3.67,20.95,5.29a336.64,336.64,0,0,0,57.13,8.15,17.33,17.33,0,0,1,2.63.55h36.75c3.61-.39,7.21-.85,10.82-1.17q120.79-10.68,209.65-93.21c52.05-48.53,85.94-107.86,102.13-177.21a330.52,330.52,0,0,0,8.17-57.73,17.08,17.08,0,0,1,.55-2.61V493.93c-.39-3.6-.84-7.21-1.15-10.82Q852,378.35,787.12,295.62Z" fill="#999"/><path d="M37.33,757.51l1.14.06a4.6,4.6,0,0,0-.65-.74Z" fill="#999"/>
1354    </svg>
1355
1356  
1357
1358        <span class="fallback-text">Pinterest</span>
1359      </a>
1360    </li>
1361  
1362  
1363  
1364    <li>
1365      <a class="icon-fallback-text" href="https://instagram.com/staysunyours/?hl=zh-tw" title="上友鋼模彫刻工藝社在Instagram上" target="_blank">
1366        
1367
1368
1369
1370    <svg xmlns="http://www.w3.org/2000/svg" class="instagram-icon-svg social-icon-svg" viewBox="0 0 1024 1024">
1371        <title>icon-instagram</title>
1372        <path d="M834.35,341.22a231.23,231.23,0,0,0-9.59-46.45,166.71,166.71,0,0,0-52.17-78.33c-17-14.41-36.33-24.44-57.44-31.3-21.52-7-43.69-10.21-66.19-11.12-22.28-.9-44.58-1.73-66.87-1.85-47.68-.26-95.37-.16-143.06,0-27.47.11-54.95.69-82.32,3.39a220.7,220.7,0,0,0-37.43,6.95c-26.2,7.26-50,19-70.24,37.45-18.06,16.4-32.3,35.52-41.87,58.05-9.89,23.29-15.13,47.68-16.69,72.82-1.23,19.78-2.06,39.6-2.32,59.41-.38,28.91-.1,57.82-.1,86.73-.23,39.92-.67,79.85,1,119.76.72,17.66,1.57,35.3,4.6,52.76,3.22,18.52,8.32,36.51,16.71,53.34C232.83,768,268.81,797,317.12,811a246.28,246.28,0,0,0,59.24,9.11c25.3.95,50.63,1.78,75.95,1.94,43.83.28,87.66.1,131.5,0,26-.08,52.08-.72,78.06-2.74a234.52,234.52,0,0,0,45.76-8c24.54-6.92,46.82-18.12,66.22-34.79,24.65-21.17,41.5-47.44,51.3-78.36,6.7-21.14,9.83-42.88,10.73-64.94.9-21.84,1.73-43.69,1.82-65.55q.33-78.21-.15-156.44C837.42,387.82,836.72,364.47,834.35,341.22Zm-55.3,232.84c-.12,20.41-1,40.84-2,61.24-1,19.2-4.13,38.08-11.74,55.92q-18.43,43.24-62.47,60c-14.36,5.48-29.3,8.3-44.55,9.53-27.07,2.18-54.21,2.63-81.36,2.73-21.31.07-42.62,0-63.93,0v-.16c-28.47,0-56.94.22-85.4-.09-17.5-.18-35-1-52.49-1.89-19.94-1-39.51-4.31-57.95-12.38q-41.6-18.2-58-60.68a162.37,162.37,0,0,1-9.95-45.62c-2-24.66-2.62-49.38-2.66-74.1-.09-50.88-.16-101.77.12-152.65.11-19,1-38.09,2-57.11a180,180,0,0,1,8.78-48.23c8.32-24.84,23.63-44.14,45.66-58.12,11.78-7.48,24.85-11.91,38.36-15,15.57-3.61,31.43-4.65,47.34-5.32,54.32-2.28,108.68-1.46,163-1.5,18.67,0,37.34.12,56,.56,15.84.38,31.7,1,47.51,2,18.33,1.18,36.27,4.59,53.19,12q41.67,18.25,58.1,60.83c5.67,14.7,8.64,30,9.91,45.63,2,25,2.63,50,2.67,75.09C779.25,475.82,779.35,524.94,779.05,574.06Z" fill="#999"/><path d="M513,330.12c-92-.34-167,74.55-167.08,166.87s74.71,167,167,167A166.86,166.86,0,0,0,679.77,497.12C679.87,405,605.46,330.45,513,330.12Zm-.29,275.31A108.38,108.38,0,1,1,621.21,497.15,108.38,108.38,0,0,1,512.7,605.43Z" fill="#999"/><path d="M686.47,284.5a39,39,0,1,0,38.92,39.14A39,39,0,0,0,686.47,284.5Z" fill="#999"/>
1373    </svg>
1374
1375  
1376
1377        <span class="fallback-text">Instagram</span>
1378      </a>
1379    </li>
1380  
1381  
1382  
1383  
1384  
1385  
1386  
1387    <li>
1388      <a class="icon-fallback-text" href="http://line.me/ti/p/%40tvi4455h" title="上友鋼模彫刻工藝社在Line上" target="_blank">
1389        
1390
1391
1392
1393    <svg xmlns="http://www.w3.org/2000/svg" class="line-icon-svg social-icon-svg" viewBox="0 0 1024 1024">
1394        <title>icon-line</title>
1395        <path d="M837.58,237.47c-15.8-26.86-38.14-46.42-66.73-58.78A128.73,128.73,0,0,0,734,168.78c-4.2-.47-8.42-.74-12.62-1.15a26.81,26.81,0,0,1-2.93-.63H306.1a21,21,0,0,1-3.19.65A141,141,0,0,0,193.7,227.18a136.92,136.92,0,0,0-24.4,60.54c-.5,3.45-.7,6.94-1.18,10.39a21.46,21.46,0,0,1-1.12,3.58V719.55a23.91,23.91,0,0,1,1.1,4.45,132.12,132.12,0,0,0,14.49,54.45c20.58,39.69,52.66,64.84,96.28,75.07a118.63,118.63,0,0,0,21.81,2.91,24.16,24.16,0,0,1,3.22.57H720.66a27.33,27.33,0,0,1,3.21-.57c39.53-2.53,72.32-18.87,98.47-48.43a136.51,136.51,0,0,0,32-65.32c1-4.85,1.26-9.82,1.91-14.73a24.25,24.25,0,0,1,.72-2.88V301.69a15.08,15.08,0,0,1-.69-2.9C855.25,276.76,848.7,256.38,837.58,237.47ZM753.76,544.74a189.6,189.6,0,0,1-23.32,42.11,208.16,208.16,0,0,1-32.15,34.76c-12.76,11.12-25.31,22.48-38.38,33.23-35.07,28.83-71.7,55.51-110.67,78.87-11.12,6.67-22.46,13-34.55,17.76a84.7,84.7,0,0,1-12.35,3.8c-7.29,1.65-11.22-1.26-11.62-8.72a53.45,53.45,0,0,1,.91-10.68c1-6.62,2.39-13.19,3.34-19.83a39.31,39.31,0,0,0-.35-14.26,19.77,19.77,0,0,0-11.3-14.11c-4.23-2-8.76-2.63-13.32-3.21a290.39,290.39,0,0,1-46-9.72c-31.07-9.18-59.84-23-85.77-42.53-26.73-20.1-48.32-44.61-63-74.85a170.66,170.66,0,0,1-17.05-78.18,163.09,163.09,0,0,1,10.07-52c9.7-26.44,25-49.27,44.73-69.19,21.9-22.09,47.44-38.86,75.76-51.51a289.28,289.28,0,0,1,59.46-19.08,260.46,260.46,0,0,1,31.59-4.72c5.31-.44,10.62-.92,15.94-1.22s10.65-.38,16-.56a339.27,339.27,0,0,1,36.88,2.27,290.8,290.8,0,0,1,77.23,19.51c31.72,12.85,60.21,30.74,84.43,55.11,18.57,18.67,33.22,40,43,64.52a172,172,0,0,1,12.08,63.78A164.42,164.42,0,0,1,753.76,544.74Z" fill="#999"/><path d="M569.52,425.37c-6,1.41-9.73,6.4-9.81,12.73-.08,5.62,0,11.23,0,16.84q0,18.63,0,37.26c0,.91.35,2-.72,2.89-.65-.81-1.25-1.5-1.79-2.22L537.86,467c-9.12-12.25-18.3-24.45-27.31-36.77-5.3-7.26-17.63-7.11-22.37.83a14.49,14.49,0,0,0-1.94,7.63q0,47.9,0,95.77c0,.55,0,1.11,0,1.66A13,13,0,0,0,492,546.28a13.78,13.78,0,0,0,8.7,2,12.25,12.25,0,0,0,10.14-5.75A13.27,13.27,0,0,0,513,535q0-26.91,0-53.82v-4a6,6,0,0,1,3,2.76q23,31.39,45.93,62.82c3.87,5.34,9.24,6.5,14.87,5.26a12.45,12.45,0,0,0,9.68-12.22c-.12-8.73,0-17.47,0-26.21,0-23.83-.07-47.66,0-71.49C586.46,430.63,580.05,422.88,569.52,425.37Z" fill="#999"/><path d="M634.92,451.78q15.18,0,30.35,0c1.28,0,2.57,0,3.86-.11a11.71,11.71,0,0,0,7.64-3.38c4.29-4.21,5-9.34,3.15-14.75s-6.18-8-11.81-8.46c-.91-.08-1.83,0-2.75,0h-45.8c-.83,0-1.66,0-2.48,0-6.18.33-11,4-12.41,9.55a23.69,23.69,0,0,0-.41,5.47q0,46.62,0,93.24c0,1.2,0,2.4.07,3.59a12.1,12.1,0,0,0,6.14,9.88,14.75,14.75,0,0,0,7.94,1.92q24,.06,48,0a22,22,0,0,0,5.69-.84c4.58-1.28,9.06-6.21,8.69-13.24-.3-5.93-4-10.89-9.7-12.24a20.57,20.57,0,0,0-4.65-.36c-10.48,0-21,0-31.45,0-1.25,0-2.49-.19-3.65-.28-.6-3.33-.48-19.09.17-21.34,1-.05,2.08-.15,3.16-.15,10.94,0,21.89-.12,32.83,0,7.09.1,15.12-5.73,13-16.47a12.57,12.57,0,0,0-12.66-10.21c-11-.05-22.07,0-33.1,0h-3.35c-.63-3.48-.52-19.31.12-21.54C632.58,451.93,633.75,451.78,634.92,451.78Z" fill="#999"/><path d="M414.9,521.65c-10.76,0-21.52,0-32.29,0h-3.84v-4.26c0-26.3,0-52.61,0-78.92a13.36,13.36,0,0,0-26.72-.65q.1,48.72,0,97.42a13,13,0,0,0,13,13.11c16.83-.14,33.67,0,50.5-.06a13.53,13.53,0,0,0,3.54-.38c10.55-2.9,11.23-14.46,7.49-20.26C423.89,523.39,419.8,521.66,414.9,521.65Z" fill="#999"/><path d="M466.59,436.12a18.43,18.43,0,0,0-2.09-5.59c-2.75-4.22-6.9-5.79-11.87-5.59a12.74,12.74,0,0,0-11.93,9.37,20.25,20.25,0,0,0-.41,4.93q0,23.6,0,47.19t0,47.47a19.84,19.84,0,0,0,.54,5.45c1.7,6,6.6,9.1,13.56,8.94a12.4,12.4,0,0,0,12.32-11.73c.07-1.1.06-2.21.06-3.31q0-46.5,0-93A17.09,17.09,0,0,0,466.59,436.12Z" fill="#999"/>
1396    </svg>
1397
1398  
1399
1400        <span class="fallback-text">Line</span>
1401      </a>
1402    </li>
1403  
1404  
1405  
1406</ul>
1407
1408            </div>
1409          
1410        </div>
1411  
1412        <hr class="hr--small hr--clear">
1413  
1414        
1415  
1416         <div class="grid">
1417           <div class="grid__item text-center">
1418             <p class="site-footer__links">
1418站內所有圖片皆為上友著作財產,如未經允許拷貝複製,我們將行使法律途徑 2026 上友鋼模</p>
1419             
1420             <p class="site-footer__links">
1421              
1422              
1423                
1424                  <a href="/legal/terms-of-service">隱私政策 PRIVACY POLICY</a>
1425                
1426                
1427              
1428                
1429                  | <a href="/legal/return-policy">退貨退款須知 Return policy</a>
1430                
1431                
1432              
1433             </p>
1434             
1435           </div>
1436         </div>
1437  
1438      </div>
1439    </footer>
1440  
1441    
1442  
1443    
1443<script src="https://store-themes.easystore.co/227019/themes/1592/assets/fastclick.min.js?t=1787072457" type="text/javascript" ></script>
1443
1444    
1444<script src="https://store-themes.easystore.co/227019/themes/1592/assets/timber.js?t=1787072457" type="text/javascript" ></script>
1444
1445    
1445<script src="https://store-themes.easystore.co/227019/themes/1592/assets/theme.js?t=1787072457" type="text/javascript" ></script>
1445
1446  
1447    
1448  
1449    
1450  
1451    
1452
1453<script src="/assets/currencies.js" type="text/javascript" ></script>
vendor: 2 bytes, line 1453
1453
1454<script src="/assets/jquery.currencies.min.js" type="text/javascript" ></script>
vendor: 2 bytes, line 1454
1454
1455<script src="/assets/currencies_format.js" type="text/javascript" ></script>
1455
1456
1457<script>
1458Currency.format = "money_with_currency_format";
1459var shopCurrency = 'TWD';
1460var selectedCurrency = '';
1461
1462
1463  Currency.convert = function(amount, from, to) {
1464    return amount;
1465  };
1466
1467  
1468if( $.cookie("currency") == null ){
1469  
1470  if( selectedCurrency != false ) {
1471
1472  Currency.convertAll(shopCurrency, selectedCurrency);
1473  jQuery('.selected-currency').text(Currency.currentCurrency);  
1474
1475  }
1476
1477}
1478
1479/* Sometimes merchants change their shop currency, let's tell our JavaScript file */
1480// Currency.moneyFormats[shopCurrency].money_with_currency_format = "";
1481// Currency.moneyFormats[shopCurrency].money_format = "NT$ {{amount}} ";
1482  
1483/* Default currency */
1484var defaultCurrency = 'TWD';
1485  
1486/* Cookie currency */
1487var cookieCurrency = Currency.cookie.read();
1488
1489$("input[name=current_currency]").val(cookieCurrency);
1490if(cookieCurrency == null){
1491  cookieCurrency = shopCurrency;
1492  Currency.cookie.write(shopCurrency);
1493}
1494/* Fix for customer account pages */
1495jQuery('span.money span.money').each(function() {
1496  jQuery(this).parents('span.money').removeClass('money');
1497});
1498/* Saving the current price */
1499jQuery('span.money').each(function() {
1500  jQuery(this).attr('data-currency-TWD', jQuery(this).html());
1501});
1502// If there's no cookie.
1503if (cookieCurrency == null) {
1504  if (shopCurrency !== defaultCurrency) {
1505    Currency.convertAll(shopCurrency, defaultCurrency);
1506  }
1507  else {
1508    Currency.currentCurrency = defaultCurrency;
1509  }
1510}
1511// If the cookie value does not correspond to any value in the currency dropdown.
1512else if (jQuery('[name=currencies]').size() && jQuery('[name=currencies] option[value=' + cookieCurrency + ']').size() === 0) {
1513  Currency.currentCurrency = shopCurrency;
1514  Currency.cookie.write(shopCurrency);
1515}
1516else if (cookieCurrency === shopCurrency) {
1517  Currency.currentCurrency = shopCurrency;
1518  Currency.convertAll(shopCurrency, cookieCurrency);
1519}
1520else {
1521  Currency.convertAll(shopCurrency, cookieCurrency);
1522}
1523jQuery('[name=currencies]').val(Currency.currentCurrency).change(function() {
1524  var newCurrency = jQuery(this).val();
1525  
1526  
1527    Currency.cookie.write(newCurrency)
1528    if ('blog' == 'cart') {
1529      const params = new URLSearchParams(window.location.search);
1530      params.set('delete_cache', 1);
1531      window.location.search = params;
1532    } else {
1533      window.location.reload();
1534    }
1535  
1536});
1537var original_selectCallback = window.selectCallback;
1538var selectCallback = function(variant, selector) {
1539  var currencies = null;
1540  original_selectCallback(variant, selector);
1541  if(typeof jQuery('[name=currencies]').val() == "undefined"){
1542    currencies = shopCurrency;
1543  }
1544  else{
1545    currencies = jQuery('[name=currencies]').val();
1546  }
1547  Currency.convertAll(shopCurrency, currencies);
1548  jQuery('.selected-currency').text(Currency.currentCurrency);
1549};
1550$('body').on('ajaxCart.afterCartLoad', function(cart) {
1551  Currency.convertAll(shopCurrency, jQuery('[name=currencies]').val());
1552  jQuery('.selected-currency').text(Currency.currentCurrency);  
1553});
1554jQuery('.selected-currency').text(Currency.currentCurrency);
1555</script>
1555
1556
1557
1558  
1559<!-- Snippet:global/body_end: Omnichat -->
1560<!-- Start of Omnichat code --> 
1560<script>var a=document.createElement('a');a.setAttribute('href','javascript:;');a.setAttribute('id','easychat-floating-button');var img=document.createElement('img');img.src='https://chat-plugin.easychat.co/icon.svg';a.appendChild(img);var span=document.createElement('span');span.setAttribute('id', 'easychat-unread-badge');span.setAttribute('style','display: none');var d1=document.createElement('div');d1.setAttribute('id','easychat-close-btn');d1.setAttribute('class','easychat-close-btn-close');var d2=document.createElement('div');d2.setAttribute('id','easychat-chat-dialog');d2.setAttribute('class','easychat-chat-dialog-close');var ifrm=document.createElement('iframe');ifrm.setAttribute('id','easychat-chat-dialog-iframe');ifrm.setAttribute('src','https://client-chat.easychat.co/?appkey=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0ZWFtTmFtZSI6IuS4iuWPi-mLvOaooSJ9.IO-XWOIyBCYK9ItlF6HDMryy_NaJlAUOZGwqy8b-QrM&lang=zh-Hant');ifrm.style.width='100%';ifrm.style.height='100%';ifrm.style.frameborder='0';ifrm.style.scrolling='on';d2.appendChild(ifrm);document.body.appendChild(a);document.body.appendChild(span);document.body.appendChild(d1);document.body.appendChild(d2);</script>
1560<script src='https://chat-plugin.easychat.co/easychat.js'></script>
1560 <!-- End of Omnichat code -->
1561<!-- /Snippet -->
1562
1563<!-- Snippet:global/body_end: Insert Code -->
1564
1565<!--Cal-->
1566<script>
1567(function() {
1568    // ==========================================
1569    // ⚙️ 價格與限制設定區 (方便日後修改)
1570    // ==========================================
1571    const PRICE_PER_Y = 330;   // 每 Y 的單價 (元)
1572    const MAX_Y_LIMIT = 14;    // 最大材數限制 (Y)
1573    const MIN_Y_LIMIT = 3;     // 最低基本費材數 (Y)
1574    // ==========================================
1575
1576    // 設定計時器,等待頁面載入並尋找計算機元素
1577    let checkAttempts = 0;
1578    let checkExist = setInterval(function() {
1579        checkAttempts++;
1580        const calcBtn = document.getElementById("webCalcBtn");
1581        const widthInput = document.getElementById("webMoldWidth");
1582        const heightInput = document.getElementById("webMoldHeight");
1583        
1584        // 如果找到了按鈕,代表這頁是計算機頁面,開始綁定功能
1585        if (calcBtn && widthInput && heightInput) {
1586            clearInterval(checkExist); // 停止尋找
1587            
1588            const moldBox = document.getElementById("webMoldBox");
1589            const boxLabel = document.getElementById("webBoxLabel");
1590            const resultPanel = document.getElementById("webResultPanel");
1591            const resDetail = document.getElementById("webResDetail");
1592            const resTitle = document.getElementById("webResTitle");
1593
1594            function updatePreview() {
1595                const w = parseFloat(widthInput.value) || 0;
1596                const h = parseFloat(heightInput.value) || 0;
1597                boxLabel.textContent = w + " x " + h + " cm";
1598
1599                const scale = 15; 
1600                let displayW = w * scale;
1601                let displayH = h * scale;
1602
1603                if (displayH > 160) { displayH = 160; displayW = (w / h) * 160; }
1604                if (displayW > 300) { displayW = 300; displayH = (h / w) * 300; }
1605
1606                moldBox.style.width = displayW + "px";
1607                moldBox.style.height = displayH + "px";
1608            }
1609
1610            widthInput.addEventListener("input", updatePreview);
1611            heightInput.addEventListener("input", updatePreview);
1612
1613            calcBtn.addEventListener("click", function() {
1614                const w = parseFloat(widthInput.value) || 0;
1615                const h = parseFloat(heightInput.value) || 0;
1616
1617                if (w <= 0 || h <= 0) {
1618                    resultPanel.style.display = "block";
1619                    resultPanel.className = "output-panel alert-mode";
1620                    resTitle.textContent = "提示 / Notice";
1621                    resDetail.textContent = "請輸入大於 0 的有效尺寸。";
1622                    return;
1623                }
1624
1625                const sum = w + h;
1626                let roundedY = Math.round(sum);
1627
1628                // 超過最大材數限制,提示聯繫客服
1629                if (roundedY > MAX_Y_LIMIT) {
1630                    resultPanel.style.display = "block";
1631                    resultPanel.className = "output-panel alert-mode";
1632                    resTitle.textContent = "超過線上估算範圍";
1633                    resDetail.innerHTML = "長寬總和 (L+W):" + sum.toFixed(2) + " cm<br>計費單位 (材數):" + roundedY + " Y<br><span class='contact-notice'>
1633請直接與上友聯繫,為您報價</span>";
1634                    return;
1635                }
1636
1637                // 低於最低起算材數,則以最低材數計算
1638                if (roundedY < MIN_Y_LIMIT) {
1639                    roundedY = MIN_Y_LIMIT;
1640                }
1641
1642                // 計算費用
1643                const calculatedPrice = roundedY * PRICE_PER_Y;
1644                
1645                resultPanel.style.display = "block";
1646                resultPanel.className = "output-panel"; 
1647                resTitle.textContent = "計算結果 / Calculation Result";
1648                resDetail.innerHTML = "長寬總和 (L+W):" + sum.toFixed(2) + " cm<br>計費單位 (材數):" + roundedY + " Y<br><span class='price-display'>NT$ " + calculatedPrice.toLocaleString() + "</span>";
1649            });
1650
1651            // 啟動第一次預覽
1652            updatePreview();
1653            
1654        } else if (checkAttempts > 20) {
1655            // 如果找了 20 次 (約 6 秒) 都沒找到,代表這不是計算機頁面,直接放手結束
1656            clearInterval(checkExist);
1657        }
1658    }, 300);
1659})();
1660</script>
1660
1661<!-- /Snippet -->
1662<script>
1663
1664  /*
1665
1666    ------
1667    Events
1668    ------
1669
1670    pages/viewed
1671
1672    customers/signup
1673
1674    customers/login
1675
1676    products/searched
1677
1678    collections/viewed
1679
1680    products/viewed
1681
1682    products/shared
1683
1684    wishlists/item_added
1685
1686    carts/items_added
1687
1688    carts/viewed
1689
1690    carts/item_removed
1691
1692    checkouts/initiated
1693
1694    checkouts/shipping_info_added
1695
1696    checkouts/payment_info_added
1697
1698    checkouts/completed
1699
1700    orders/placed
1701
1702    orders/purchased
1703
1704    payments/captured
1705
1706    payments/failed
1707
1708  */
1709
1710  window.__latest_cart = window.__latest_cart || null;
1711
1712  const _selector = document.querySelector.bind(document),
1713        _selectorAll = document.querySelectorAll.bind(document)
1714
1715  document.addEventListener('DOMContentLoaded', (event) => {
1716
1717    const default_currency = getCookie("currency")
1718    const customer_id = window.__st.cid
1719    const template    = window.__st.p
1720
1721    onPageView()
1722
1723    //-----------------------//
1724    //        Configs        //
1725    //-----------------------//
1726
1727    window.dataLayer = window.dataLayer || []
1728
1729    Array.prototype.last = Array.prototype.last || function() {
1730      return this[this.length - 1] || null
1731    }
1732
1733    Array.prototype.first = Array.prototype.first || function() {
1734      return this[0] || null
1735    }
1736
1737    //----------------------//
1738    //       Triggers       //
1739    //----------------------//
1740
1741    const XHR = window.XMLHttpRequest
1742
1743    function xhr() {
1744
1745      const xhr = new XHR()
1746
1747      xhr.addEventListener("readystatechange", function() {
1748
1749        if(xhr.readyState != 4) return
1750
1751        try {
1752
1753          const response_url = xhr.responseURL
1754
1755          if (response_url.includes("cart/add")) {
1756
1757            window.__latest_cart = JSON.parse(xhr.response)
1758
1759            onCartItemsAdded() // ok
1760
1761          }
1762
1763          if (response_url.includes("cart/remove_item_quantity")) {
1764
1765            window.__latest_cart = JSON.parse(xhr.response)
1766
1767            onCartItemRemoved() // ok
1768
1769          }
1770
1771          if (response_url.includes("new_cart?retrieve=true")) {
1772
1773            result = JSON.parse(xhr.response)
1774
1775            if (result.cart) {
1776              window.__latest_cart = result.cart
1777            }
1778
1779          }
1780
1781        } catch(e) {
1782
1783          console.error(e)
1784
1785        }
1786
1787      }, false);
1788
1789      return xhr
1790
1791    }
1792
1793    window.XMLHttpRequest = xhr
1794
1795    switch(template) {
1796
1797      case 'cart': onCartView() // ok
1798      break
1799      case 'product': onProductView() // ok
1800      break
1801      case 'collection': onCollectionView() // ok
1802      break
1803      case 'blog': onBlogView()
1804      break
1805      case 'article': onArticleView()
1806      break
1807      case 'payment_completed': onOrderPlace()
1808      break
1809      case 'payment_fail': onPaymentFail()
1810      break
1811
1812    }
1813
1814    // _selector('form[action="/checkout/payments"]').addEventListener("submit", onPaymentInfoAdded(_selector('form[action="/checkout/payments"]')))
1815    if (_selector('form[action="/checkout/detail"]'))                            _selector('form[action="/checkout/detail"]').addEventListener("submit", ()=>{onShippingInfoAdded(_selector('form[action="/checkout/detail"]'))})  // ok
1816    if (_selector('form[action="/checkout/shipping"]'))                          _selector('form[action="/checkout/shipping"]').addEventListener("submit", ()=>{onShippingInfoAdded(_selector('form[action="/checkout/shipping"]'))})  // ok
1817    if (_selector('form[action="/account/register"]'))                           _selector('form[action="/account/register"]').addEventListener("submit", onSignUp)  // ok
1818    if (_selector('form[action="/account/login"]'))                              _selector('form[action="/account/login"]').addEventListener("submit", onLogin)  // ok
1819    if (_selector('form[action="/search"]'))                                     _selector('form[action="/search"]').addEventListener("submit", onProductSearch()) // ok
1820    if (_selector('#line-login-btn'))                                            _selector('#line-login-btn').addEventListener('click', onLineLogin) // ok
1821    if (_selector('#PlaceOrder'))                                                _selector('#PlaceOrder').addEventListener("click", ()=>{onCheckoutComplete(_selector('form[action="/checkout/payments"]'))});  // ok
1822    if (_selector('#add_wishlist'))                                              _selector('#add_wishlist').addEventListener("click", onWishlistItemAdded) // ok
1823    if (_selectorAll('a[href="/account/logout"]'))                               _selectorAll('a[href="/account/logout"]').forEach(logoutButton => logoutButton.addEventListener("click", onLogout)) // ok
1824    if (_selector('.CartDrawerTrigger.cart-page-link'))                          _selector('.CartDrawerTrigger.cart-page-link').addEventListener("click", onCartView) // ok
1825    if (_selector('.CartDrawerTrigger.cart-page-link.mobile-cart-page-link'))    _selector('.CartDrawerTrigger.cart-page-link.mobile-cart-page-link').addEventListener("click", onCartView) // ok
1826    if (_selectorAll('a[class^="share-"]'))                                      _selectorAll('a[class^="share-"]').forEach(shareButton => shareButton.addEventListener("click", ()=>{onProductShare(shareButton)}) ) // ok
1827    if (_selectorAll('[name$="checkout"]'))                                      _selectorAll('[name$="checkout"]').forEach(checkoutButton => checkoutButton.addEventListener("click", onCheckoutInitiate))
1828
1829    // For append elements
1830    const bodyMutationObserver = new MutationObserver(() => {
1831      if (_selector('#form__spc #PlaceOrder'))             _selector('#form__spc #PlaceOrder').addEventListener("click", onSinglePageCheckout) // ok
1832      if (_selectorAll('[name$="checkout"]'))              _selectorAll('[name$="checkout"]').forEach(checkoutButton => checkoutButton.addEventListener("click", onCheckoutInitiate))
1833    });
1834    bodyMutationObserver.observe(_selector("body"), {subtree: true, childList: true});
1835
1836    //------------------------------//
1837    //        Event handlers        //
1838    //------------------------------//
1839
1840    function onPageView() {
1841
1842      EasyStore.Event.dispatch('pages/viewed', {
1843        page: {
1844          type: template,
1845          title: document.title,
1846          description: _selector('meta[name=description]') ? _selector('meta[name=description]').getAttribute('content') : null,
1847          url: location.href,
1848        }
1849      })
1850
1851    }
1852
1853    function onSignUp() {
1854
1855      const email_regex = new RegExp(/^[a-zA-Z0-9.!#$%&"*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)
1856      const phone_regex = new RegExp(/^(\+?6?01)[0-46-9]-*[0-9]{7,8}$/)
1857
1858      const email_or_phone = _selector(`input[name="customer[email_or_phone]"]`).value.replace("+", "").replace(/\s+/, "")
1859
1860      let data = {}
1861
1862      if (email_regex.test(email_or_phone)) {
1863        data.method = 'email'
1864        data.email = email_or_phone
1865      }
1866
1867      if (phone_regex.test(email_or_phone)) {
1868        data.method = "phone"
1869        data.phone = email_or_phone
1870      }
1871
1872      if (!data.method) return
1873
1874      EasyStore.Event.dispatch('customers/signup', data)
1875
1876    }
1877
1878    function onLogin() {
1879
1880      const email_regex = new RegExp(/^[a-zA-Z0-9.!#$%&"*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)
1881      const phone_regex = new RegExp(/^(\+?6?01)[0-46-9]-*[0-9]{7,8}$/)
1882
1883      const email_or_phone = _selector(`input[name="customer[email_or_phone]"]`).value.replace("+", "").replace(/\s+/, "")
1884
1885      let data = {}
1886
1887      if (email_regex.test(email_or_phone)) {
1888        data.method = 'email'
1889        data.email = email_or_phone
1890      }
1891
1892      if (phone_regex.test(email_or_phone)) {
1893        data.method = "phone"
1894        data.phone = email_or_phone
1895      }
1896
1897      if (!data.method) return
1898
1899      EasyStore.Event.dispatch('customers/login', data)
1900
1901    }
1902
1903    function onLineLogin() {
1904
1905      EasyStore.Event.dispatch('customers/login', { method: 'line' })
1906
1907    }
1908
1909    function onLogout() {
1910
1911      EasyStore.Event.dispatch('customers/logout', { customer_id })
1912
1913    }
1914
1915    function onBlogView() {
1916
1917      const blog = {"id":1049984,"handle":"tsaifu-calligraphy","url":"\/blogs\/tsaifu-calligraphy","title":"\u6771\u77f3\u8521\u752b_\u66f8\u6cd5\u4f5c\u54c1","description":"\u4e0a\u53cb\u92fc\u6a21\u5de5\u85dd\u793e\u5275\u59cb\u4eba:\u6771\u77f3\u8521\u752b_\u66f8\u6cd5\u4f5c\u54c1","articles_count":2,"all_tags":null,"comments_enabled":null,"moderated":null,"next_article":null,"previous_article":null,"tags":null,"updated_at":"2024-09-23T09:51:06.000+08:00","articles":[{"id":550280,"title":"\u8521\u752b\u66f8\u6cd5","handle":"\u8521\u752b\u66f8\u6cd5","url":"\/blogs\/tsaifu-calligraphy\/\u8521\u752b\u66f8\u6cd5","author":"\u8521\u752b","description":"02 ","image_url":"https:\/\/cdn.store-assets.com\/s\/227019\/f\/14013488.jpg","image":{"src":"https:\/\/cdn.store-assets.com\/s\/227019\/f\/14013488.jpg"}
1917,"published_at":"2024-09-24T10:00:51.000+08:00","updated_at":"2024-09-24T10:54:47.000+08:00"},{"id":550253,"title":"\u6771\u77f3\u8521\u752b-\u795e\u6e05\u6c23\u723d \u8349\u66f8\u4f5c\u54c1","handle":"\u6771\u77f3\u8521\u752b-\u795e\u6e05\u6c23\u723d-\u8349\u66f8\u4f5c\u54c1","url":"\/blogs\/tsaifu-calligraphy\/\u6771\u77f3\u8521\u752b-\u795e\u6e05\u6c23\u723d-\u8349\u66f8\u4f5c\u54c1","author":"MOMO","description":"\u795e\u6e05\u6c23\u723d 2024.9.23","image_url":"https:\/\/cdn.store-assets.com\/s\/227019\/f\/14006481.jpg","image":{"src":"https:\/\/cdn.store-assets.com\/s\/227019\/f\/14006481.jpg"},"published_at":"2024-09-23T09:54:24.000+08:00","updated_at":"2024-09-23T09:56:07.000+08:00"}]}
1918
1919      EasyStore.Event.dispatch('blogs/viewed', { blog })
1920
1921    }
1922
1923    function onArticleView() {
1924
1925      const article = ""
1926
1927      EasyStore.Event.dispatch('articles/viewed', { article })
1928
1929    }
1930
1931    function onProductSearch() {
1932
1933      const query = _selector('input[name=q]').value
1934
1935      if (!query) return
1936
1937      EasyStore.Event.dispatch('products/searched', { query })
1938
1939    }
1940
1941    function onCollectionView() {
1942
1943      const collection = ""
1944
1945      EasyStore.Event.dispatch('collections/viewed', { collection })
1946
1947    }
1948
1949    function onProductView() {
1950
1951      const product = ""
1952
1953      EasyStore.Event.dispatch("products/viewed", { product })
1954
1955    }
1956
1957    function onProductShare(el) {
1958
1959      const product = ""
1960
1961      const channel = el.getAttribute("class").split("-").last()
1962
1963      EasyStore.Event.dispatch('products/shared', { product, channel })
1964
1965    }
1966
1967    function onWishlistItemAdded() {
1968
1969      let product  = ""
1970      const quantity = _selector("#Quantity").value
1971
1972      EasyStore.Event.dispatch('wishlists/item_added', { product })
1973
1974    }
1975
1976    async function onCartItemsAdded() {
1977
1978      const cart = await getCart()
1979
1980      if(cart && cart.items != undefined && cart.items.length > 0) {
1981
1982        EasyStore.Event.dispatch('carts/item_added', { cart })
1983
1984      }
1985
1986    }
1987
1988    async function onCartView() {
1989
1990      const cart = await getCart()
1991
1992      EasyStore.Event.dispatch('carts/viewed', { cart })
1993
1994    }
1995
1996    async function onCartItemRemoved() {
1997
1998      const cart = await getCart()
1999
2000      cart.items = []
2001
2002      if(cart) {
2003
2004        EasyStore.Event.dispatch('carts/item_removed', { cart })
2005
2006      }
2007
2008    }
2009
2010    async function onCheckoutInitiate() {
2011
2012      const cart = await getCart()
2013
2014      EasyStore.Event.dispatch('checkouts/initiated', { cart })
2015
2016    }
2017
2018    async function onShippingInfoAdded(form) {
2019      let checkout = getCheckout()
2020
2021      let form_data = {}
2022      new FormData(form).forEach((value, key) => form_data[key] = value)
2023
2024      let shipping_tier = null
2025
2026      if (form_data.type && form_data.type.startsWith("r_pickup")) {
2027        shipping_tier = `Pickup - ${form_data.pick_location}`
2028      }
2029
2030      if (form_data.s_id) {
2031        shipping_tier = _selector(`input[id='`+form_data.s_id+`']`).getAttribute("data-shipping-name")
2032      }
2033
2034      if (!shipping_tier) return
2035
2036      EasyStore.Event.dispatch('checkouts/shipping_info_added', { checkout, shipping_tier })
2037
2038    }
2039
2040    async function onPaymentInfoAdded(form) {
2041
2042      let checkout = getCheckout()
2043
2044      let payment_type = new FormData(form).get('payment_method')
2045
2046      EasyStore.Event.dispatch("checkouts/payment_info_added", { checkout, payment_type })
2047
2048    }
2049
2050    async function onOrderPlace() {
2051
2052      let cart_token  = getCookie("cart_js")
2053      let previous_cart_token = getCookie("previous_cart_ga4_js")
2054
2055      if (previous_cart_token && previous_cart_token == cart_token) {
2056        // Prevent duplicate purchase tracking
2057        return
2058      }
2059
2060      let order = getOrder()
2061
2062      EasyStore.Event.dispatch('orders/placed', { order })
2063
2064      if(order.is_manual_payment) {
2065
2066        EasyStore.Event.dispatch('orders/purchased', { order })
2067
2068      }
2069
2070      const last_transaction = order.transactions.last()
2071
2072      if (last_transaction.status) {
2073
2074        EasyStore.Event.dispatch('orders/purchased', { order })
2075        EasyStore.Event.dispatch('payments/captured', { order })
2076
2077      }
2078
2079    }
2080
2081    async function onPaymentFail() {
2082
2083      const order = getOrder()
2084
2085      EasyStore.Event.dispatch('payments/failed', { order })
2086
2087    }
2088
2089    async function onCheckoutComplete(form) {
2090
2091      onPaymentInfoAdded(form)
2092
2093      const checkout = getCheckout()
2094
2095      EasyStore.Event.dispatch('checkouts/completed', { checkout })
2096
2097    }
2098
2099    async function onSinglePageCheckout() {
2100
2101      // let checkout = $("[data-app-checkout]").data("app-checkout")
2102
2103      let checkout = getCheckout()
2104
2105      // const payment_type = _selector("#app_spc_payment_method").find(`[class*="label-content"]`).first().find("b").first().text()
2106      const payment_type = _selector("#app_spc_payment_method").getElementsByClassName('label-content')[0].getElementsByTagName('b')[0].innerHTML
2107
2108      const shipping_method = _selector("#delivery_method").value
2109
2110      let shipping_tier = null
2111      let app_spc_customer_info_label = _selector("#app_spc_customer_info").getElementsByClassName('label-content')
2112      if (shipping_method == "shipping") {
2113        shipping_tier = app_spc_customer_info_label[app_spc_customer_info_label.length - 1].getElementsByTagName('b')[0].innerHTML
2114      }
2115
2116      if (shipping_method == "pickup") {
2117        shipping_tier = app_spc_customer_info_label[0].innerHTML
2118      }
2119
2120      if (shipping_tier) {
2121
2122        EasyStore.Event.dispatch('checkouts/shipping_info_added', {
2123          checkout,
2124          shipping_tier,
2125        })
2126
2127      }
2128
2129      if (payment_type) {
2130
2131        EasyStore.Event.dispatch('checkouts/payment_info_added', {
2132          checkout,
2133          payment_type,
2134        })
2135
2136      }
2137
2138      EasyStore.Event.dispatch('checkouts/completed', { checkout })
2139
2140    }
2141
2142  })
2143
2144
2145  //-----------------------//
2146  //       Functions       //
2147  //-----------------------//
2148
2149  function getCookie(name) {
2150
2151    name += "="
2152
2153    decodedCookie = decodeURIComponent(document.cookie)
2154
2155    ca = decodedCookie.split(";")
2156
2157    for(i = 0; i < ca.length; i++) {
2158      c = ca[i]
2159      while (c.charAt(0) == " ") {
2160        c = c.substring(1)
2161      }
2162      if (c.indexOf(name) == 0) {
2163        return c.substring(name.length, c.length)
2164      }
2165    }
2166
2167    return ""
2168
2169  }
2170
2171  const parsePrice = price => {
2172    if(typeof price === 'string') {
2173      return parseFloat(price.split(',').join(''))
2174    }
2175
2176    return price
2177  }
2178
2179  const requestCart = async (method, data) => {
2180
2181  let response = await fetch('/cart.json', {method: 'GET',headers: {'Content-Type': 'application/json'}})
2182    result = await response.json()
2183
2184    return result.cart
2185
2186  }
2187  const getCart = async (latest = false) => {
2188
2189    let cart = window.__latest_cart
2190
2191    const cart_invalid = !cart || !cart.items || (cart.total_price > 0 && !cart.items.length)
2192
2193    if(latest || cart_invalid) {
2194      cart = await requestCart()
2195    }
2196
2197    cart.items = cart.items || []
2198
2199    return mapCart(cart)
2200
2201  }
2202
2203  const getCheckout = async () => {
2204    mapCheckout(window.__latest_cart || await requestCart())
2205  }
2206
2207  const getOrder = async () => {
2208    mapOrder(window.__latest_cart || await requestCart())
2209  }
2210
2211  //-----------------------//
2212  //        Mappers        //
2213  //-----------------------//
2214
2215  const fallbackAttribute = (object, attribute) => {
2216
2217    if(!Array.isArray(attribute)) {
2218      attribute = [attribute]
2219    }
2220
2221    let final_value = null
2222
2223    do {
2224
2225      final_value = object[attribute.shift()]
2226
2227    } while(!final_value && attribute.length)
2228
2229    return final_value
2230
2231  }
2232
2233  const map = (object, mapper) => {
2234
2235    const newObject = {}
2236
2237    for(const key in mapper) {
2238
2239      // Handle different keys between new and old format
2240      newObject[key] = fallbackAttribute(object, mapper[key])
2241
2242      // Cast price to float
2243      if(newObject[key] && ['price', 'amount', 'discount', 'discounts'].some(x => key.endsWith(x))) {
2244        newObject[key] = parsePrice(newObject[key])
2245      }
2246
2247      if(newObject[key] === undefined) {
2248        delete newObject[key]
2249      }
2250
2251    }
2252
2253    return newObject
2254
2255  }
2256
2257  const mapCart = cart => {
2258
2259    const oldCart = cart
2260
2261    const mapper = {
2262      id: 'id',
2263      currency: 'currency',
2264      item_count: 'item_count',
2265      items: 'items',
2266      total_price: 'total_price',
2267      latest_items: 'latest_items'
2268    }
2269
2270    cart = map(cart, mapper)
2271
2272    const discounts = (oldCart.storewide_discounts || []).concat((oldCart.voucher_discounts || []))
2273
2274    cart.discount_applications = discounts.map(discount => ({
2275      title: discount.voucher_code || null,
2276      value: parsePrice(discount.amount),
2277    }))
2278
2279    cart.original_total_price = cart.items.length
2280    ? cart.items
2281      .map(item => item.original_price)
2282      .reduce((sum, price) => sum + price)
2283    : 0
2284
2285    cart.total_discount = cart.discount_applications.length
2286    ? cart.discount_applications
2287      .map(discount => parsePrice(discount.value))
2288      .reduce((sum, value) => sum + value)
2289    : 0
2290
2291    cart.items = cart.items.map(item => mapLineItem(item))
2292
2293    return cart
2294
2295  }
2296
2297  const mapCheckout = checkout => {
2298
2299    const mapper = {
2300      note: 'note',
2301      attributes: 'note_attributes',
2302      billing_address: 'billing_address',
2303      currency: 'currency',
2304      customer_id: 'customer_id',
2305      discounts_amount: 'total_discount',
2306      id: 'id',
2307      line_items: 'order_item',
2308      order_number: 'order_number',
2309      shipping_address: 'shipping_address',
2310      shipping_price: 'shipping_tax',
2311      shipping_method: 'shipping_method_name',
2312      tax_price: 'total_tax',
2313    }
2314
2315    checkout = map(checkout, mapper)
2316
2317    checkout.requires_shipping = checkout.line_items.some(item => item.shipping_required)
2318
2319    checkout.line_items = checkout.line_items.map(item => mapLineItem(item))
2320
2321    return checkout
2322
2323  }
2324
2325  const mapOrder = order => {
2326
2327    const mapper = {
2328      attributes: 'note_attributes',
2329      billing_address: 'billing_address',
2330      cancelled: 'is_cancelled',
2331      cancelled_at: 'cancelled_at',
2332      created_at: 'created_at',
2333      customer_id: 'customer_id',
2334      // discount_applications: 'discount_applications',
2335      email: 'email',
2336      financial_status: 'financial_status',
2337      fulfillment_status: 'fulfillment_status',
2338      line_items: 'order_item',
2339      note: 'note',
2340      order_number: 'order_number',
2341      phone: 'phone',
2342      shipping_address: 'shipping_address',
2343      shipping_methods: 'shipping_methods',
2344      shipping_price: 'total_shipping',
2345      subtotal_price: 'subtotal_price',
2346      // tax_lines: 'tax_lines',
2347      tax_price: 'total_tax',
2348      total_discounts: 'total_discount',
2349      total_net_amount: 'total_amount_include_transaction',
2350      total_price: 'total_price',
2351      transactions: 'transaction_records',
2352      is_manual_payment: 'is_manual_payment',
2353    }
2354
2355    order.email = order.billing_address.email
2356    order.phone = order.billing_address.phone
2357    order.shipping_method = order.shipping_method_name
2358
2359    order = map(order, mapper)
2360
2361    order.line_items = order.line_items.map(item => mapLineItem(item))
2362    order.transactions = order.transactions.map(transaction => mapTransaction(transaction))
2363
2364    return order
2365
2366  }
2367
2368  const mapLineItem = line_item => {
2369
2370    const old_line_item = line_item
2371
2372    const mapper = {
2373      final_price: 'price',
2374      image: 'img_url',
2375      message: 'message',
2376      original_line_price: 'original_line_price',
2377      original_price: 'original_price',
2378      properties: 'properties',
2379      quantity: 'quantity',
2380      requires_shipping: 'shipping_required',
2381      sku: 'sku',
2382      taxable: 'taxable',
2383      title: 'product_name',
2384      product_name: 'product_name',
2385      url: 'url',
2386      product_id: 'product_id',
2387      variant_id: 'variant_id',
2388      id: ['id', 'i_id'],
2389    }
2390
2391    line_item = map(line_item, mapper)
2392
2393    line_item.product_id = line_item.product_id || (old_line_item.product && old_line_item.product.id) || null
2394    line_item.variant_id = line_item.variant_id || (old_line_item.variant && old_line_item.variant.id) || null
2395    line_item.image      = line_item.image || (old_line_item.image && old_line_item.image.url) || null
2396
2397    return line_item
2398
2399  }
2400
2401  const mapTransaction = transaction => {
2402
2403    const mapper = {
2404      amount: 'amount',
2405      created_at: 'created_at',
2406      gateway: 'gateway_type',
2407      id: 'id',
2408      status: 'status',
2409    }
2410
2411    transaction = map(transaction, mapper)
2412
2413    return transaction
2414
2415  }
2416
2417
2418</script>
2418
2419
2420</div>
2421</body>
2422</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.