---
# System prepended metadata

title: JS 常見問題
tags: [Develop, JS]

---

# JS 常見問題

###### tags: `Develop`, `JS`

## 套件：Select2
### 參考
- 官網：https://select2.org
- 自訂過濾條件： https://select2.org/searching

```javascript=
$(document).ready(function () {
    var ddl = $("#ddlMainIngredientsCategory");
    var lb = $("#lbMainIngredients");
    
    // 這段應該用 伺服器端 產生
    var mappingContent = [{
        "CategoryID": "a1450d8a-2a91-46eb-8c3d-4dd42b366559",
        "MainIngredientID": "ace632bd-f66a-4b44-b3f9-5118732ffbdf"
    }, {
        "CategoryID": "a1450d8a-2a91-46eb-8c3d-4dd42b366559",
        "MainIngredientID": "f68a9d33-de09-46e3-8463-64fb4e9a0bb0"
    }, {
        "CategoryID": "51cf12e1-9972-436c-b3e5-2704478fd180",
        "MainIngredientID": "7aa9cfa2-d67f-4132-9508-65044fa58370"
    }, {
        "CategoryID": "a1450d8a-2a91-46eb-8c3d-4dd42b366559",
        "MainIngredientID": "96c05f8b-8829-48f7-9df8-67569642b392"
    }, {
        "CategoryID": "a1450d8a-2a91-46eb-8c3d-4dd42b366559",
        "MainIngredientID": "7210a629-2761-461e-b05d-4862ab7fbac2"
    }, {
        "CategoryID": "a1450d8a-2a91-46eb-8c3d-4dd42b366559",
        "MainIngredientID": "8dbb830b-d62a-4676-baeb-4b5b66ae8e34"
    }, {
        "CategoryID": "a1450d8a-2a91-46eb-8c3d-4dd42b366559",
        "MainIngredientID": "205d5bf4-bda6-4960-918d-4beef284ce39"
    }];

    function matchStart(params, data) {
        var txtTerm = $.trim(params.term);
        var txtCateID = $.trim(ddl.find("option:selected").val());


        var canAdd = true;

        // 輸入字串過濾
        if (txtTerm.length > 0)
        {
            var txt = data.text.toLowerCase();
            var inp = txtTerm.toLowerCase();

            if (txt.indexOf(inp) == -1) {
                if (canAdd)
                    canAdd = false;
            }
        }


        // 分類過濾
        if (txtCateID.length > 0) {
            var id = data.id.toLowerCase();
            txtCateID = txtCateID.toLowerCase();


            var isExist = false;
            for (var i = 0; i < mappingContent.length; i++) {
                var item = mappingContent[i];

                var MI = item["MainIngredientID"].toLowerCase();
                var cateID = item["CategoryID"].toLowerCase();

                if (MI == data.id && cateID == txtCateID) {
                    isExist = true;
                    break;
                }
            }

            canAdd = (!canAdd) ? canAdd : isExist;
        }


        if (!canAdd)
            return null;

        return data;
    }

    lb.select2({
        maximumSelectionLength: 1,//限制數量設定
        placeholder: '請輸入關鍵字',
        language: 'zh-TW',
        width: '50%',// 最多字元限制
        maximumInputLength: 100,// 最少字元才觸發尋找, 0 不指定
        minimumInputLength: 0,// 當找不到可以使用輸入的文字
        tags: true,
        allowClear: true,//清除全部tag的關閉btn

        matcher: matchStart

    });


    lb.on('select2:select', function (e) {
        var data = e.params.data;
        console.log(data);
    });
});
```

### Select2 + AJAX

- templateResult, templateSelection 這兩個參數為必要
- tag 必須使用 select ，否則無法運作

- templateResult: 自定義輸出樣式，如果不想自定格式的話，直接回傳文字即可，否則回傳 html
    - 如果是讀取中，格式是： { disabled: true, loading: true, text: "Searching…" }
    
- templateSelection: 尚不確定，待查
- AJAX 的 Result 中， data 每個項目必須包含有叫做 id 的欄位 (小寫)，否則無法選取。


```javascript=
$(document).ready(function () {
    // 本範例使用 github 函式庫搜尋結果
    $("#test123").select2({
        placeholder: "Search for git repositories",
        allowClear: true,
        ajax: {
            url: "https://api.github.com/search/repositories",
            dataType: 'json',
            delay: 250,
            data: function(params) {
                return {
                    q: params.term, // search term
                    page: params.page
                };
            },
            processResults: function(data, params) {
                // parse the results into the format expected by Select2
                // since we are using custom formatting functions we do not need to
                // alter the remote JSON data, except to indicate that infinite
                // scrolling can be used
                params.page = params.page || 1;

                return {
                    results: data.items,
                    pagination: {
                        more: (params.page * 30) < data.total_count
                    }
                };
            },
            cache: true
        },
        escapeMarkup: function(markup) {
            return markup;
        }, // let our custom formatter work
        minimumInputLength: 1,
        templateResult: function (repo) {
            // 如果是讀取中，格式是： { disabled: true, loading: true, text: "Searching…" }
            if (repo.loading)   
                return repo.text;

            // 以下是不自定義標籤可以使用的方向
            //var markup = repo.full_name;

            // 以下是自定義標籤，範例中是將 Github 搜尋出的函式庫資訊格式化
            var markup = "<div class='select2-result-repository clearfix'>" +
               "<div class='select2-result-repository__meta'>" +
               "<div class='select2-result-repository__title'>" + repo.full_name + "</div>";
            if (repo.description) {
               markup += "<div class='select2-result-repository__description'>" + repo.description + "</div>";
            }
            markup += "<div class='select2-result-repository__statistics'>" +
               "<div class='select2-result-repository__forks'><i class='fa fa-flash'></i> " + repo.forks_count + " Forks</div>" +
               "<div class='select2-result-repository__stargazers'><i class='fa fa-star'></i> " + repo.stargazers_count + " Stars</div>" +
               "<div class='select2-result-repository__watchers'><i class='fa fa-eye'></i> " + repo.watchers_count + " Watchers</div>" +
               "</div>" +
               "</div></div>";
            return markup;
        }, // omitted for brevity, see the source of this page
        templateSelection: function (repo) {
            return repo.full_name || repo.text;
        } // omitted for brevity, see the source of this page
    });
});
```



## 檔案上傳
### html 5 做檔案容量上限
- [參考](https://phppot.com/jquery/file-size-validation-using-jquery/)

```htmlmixed=
<form name="frmFile" id="frmFile" 
      method="post" action="" onSubmit="return validate();">
    <div>
        <input type="file" name="file" id="file" class="demoInputBox" /> 
        <span id="file_error"></span>
    </div>
    <div><input type="submit" id="btnSubmit" value="Upload"/></div>
</form>
```

```javascript=
function validate() {
    var maxFileSizeMB = 10;
    var maxFileSizeLimit = maxFileSizeMB * 1024 * 1024;

    $("#file_error").html("");
    $(".demoInputBox").css("border-color","#F0F0F0");
    var file_size = $('#file')[0].files[0].size;
    if (file_size > maxFileSizeLimit) {
        var txt = "File size is greater than " + maxFileSizeMB + " MB.";
        $("#file_error").html(txt);
        $(".demoInputBox").css("border-color","#FF0000");
        return false;
    } 
    return true;
}
```


## 處理千分位符號
- [參考](https://www.codingem.com/comma-thousand-separator-in-javascript/)

```htmlmixed=
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    Source: <input type="text" id="source" value="1,234,567.3333" /> <br />
    Target: <input type="text" id="target" /> <br />
    <button type="button" id="btnGoGoGo" onclick="btnGoGoGoClick()">GOGOGO</button>
</body>

<script>
// 文字轉數字，並去除千分位符號
function parseNumber(txt) {
    var noCommaTxt = txt.replace(/[,]/g, "");
    var number = parseFloat(noCommaTxt, 10);
    return number;
}

// 加入千分位符號
function txtThousandFormat(float) {
    const formatted = float.toLocaleString('en-US');
    return formatted;
}

// 按鈕事件
function btnGoGoGoClick() {
    // 輸入
    var txt = document.getElementById("source").value;

    // 讀取數字，並在小數兩位四捨五入
    var number = parseNumber(txt);
    var rounded = Math.round(number * 100) / 100;

    // 輸出
    var result = txtThousandFormat(rounded);
    var inpOutput = document.getElementById("target");
    inpOutput.value = result;
}
</script>
</html>
```

## 日期格式化
- [參考](https://www.hiimray.co.uk/2023/10/06/format-js-datetime-tostring-like-csharp/1514)

```js
function DateToString(date, pattern) {
    let result = pattern;

    result = result.replace("fffffff", date.getMilliseconds().toString().padStart(7, '0'));
    result = result.replace("ffffff", date.getMilliseconds().toString().padStart(6, '0'));
    result = result.replace("fffff", date.getMilliseconds().toString().padStart(5, '0'));
    result = result.replace("yyyy", date.getFullYear().toString().padStart(4, '0'));
    result = result.replace("MMMM", "{1}");
    result = result.replace("dddd", "{2}");
    result = result.replace("ffff", date.getMilliseconds().toString().padStart(4, '0'));
    result = result.replace("yyy", date.getFullYear().toString().padStart(3, '0'));
    result = result.replace("MMM", "{3}");
    result = result.replace("ddd", "{4}");
    result = result.replace("fff", date.getMilliseconds().toString().padStart(3, '0'));
    result = result.replace("zzz", "");
    result = result.replace("yy", date.getFullYear().toString().slice(-2));
    result = result.replace("MM", (date.getMonth() + 1).toString().padStart(2, '0'));
    result = result.replace("dd", date.getDate().toString().padStart(2, '0'));
    result = result.replace("HH", date.getHours().toString().padStart(2, '0'));
    result = result.replace("hh", (date.getHours() > 12 ? (date.getHours() - 12) : date.getHours()).toString().padStart(2, '0'));
    result = result.replace("mm", date.getMinutes().toString().padStart(2, '0'));
    result = result.replace("ss", date.getSeconds().toString().padStart(2, '0'));
    result = result.replace("ff", date.getMilliseconds().toString().padStart(2, '0'));
    result = result.replace("tt", "{5}");
    result = result.replace("zz", "");
    result = result.replace("y", date.getFullYear().toString());
    result = result.replace("M", (date.getMonth() + 1).toString());
    result = result.replace("d", date.getDate().toString());
    result = result.replace("H", date.getHours().toString());
    result = result.replace("h", (date.getHours() > 12 ? (date.getHours() - 12) : date.getHours()).toString());
    result = result.replace("m", date.getMinutes().toString());
    result = result.replace("s", date.getSeconds().toString());
    result = result.replace("z", "");
    result = result.replace("t", "{6}");
    result = result.replace("Z", "");

    result = result.replace("{1}", date.toLocaleString('default', { month: 'long' }));
    result = result.replace("{2}", date.toLocaleString('default', { weekday: 'long' }));
    result = result.replace("{3}", date.toLocaleString('default', { month: 'short' }));
    result = result.replace("{4}", date.toLocaleString('default', { weekday: 'short' }));
    result = result.replace("{5}", (date.getHours() >= 12 ? "PM" : "AM"));
    result = result.replace("{6}", (date.getHours() >= 12 ? "P" : "A"));

    return result;
  }
```