《Javascript 高階程式設計(第三版)》筆記0x1A 表單指令碼
目錄
表單的基礎知識
在 HTML 中,表單是由<form>元素來表示的,而在 JavaScript 中,表單對應的則是 HTMLFormElement 型別。 HTMLFormElement 繼承了 HTMLElement,因而與其他 HTML 元素具有相同的預設屬性。不過, HTMLFormElement 也有它自己下列獨有的屬性和方法。
acceptCharset:伺服器能夠處理的字符集;等價於 HTML 中的 accept-charset 特性。
action:接受請求的 URL;等價於 HTML 中的 action 特性。
elements:表單中所有控制元件的集合(HTMLCollection)。
enctype:請求的編碼型別;等價於 HTML 中的 enctype 特性。
length:表單中控制元件的數量。
method:要傳送的 HTTP 請求型別,通常是"get"或"post";等價於 HTML 的 method 特性。
name:表單的名稱;等價於 HTML 的 name 特性。
reset():將所有表單域重置為預設值。
submit():提交表單。
target:用於傳送請求和接收響應的視窗名稱;等價於 HTML 的 target 特性。
///取得<form>元素
var form = document.getElementById("form1");
var firstForm = document.forms[0]; //取得頁面中的第一個表單
var myForm = document.forms["form2"]; //取得頁面中名稱為"form2"的表單
提交表單
<!-- 通用提交按鈕 -->
<input type="submit" value="Submit Form">
<!-- 自定義提交按鈕 -->
<button type="submit">Submit Form</button>
<!-- 影象按鈕 -->
<input type="image" src="graphic.gif">
瀏覽器會在將請求傳送給伺服器之前觸發 submit 事件。這樣就有機會驗證表單資料,並據以決定是否允許表單提交。
var form = document.getElementById("myForm");
EventUtil.addHandler(form, "submit", function(event){
//取得事件物件
event = EventUtil.getEvent(event);
//阻止預設事件
EventUtil.preventDefault(event);
});
//通過JavaScript提交表單,不會觸發submit事件,因此要記得在呼叫此方法之前先驗證表單資料。
var form = document.getElementById("myForm");
//提交表單
form.submit();
重置表單
<!-- 通用重置按鈕 -->
<input type="reset" value="Reset Form">
<!-- 自定義重置按鈕 -->
<button type="reset">Reset Form</button>
使用者單擊重置按鈕重置表單時,會觸發 reset 事件。利用這個機會,可以在必要時取消重置操作。
var form = document.getElementById("myForm");
EventUtil.addHandler(form, "reset", function(event){
//取得事件物件
event = EventUtil.getEvent(event);
//阻止表單重置
EventUtil.preventDefault(event);
});
//通過 JavaScript 來重置表單,呼叫 reset()方法會像單擊重置按鈕一樣觸發 reset 事件
var form = document.getElementById("myForm");
//重置表單
form.reset();
表單欄位
每個表單都有elements 屬性,該屬性是表單中所有表單元素(欄位)的集合。這個 elements 集合是一個有序列表,其中包含著表單中的所有欄位,例如<input>、 <textarea>、 <button>和<fieldset>。每個表單欄位在 elements 集合中的順序,與它們出現在標記中的順序相同,可以按照位置和 name 特性來訪問它們。
var form = document.getElementById("form1");
//取得表單中的第一個欄位
var field1 = form.elements[0];
//取得名為"textbox1"的欄位
//如果有多個表單控制元件都在使用一個 name(如單選按鈕),那麼就會返回以該 name 命名的一個NodeList
var field2 = form.elements["textbox1"];
//取得表單中包含的欄位的數量
var fieldCount = form.elements.length;
共有的表單欄位屬性
除了<fieldset>元素之外,所有表單欄位都擁有相同的一組屬性。表單欄位共有的屬性如下。
disabled:布林值,表示當前欄位是否被禁用。
form:指向當前欄位所屬表單的指標;只讀。
name:當前欄位的名稱。
readOnly:布林值,表示當前欄位是否只讀。
tabIndex:表示當前欄位的切換(tab)序號。
type:當前欄位的型別,如"checkbox"、 "radio",等等。
value:當前欄位將被提交給伺服器的值。對檔案欄位來說,這個屬性是隻讀的,包含著檔案在計算機中的路徑
var form = document.getElementById("myForm");
var field = form.elements[0];
//修改 value 屬性
field.value = "Another value";
//檢查 form 屬性的值
alert(field.form === form); //true
//把焦點設定到當前欄位
field.focus();
//禁用當前欄位
field.disabled = true;
//修改 type 屬性(不推薦,但對<input>來說是可行的)
field.type = "checkbox";
不能通過 onclick 事件處理程式來實現一些功能,原因是不同瀏覽器之間存在“時差”:有的瀏覽器會在觸發表單的 submit 事件之前觸發 click 事件,而有的瀏覽器則相反。對於先觸發 click 事件的瀏覽器,意味著會在提交發生之前禁用按鈕,結果永遠都不會提交表單。因此,最好是通過 submit 事件來禁用提交按鈕。
//避免多次提交表單
EventUtil.addHandler(form, "submit", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
//取得提交按鈕
var btn = target.elements["submit-btn"];
//禁用它
btn.disabled = true;
});
共有的表單欄位方法
每個表單欄位都有兩個方法: focus()和 blur()。focus()方法用於將瀏覽器的焦點設定到表單欄位,即啟用表單欄位,使其可以響應鍵盤事件。blur()方法,它的作用是從元素中移走焦點。在呼叫 blur()方法時,並不會把焦點轉移到某個特定的元素上;僅僅是將焦點從呼叫這個方法的元素上面移走而已。
共有的表單欄位事件
除了支援滑鼠、鍵盤、更改和 HTML 事件之外,所有表單欄位都支援下列 3 個事件。
blur:當前欄位失去焦點時觸發。
change:對於<input>和<textarea>元素,在它們失去焦點且 value 值改變時觸發;對於
<select>元素,在其選項改變時觸發。
focus:當前欄位獲得焦點時觸發
文字框指令碼
<input type="text" size="25" maxlength="50" value="initial value">
<textarea rows="25" cols="5">initial value</textarea>
選擇文字
上述兩種文字框都支援 select()方法,這個方法用於選擇文字框中的所有文字。在呼叫 select()方法時,大多數瀏覽器(Opera 除外)都會將焦點設定到文字框中。這個方法不接受引數,可以在任何時候被呼叫。
var textbox = document.forms[0].elements["textbox1"];
textbox.select();
//在文字框獲得焦點時選擇其所有文字
EventUtil.addHandler(textbox, "focus", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
target.select();
});
選擇(select)事件
var textbox = document.forms[0].elements["textbox1"];
EventUtil.addHandler(textbox, "select", function(event){
var alert("Text selected" + textbox.value);
});
取得選擇的文字
//取得使用者在文字框中選擇的文字
function getSelectedText(textbox){
return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd);
}
選擇部分文字
function selectText(textbox, startIndex, stopIndex){
if (textbox.setSelectionRange){
textbox.setSelectionRange(startIndex, stopIndex);
} else if (textbox.createTextRange){
var range = textbox.createTextRange();
range.collapse(true);
range.moveStart("character", startIndex);
range.moveEnd("character", stopIndex - startIndex);
range.select();
}
textbox.focus();
}
textbox.value = "Hello world!"
//選擇所有文字
selectText(textbox, 0, textbox.value.length); //"Hello world!"
//選擇前 3 個字元
selectText(textbox, 0, 3); //"Hel"
//選擇第 4 到第 6 個字元
selectText(textbox, 4, 7); //"o w"
過濾輸入
遮蔽字元
//遮蔽所有按鍵操作
EventUtil.addHandler(textbox, "keypress", function(event){
event = EventUtil.getEvent(event);
EventUtil.preventDefault(event);
});
//只允許使用者輸入數值
EventUtil.addHandler(textbox, "keypress", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
var charCode = EventUtil.getCharCode(event);
if (!/\d/.test(String.fromCharCode(charCode)) && charCode > 9 &&!event.ctrlKey){
EventUtil.preventDefault(event);
}
});
操作剪貼簿
var EventUtil = {
//省略的程式碼
getClipboardText: function(event){
var clipboardData = (event.clipboardData || window.clipboardData);
return clipboardData.getData("text");
},
//省略的程式碼
setClipboardText: function(event, value){
if (event.clipboardData){
return event.clipboardData.setData("text/plain", value);
} else if (window.clipboardData){
return window.clipboardData.setData("text", value);
}
},
//省略的程式碼
};
自動切換焦點
使用 JavaScript 可以從多個方面增強表單欄位的易用性。其中,最常見的一種方式就是在使用者填寫完當前欄位時,自動將焦點切換到下一個欄位。
<input type="text" name="tel1" id="txtTel1" maxlength="3">
<input type="text" name="tel2" id="txtTel2" maxlength="3">
<input type="text" name="tel3" id="txtTel3" maxlength="4">
(function(){
function tabForward(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (target.value.length == target.maxLength){
var form = target.form;
for (var i=0, len=form.elements.length; i < len; i++) {
if (form.elements[i] == target) {
if (form.elements[i+1]){
form.elements[i+1].focus();
}
return;
}
}
}
}
var textbox1 = document.getElementById("txtTel1");
var textbox2 = document.getElementById("txtTel2");
var textbox3 = document.getElementById("txtTel3");
EventUtil.addHandler(textbox1, "keyup", tabForward);
EventUtil.addHandler(textbox2, "keyup", tabForward);
EventUtil.addHandler(textbox3, "keyup", tabForward);
})();
HTML5 約束驗證API
必填欄位
<input type="text" name="username" required>
var isUsernameRequired = document.forms[0].elements["username"].required;
var isRequiredSupported = "required" in document.createElement("input");
其他輸入型別
<input type="email" name ="email">
<input type="url" name="homepage">
var input = document.createElement("input");
input.type = "email";
var isEmailSupported = (input.type == "email");
數值範圍
<!--只能輸入 0 到 100 的值,而且這個值必須是 5 的倍數-->
<input type="number" min="0" max="100" step="5" name="count">
輸入模式
<!--只允許在文字欄位中輸入數值-->
<input type="text" pattern="\d+" name="count">
檢測有效性
//使用 checkValidity()方法可以檢測表單中的某個欄位是否有效。
if (document.forms[0].elements[0].checkValidity()){
//欄位有效,繼續
} else {
//欄位無效
}
//validity屬性可說明為什麼欄位有效或無效
if (input.validity && !input.validity.valid){
if (input.validity.valueMissing){
alert("Please specify a value.")
} else if (input.validity.typeMismatch){
alert("Please enter an email address.");
} else {
alert("Value is invalid.");
}
}
禁用驗證
<form method="post" action="signup.php" novalidate>
<!--這裡插入表單元素-->
</form>
選擇框指令碼
選擇選項
//////////////////用選擇框的 selectedIndex 屬性////////////////////////////
var selectedIndex = selectbox.selectedIndex;
var selectedOption = selectbox.options[selectedIndex];
alert("Selected index: " + selectedIndex + "\nSelected text: " +
selectedOption.text + "\nSelected value: " + selectedOption.value);
///////////取得對某一項的引用,然後將其 selected 屬性設定為 true///////////
function getSelectedOptions(selectbox){
var result = new Array();
var option = null;
for (var i=0, len=selectbox.options.length; i < len; i++){
option = selectbox.options[i];
if (option.selected){
result.push(option);
}
}
return result;
}
var selectbox = document.getElementById("selLocation");
var selectedOptions = getSelectedOptions(selectbox);
var message = "";
for (var i=0, len=selectedOptions.length; i < len; i++){
message += "Selected index: " + selectedOptions[i].index +
"\nSelected text: " + selectedOptions[i].text +
"\nSelected value: " + selectedOptions[i].value + "\n\n";
}
alert(message);
新增選項
//DOM 方法
var newOption = document.createElement("option");
newOption.appendChild(document.createTextNode("Option text"));
newOption.setAttribute("value", "Option value");
selectbox.appendChild(newOption);
//使用 Option 建構函式來建立新選項
var newOption = new Option("Option text", "Option value");
selectbox.appendChild(newOption); //在 IE8 及之前版本中有問題
//使用選擇框的 add()方法
var newOption = new Option("Option text", "Option value");
selectbox.add(newOption, undefined); //最佳方案
移除選項
//DOM 的 removeChild()方法
selectbox.removeChild(selectbox.options[0]); //移除第一個選項
//選擇框的 remove()方法
selectbox.remove(0); //移除第一個選項
//將相應選項設定為 null
selectbox.options[0] = null; //移除第一個選項
//清除選擇框中所有的項
function clearSelectbox(selectbox){
for(var i=0, len=selectbox.options.length; i < len; i++){
selectbox.remove(i);
}
}
移動和重排選項
//將第一個選擇框中的第一個選項移動到第二個選擇框
var selectbox1 = document.getElementById("selLocations1");
var selectbox2 = document.getElementById("selLocations2");
selectbox2.appendChild(selectbox1.options[0]);
//在選擇框中向前移動一個選項的位置
var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index-1]);
//將選擇框中的選項向後移動一個位置
var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index+2]);
表單序列化
function serialize(form){
var parts = [],
field = null,
i,
len,
j,
optLen,
option,
optValue;
for (i=0, len=form.elements.length; i < len; i++){
field = form.elements[i];
switch(field.type){
case "select-one":
case "select-multiple":
if (field.name.length){
for (j=0, optLen = field.options.length; j < optLen; j++){
option = field.options[j];
if (option.selected){
optValue = "";
if (option.hasAttribute){
optValue = (option.hasAttribute("value") ?
option.value : option.text);
} else {
optValue = (option.attributes["value"].specified ?
option.value : option.text);
}
parts.push(encodeURIComponent(field.name) + "=" +
encodeURIComponent(optValue));
}
}
}
break;
case undefined: //欄位集
case "file": //檔案輸入
case "submit": //提交按鈕
case "reset": //重置按鈕
case "button": //自定義按鈕
break;
case "radio": //單選按鈕
case "checkbox": //複選框
if (!field.checked){
break;
}
/* 執行預設操作 */
default:
//不包含沒有名字的表單欄位
if (field.name.length){
parts.push(encodeURIComponent(field.name) + "=" +
encodeURIComponent(field.value));
}
}
}
return parts.join("&");
}
富文字編輯