# 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;
}
```