星期六, 12月 13, 2025

[GAS] 引用 css、javascript

學習前端開發時,習慣會把 html、css、javascript 檔案拆開來維護,但 Vibe Coding 產生的 Code 都是全部放在一起,該筆記是要記錄如何拆分檔案且能正常執行,基本上是透過 HtmlService.createTemplateFromFile() 來達成該需求

html、css、javascript 全部在一起
.gs Code

使用 HtmlService.createHtmlOutputFromFile 直接呼叫 index.html
function doGet() {
  return HtmlService.createHtmlOutputFromFile('index')
       .setTitle('Google Apps Script 引用 css、javascript 檔案');     
}
index.html
<!DOCTYPE html>
<html>

<head>
  <base target="_top">
  <style>
    h2 {
      background-color: gray;
      text-align: left;
      padding: 10px;
    }
  </style>
</head>

<body>

  <h2>Google Apps Script 引用 css、javascript 檔案</h2>

  <button id="btnUpload" onclick="disableButton()">
    上傳檔案
  </button>

  <script>
    function disableButton() {
      const button = document.getElementById('btnUpload');

      if (button) { 
        button.innerText = "上傳處理中,請稍候... (From index.html)";

        button.disabled = true;

        button.style.backgroundColor = '#cccccc';
        button.style.color = '#666666';
        button.style.cursor = 'not-allowed';
      }      

    }
  </script>
</body>

</html>
執行結果

h2 以灰色背景呈現,按鈕按下去文字會變成 [上傳處理中,請稍候... (From index.html)]
拆分檔案

Google Apps Script 內只有 .html 和 .gs 兩種檔案格式,css 和 javascript 內容也是放在 html 檔案格式內,拆分後如下圖

.gs Code

因為 index.html 會呼叫 include() 函數來抓取 css.html 和 js.html 檔案,所以必須使用 HtmlService.createTemplateFromFile() 來呼叫 index.html
function doGet() {
  return HtmlService.createTemplateFromFile('index') // 回傳 HtmlTemplate
    .evaluate() // 把 HtmlTemplate 轉回 HtmlOuput
    .setTitle('Google Apps Script 引用 css、javascript 檔案');       
}

/**
 * index.html 內會透過呼叫 include() 來把 css.html 和 js.html 內容塞進 index.html 
 */
function include(fileName)
{
  return HtmlService.createHtmlOutputFromFile(fileName).getContent();
}
index.html

<?!= include("css") ?> 意思分兩個部分解釋
  • <? 函式 ?>:呼叫 .gs 檔案內的函式,即為 include()
  • !=:不進行 HTML 跳脫 (no escaping),會當成 html 語法的意思
<!DOCTYPE html>
<html>

<head>
  <base target="_top">
  <!-- 載入 css -->
  <?!= include("css") ?>
</head>

<body>

  <h2>Google Apps Script 引用 css、javascript 檔案</h2>

  <button id="btnUpload" onclick="disableButton()">
    上傳檔案
  </button>

  <!-- 載入 Javascript -->
  <?!= include("js") ?>
</body>

</html>
css.html

css 語法必須用 style 標籤包起來
<style>
h2 {
  background-color: green;
  text-align: left;
  padding: 10px;
}
</style>
js.html

javascript 語法必須用 script 標籤包起來
<script>
function disableButton() {
  const button = document.getElementById('btnUpload');

  if (button) { 

    button.innerText = "上傳處理中,請稍候... (From js html)";
    
    button.disabled = true;
    
    button.style.backgroundColor = '#cccccc'; 
    button.style.color = '#666666';
    button.style.cursor = 'not-allowed';
  }      
}
</script>
執行結果

h2 以綠色背景呈現,按鈕按下去文字會變成 [上傳處理中,請稍候... (From js.html)]

星期五, 12月 12, 2025

GodexRT730x-紙張偵測 sensor

公司內有 [一 Row 兩張] 的標籤紙,廠商來公司進行維修時請教對方,這類標籤紙在偵測結束後,按 [出紙鍵] 不會作動,直覺是偵測異常,經對方解釋後才理解,標籤機內 [紙張偵測 sensor] 是可以調整的,sensor 不要剛好置中就可以提高紙張偵測成功度

[一 Row 兩張] 標籤紙,不知道正式名稱該怎麼稱呼它,就隨興取個名字
下圖紅色箭頭為 [紙張偵測 sensor] 可以左右移動,[一 Row 兩張] 正中間剛好是空白,導致偵測成功率降低,往兩邊移動偵測,讓 sensor 可以實際偵測到紙張大小就是

星期三, 12月 10, 2025

[CSS] Blogger 排版設計

模擬 Blogger 手機版排版設計,電腦版排版設計右側 sidebar 會同時有多個區塊 (關於我、文章分類、依日期分類等),但在手機板上瀏覽,只會有 [關於我] 區塊沉在主要文章區塊下方

index.html
<!DOCTYPE html>
<html lang="zh-Hant-TW">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title>[CSS] Blogger 排版設計</title>
</head>

<body>
    <div class="wrap">

        <div class="item">
            <img src="https://125408140_c9204a223e_n.jpg" alt="台北大直橋">
            <h2>台北大直橋</h2>
            <p>台北大直橋是橫跨基隆河的一座醒目地標,以其獨特的白色拱形鋼纜設計而聞名,流線型的橋身優雅地劃過水面,極具現代感。夜幕降臨後,橋體會亮起多變的燈光秀,與周圍的內湖科技園區和美麗華摩天輪夜景相互輝映,是攝影愛好者的熱點。它不僅是重要的交通樞紐,更是一座融合工程與藝術的城市景觀橋。
            </p>
        </div>

        <div class="siderbar">
            <div class="aboutme">
                <h2>關於我</h2>
                <p>以下省略一萬字</p>
            </div>
            <div class="mobile-hide">
                <h2>文章分類</h2>
                <p>HTML</p>
                <p>CSS</p>
                <p>Javascript</p>
            </div>
            <div class="mobile-hide">
                <h2>依日期分類</h2>
                <p>2025 (77)</p>
                <p>2024 (108)</p>
            </div>
        </div>
    </div>
</body>

</html>
style.css
*,
*::before,
*::after {
    box-sizing: border-box;
}

.wrap {
    max-width: 1024px;
    margin: 0 auto;
    display: flex;
}

.content {
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1;
}

.item {
    padding: 10px;
    border: lightgray 1px solid;
}

.item img {
    display: block;
    margin: 0 auto;
}

.item h2 {
    text-align: center;
    font-size: 25px;
}

.siderbar {
    flex: 0 0 200px;
    padding: 20px;
    border: lightgray 1px solid;
}

@media(max-width: 992px) {

    /* 讓 content 和 sidebar 折行 */
    .wrap {
        flex-wrap: wrap;
    }

    .content,
    .siderbar {
        width: 100%; /* 確保 content 和 sidebar 佔滿 wrap  */
        flex: auto; /* 取消 flex 相關設定 */
    }

    /* sidebar 折行後,和 content 有底部間距 */
    .content {
        margin-bottom: 20px;
    }

    /* 移除 sidebar 的邊界和內距,不凸顯它的存在 */
    .siderbar {
        border: none;
        padding: 0;
    }

    /* 隱藏 mobile-hide */
    .mobile-hide {
        display: none;
    }

    /* 讓 aboutme 更像一個獨立區塊 */
    .aboutme {
        padding: 10px;
        border: lightgray 1px solid;
    }
}
效果呈現

星期六, 12月 06, 2025

[CSS] 雙欄流體式設計

透過 flex 屬性設計,讓雙欄式版面,達到 [右側固定、左側流體式設計],flex 屬性還可以細分為 flex-grow (預設值為 0)、flex-shrink (預設值為 1) 和 flex-basis 

右側:flex: 0 0 200px 代表
  • flex-grow: 0 (不成長)
  • flex-shrink: 0 (不收縮)
  • flex-basis: 200px (基礎寬度為 200px)
左側:flex: 1 代表
  • flex-grow: 1
  • flex-shrink: 1 (預設值)
  • flex-basis: 0%
該設定會自動填滿除了右側 200 px 外的所有空間

index.html
<!DOCTYPE html>
<html lang="zh-Hant-TW">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title>[CSS] 雙欄式設計</title>
</head>

<body>
    <div class="wrap">

        <div class="content">
            <div class="item">
                <img src="https://82534363_4f518a102e_n.jpg" alt="高雄愛河">
                <h2>高雄愛河</h2>
                <p>高雄愛河是穿梭都市的生命之水,兩岸綠樹成蔭,微風徐徐。夜間尤其迷人,河畔燈光倒映水面,波光粼粼,如同一條璀璨的銀帶。遊客可漫步親水步道,或搭乘愛之船,感受迎面而來的浪漫氣息。週末更有市集和街頭藝人,為這片靜謐的河景增添熱鬧與活力,是高雄最具代表性的休憩與觀光勝地。</p>
            </div>
        </div>

        <div class="siderbar">
                <div class="aboutme">
                    <h2>關於我</h2>
                    <p>以下省略一萬字</p>
                </div>            
                <div class="mobile-hide">
                    <h2>文章分類</h2>
                    <p>HTML</p>
                    <p>CSS</p>
                    <p>Javascript</p>
                </div>              
                <div class="mobile-hide">
                    <h2>依日期分類</h2>
                    <p>2025 (77)</p>
                    <p>2024 (108)</p>
                </div>                           
        </div>

    </div>
</body>
</html>
style.css
*,*::before,*::after {
    box-sizing: border-box;
}

.wrap{
    max-width: 1024px;
    margin: 0 auto;
    display: flex;
}

.content{
    display: flex;
    flex-direction: column;
    gap: 10px; 
    flex:1; 
}

.item{
    padding: 10px;
    border: lightgray 1px solid;
}

.item img{
    display: block;
    margin: 0 auto;
}

.item h2{
    text-align: center;
    font-size: 25px;
}

.siderbar{
    flex: 0 0 200px;
    padding: 20px;
    border: lightgray 1px solid;
}
效果呈現

星期一, 12月 01, 2025

[CSS] 三欄流體式設計

延續 [CSS] Flex 基礎練習 練習內容,該筆記要記錄三欄顯示會隨著瀏覽器縮小而變成兩欄、一欄,模擬在不同行動裝置上的 UI 顯示,會用上重點為
  • box-sizing:預設為 content-box,設定為 border-box 方便計算和應用
  • max-width:以父元素 (上一層) 寬度為判斷目標
    • 當父元素寬度高於設定值 (比較寬) 時:保持該寬度
    • 當父元素寬度低於設定值 (比較窄) 時:隨父元素寬度自動調整
  • flex-wrap:預設為 no-wrap,會設定 wrap,隨著瀏覽器縮小而折行
  • Media Query:判斷瀏覽器大小
    • 大螢幕:三欄 (約 1024px 以上)
    • 中螢幕:兩欄 (約 768px 到 992px 之間)
    • 小螢幕:一欄 (約 767px 以下)
Index.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title>[CSS] 三欄流體式設計</title>
</head>

<body>
    <div class="wrap">
        <div class="content">
            <div class="item">
                <img src="https://82534363_4f518a102e_n.jpg" alt="高雄愛河">
                <h2>高雄愛河</h2>
                <p>高雄愛河是穿梭都市的生命之水,兩岸綠樹成蔭,微風徐徐。夜間尤其迷人,河畔燈光倒映水面,波光粼粼,如同一條璀璨的銀帶。遊客可漫步親水步道,或搭乘愛之船,感受迎面而來的浪漫氣息。週末更有市集和街頭藝人,為這片靜謐的河景增添熱鬧與活力,是高雄最具代表性的休憩與觀光勝地。</p>
            </div>
            <div class="item">
                <img src="https://1776884718_0ed0417709_n.jpg" alt="溫哥華市中心">
                <h2>溫哥華市中心</h2>
                <p>溫哥華市中心坐擁壯麗的海灣景色,現代化的玻璃帷幕高樓直插雲霄,與湛藍的英吉利灣和布拉德內灣形成鮮明對比。街道充滿活力,從時尚的羅布森街到歷史悠久的蓋士鎮,處處可見繁忙的購物人潮、多元的餐飲文化。市區緊鄰史丹利公園,讓這座都會在繁華之餘,仍保有親近大自然的綠色魅力。</p>
            </div>
            <div class="item">
                <img src="https://125408140_c9204a223e_n.jpg" alt="台北大直橋">
                <h2>台北大直橋</h2>
                <p>台北大直橋是橫跨基隆河的一座醒目地標,以其獨特的白色拱形鋼纜設計而聞名,流線型的橋身優雅地劃過水面,極具現代感。夜幕降臨後,橋體會亮起多變的燈光秀,與周圍的內湖科技園區和美麗華摩天輪夜景相互輝映,是攝影愛好者的熱點。它不僅是重要的交通樞紐,更是一座融合工程與藝術的城市景觀橋。</p>
            </div>
        </div>
    </div>
</body>
</html>
style.css
*{
    box-sizing: border-box; /* 讓 padding 和 border 包含在 width 內 */
}

.wrap{
    max-width: 1024px;
    margin: 0 auto;
}

.content{
    display: flex;
    justify-content: center;
    gap: 10px; /* item 之間的間距 */
    flex-wrap: wrap; /* 允許折行 */
}

.item{
    width: 30%;
    padding: 10px;
    border: lightgray 1px solid;
}

.item img{
    width: 100%;
}

.item h2{
    text-align: center;
    font-size: 25px;
}

/* 中螢幕 */
@media (max-width:992px) {
	.item{
		width: 48%;
        margin-bottom: 10px;
	}
}

/* 小螢幕 */
@media (max-width:767px) {
	.item{
		width: 80%
	}
}
效果呈現