之外,所有表單字段都有 type 屬性。對于 元素,這個值等于 HTML 特性 type 的值。對于其他元素,這個 type 屬性的值如下表所列。
1.3.2共有的表單字段方法
每個表單字段都有兩個方法: focus() 和 blur() ;
focus() 方法用于將瀏覽器的焦點設置到表單字段,即激活表單字段,使其可以響應鍵盤事件。
HTML5 為表單字段新增了一個 autofocus 屬性。在支持這個屬性的瀏覽器中,只要設置這個屬性,不用 JavaScript 就能自動把焦點移動到相應字段。
blur() 方法,它的作用是從元素中移走焦點。在調用 blur()方法時,并不會把焦點轉移到某個特定的元素上;僅僅是將焦點從調用這個方法的元素上面移走而已。
1.3.3共有的表單字段事件
除了支持鼠標、鍵盤、更改和 HTML 事件之外,所有表單字段都支持下列 3 個事件。
blur: 當前字段失去焦點時觸發。
change: 對于 和
focus: 當前字段獲得焦點時觸發。
2、文本框腳本
在 HTML 中,有兩種方式來表現文本框:一種是使用 元素的單行文本框,另一種是使用
(1)要表現文本框,必須將 元素的 type 特性設置為"text"。而通過設置 size 特性,可以指定文本框中能夠顯示的字符數。通過 value 特性,可以設置文本框的初始值,而 maxlength 特性則用于指定文本框可以接受的最大字符數。
//創建一個文本框,讓它能夠顯示 25 個字符,但輸入不能超過 50 個字符
(2)
initial value
2.1 選擇文本
上述兩種文本框都支持 select()方法,這個方法用于選擇文本框中的所有文本。 在調用 select() 方法時,大多數瀏覽器( Opera 除外)都會將焦點設置到文本框中。這個方法不接受參數,可以在任何時候被調用。
var textbox = document.forms[0].elements["textbox1"];
textbox.select();
2.1.1 選擇(select)事件
與 select() 方法對應的,是一個 select 事件。在選擇了文本框中的文本時,就會觸發 select事件。另外,在調用 select()方法時也會觸發 select 事件。
var textbox = document.forms[0].elements["textbox1"];
EventUtil.addHandler(textbox, "select", function(event){
var alert("Text selected" + textbox.value);
});
2.1.2 取得選擇的文本
(1)采取的辦法是添加兩個屬性: selectionStart 和 selectionEnd 。這兩個屬性中保存的是基于 0 的數值,表示所選擇文本的范圍(即文本選區開頭和結尾的偏移量)。
function getSelectedText(textbox){
return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd);
}
因 為 substring() 方 法 基 于 字 符 串 的 偏 移 量 執 行 操 作 , 所 以 將 selectionStart 和selectionEnd 直接傳給它就可以取得選中的文本。 (2)IE8 及更早的版本中有一個 document.selection 對象,其中保存著用戶在整個文檔范圍內選擇的文本信息。
//獲取選中的文本
function getSelectedText(textbox){
if (typeof textbox.selectionStart == "number"){
return textbox.value.substring(textbox.selectionStart,
textbox.selectionEnd);
} else if (document.selection){
return document.selection.createRange().text;
}
}
2.1.3 選擇部分文本
(1)所有文本框都有一個setSelectionRange()方法 。這個方法接收兩個參數:要選擇的第一個字符的索引和要選擇的最后一個字符之后的字符的索引(類似于 substring()方法的兩個參數)。【IE9、 Firefox、 Safari、 Chrome 和 Opera 】
textbox.value = "Hello world!"
//選擇所有文本
textbox.setSelectionRange(0, textbox.value.length); //"Hello world!"
//選擇前 3 個字符
textbox.setSelectionRange(0, 3); //"Hel"
//選擇第 4 到第 6 個字符
textbox.setSelectionRange(4, 7); //"o w"
(2)IE 在所有文本框上提供的 createTextRange()方法創建一個范圍,并將其放在恰當的位置上。然后,再使用 moveStart()和 moveEnd()這兩個范圍方法將范圍移動到位。不過,在調用這兩個方法以前,還必須使用 collapse()將范圍折疊到文本框的開始位置。此時,moveStart()將范圍的起點和終點移動到了相同的位置,只要再給 moveEnd()傳入要選擇的字符總數即可。最后一步,就是使用范圍的 select()方法選擇文本?!綢E8 及更早版本】
textbox.value = "Hello world!";
var range = textbox.createTextRange();
//選擇所有文本
range.collapse(true);
range.moveStart("character", 0);
range.moveEnd("character", textbox.value.length); //"Hello world!"
range.select();
//選擇前 3 個字符
range.collapse(true);
range.moveStart("character", 0);
range.moveEnd("character", 3);
range.select(); //"Hel"
//選擇第 4 到第 6 個字符
range.collapse(true);
range.moveStart("character", 4);
range.moveEnd("character", 3);
range.select(); //"o w"
(3)跨瀏覽器實現選擇部分文本,可以將上述兩個方案組合起來。
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();
}
這個 selectText()函數接收三個參數:要操作的文本框、要選擇文本中第一個字符的索引和要選擇文本中最后一個字符之后的索引。首先,函數測試了文本框是否包含 setSelectionRange()方法。如果有,則使用該方法。否則,檢測文本框是否支持 createTextRange()方法。如果支持,則通過創建范圍來實現選擇。最后一步,就是為文本框設置焦點,以便用戶看到文本框中選擇的文本??梢韵裣旅孢@樣使用 selectText()方法。
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
2.2 過濾輸入
2.2.1 屏蔽字符
有時候,我們需要用戶輸入的文本中包含或不包含某些字符。如果只想屏蔽特定的字符,則需要檢測 keypress 事件對應的字符編碼,然后再決定如何響應。例如,下列代碼只允許用戶輸入數值。
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);
}
});
2.2.2 操作剪切板
下列就是 6 個剪貼板事件:
beforecopy :在發生復制操作前觸發。
copy :在發生復制操作時觸發。
beforecut :在發生剪切操作前觸發。
cut :在發生剪切操作時觸發。
beforepaste :在發生粘貼操作前觸發。
paste :在發生粘貼操作時觸發。
要訪問剪貼板中的數據,可以使用 clipboardData 對象。這個 clipboardData 對象有三個方法: getData() 、 setData() 和clearData() 。 其中, getData()用于從剪貼板中取得數據,它接受一個參數,即要取得的數據的格式;setData()方法的第一個參數也是數據類型,第二個參數是要放在剪貼板中的文本。
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);
}
},
}
2.3 自動切換焦點
使用 JavaScript 可以從多個方面增強表單字段的易用性。其中,最常見的一種方式就是在用戶填寫完當前字段時,自動將焦點切換到下一個字段。這種“自動切換焦點”的功能,可以通過下列代碼實現:
(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);
})();
開始的 tabForward()函數是實現“自動切換焦點”的關鍵所在。這個函數通過比較用戶輸入的值與文本框的 maxlength 特性,可以確定是否已經達到最大長度。如果這兩個值相等(因為瀏覽器最終會強制它們相等,因此用戶絕不會多輸入字符),則需要查找表單字段集合,直至找到下一個文本框。找到下一個文本框之后,則將焦點切換到該文本框。然后, 我們把這個函數指定為每個文本框的 onkeyup事件處理程序。由于 keyup 事件會在用戶輸入了新字符之后觸發,所以此時是檢測文本框中內容長度的最佳時機。這樣一來,用戶在填寫這個簡單的表單時,就不必再通過按制表鍵切換表單字段和提交表單了。
2.4 HTML5約束驗證API
2.4.1 必填字段
(1)第一種情況是在表單字段中指定了 required 屬性
(2)在 JavaScript 中,通過對應的 required 屬性,可以檢查某個表單字段是否為必填字段。
var isUsernameRequired = document.forms[0].elements["username"].required;
//使用下面這行代碼可以測試瀏覽器是否支持 required 屬性。
var isRequiredSupported = "required" in document.createElement("input");
2.4.2 其他輸入類型
(1)HTML5 為 元素的 type 屬性又增加了幾個值。這些新的類型不僅能反映數據類型的信息,而且還能提供一些默認的驗證功能。其中, "email" 和"url" 是兩個得到支持最多的類型.
(2)要檢測瀏覽器是否支持這些新類型,可以在 JavaScript 創建一個 元素,然后將 type 屬性設置為"email"或"url",最后再檢測這個屬性的值。不支持它們的舊版本瀏覽器會自動將未知的值設置為"text",而支持的瀏覽器則會返回正確的值。
var input = document.createElement("input");
input.type = "email";
var isEmailSupported = (input.type == "email");
2.4.3 數值范圍
HTML5 還定義了另外幾個輸入元素。這幾個元素都要求填寫某種基于數字的值: "number"、 "range"、 "datetime"、 "datetime-local"、 "date"、 "month"、 "week",還有"time"。
對所有這些數值類型的輸入元素,可以指定 min 屬性 (最小的可能值)、 max 屬性 (最大的可能值)和 step 屬性 (從 min 到 max 的兩個刻度間的差值)。
//讓用戶只能輸入 0 到 100 的值,而且這個值必須是 5 的倍數
以上這些屬性在 JavaScript 中都能通過對應的元素訪問(或修改)。此外,還有兩個方法: stepUp() 和 stepDown() ,都接收一個可選的參數:要在當前值基礎上加上或減去的數值。
input.stepUp(); //加 1
input.stepUp(5); //加 5
input.stepDown(); //減 1
input.stepDown(10); //減 10
2.4.4 輸入模式
HTML5 為文本字段新增了 pattern 屬性 。這個屬性的值是一個正則表達式,用于匹配文本框中的值。
//如果只想允許在文本字段中輸入數值,可以像下面的代碼一樣應用約束:
//在 JavaScript 中可以通過 pattern 屬性訪問模式。
var pattern = document.forms[0].elements["count"].pattern;
//使用以下代碼可以檢測瀏覽器是否支持 pattern 屬性。
var isPatternSupported = "pattern" in document.createElement("input");
2.4.5 檢測有效性
使用 checkValidity()方法 可以檢測表單中的某個字段是否有效。所有表單字段都有個方法,如果字段的值有效,這個方法返回 true,否則返回 false。
if (document.forms[0].elements[0].checkValidity()){
//字段有效,繼續
} else {
//字段無效
}
與 checkValidity()方法簡單地告訴你字段是否有效相比, validity 屬性 則會告訴你為什么字段有效或無效。這個對象中包含一系列屬性,每個屬性會返回一個布爾值。
customError :如果設置了 setCustomValidity(),則為 true,否則返回false。
patternMismatch:如果值與指定的pattern 屬性不匹配,返回true。
rangeOverflow:如果值比 max 值大,返回 true。
rangeUnderflow:如果值比 min 值小,返回true。
stepMisMatch:如果 min 和 max 之間的步長值不合理,返回true。
tooLong:如果值的長度超過了maxlength 屬性指定的長度,返回true。有的瀏覽器(如Firefox 4)會自動約束字符數量,因此這個值可能永遠都返回false。
typeMismatch:如果值不是"mail"或"url"要求的格式,返回true。
valid:如果這里的其他屬性都是false,返回 true。 checkValidity()也要求相同的值。
valueMissing:如果標注為 required 的字段中沒有值,返回true。
2.4.6 禁用驗證
通過設置 novalidate 屬性,可以告訴表單不進行驗證。
//在 JavaScript 中使用 noValidate 屬性可以取得或設置這個值,如果這個屬性存在,值為 true,如果不存在,值為 false。
document.forms[0].noValidate = true; //禁用驗證
如果一個表單中有多個提交按鈕,為了指定點擊某個提交按鈕不必驗證表單,可以在相應的按鈕上添加 formnovalidate 屬性。
//使用 JavaScript 也可以設置這個屬性。
//禁用驗證
document.forms[0].elements["btnNoValidate"].formNoValidate = true;
3、選擇框腳本
選擇框是通過和元素創建的。為了方便與這個控件交互,除了所有表單字段共有的屬性和方法外, HTMLSelectElement 類型還提供了下列屬性和方法。
add(newOption, relOption):向控件中插入新元素,其位置在相關項( relOption)之前。
multiple:布爾值,表示是否允許多項選擇;等價于 HTML 中的 multiple 特性。
options:控件中所有元素的 HTMLCollection。
remove(index):移除給定位置的選項。
selectedIndex:基于 0 的選中項的索引,如果沒有選中項,則值為-1。對于支持多選的控件,只保存選中項中第一項的索引。
size:選擇框中可見的行數;等價于 HTML 中的 size 特性;
選擇框的 type 屬性不是"select-one",就是"select-multiple",這取決于 HTML 代碼中有沒有 multiple 特性。選擇框的 value 屬性由當前選中項決定,相應規則如下。
如果沒有選中的項,則選擇框的 value 屬性保存空字符串。
如果有一個選中項,而且該項的 value 特性已經在 HTML 中指定,則選擇框的 value 屬性等于選中項的 value 特性。即使 value 特性的值是空字符串,也同樣遵循此條規則。
如果有一個選中項,但該項的 value 特性在 HTML 中未指定,則選擇框的 value 屬性等于該項的文本。
如果有多個選中項,則選擇框的 value 屬性將依據前兩條規則取得第一個選中項的值。
在 DOM 中,每個元素都有一個 HTMLOptionElement 對象表示。為便于訪問數據,HTMLOptionElement 對象添加了下列屬性:
index:當前選項在 options 集合中的索引。
label:當前選項的標簽;等價于 HTML 中的 label 特性。
selected:布爾值,表示當前選項是否被選中。將這個屬性設置為 true 可以選中當前選項。
text:選項的文本。
value:選項的值(等價于 HTML 中的 value 特性)。
推薦使用選項屬性取得選擇框中的文本和值。
var selectbox = document.forms[0]. elements["location"];
//推薦
var text = selectbox.options[0].text; //選項的文本
var value = selectbox.options[0].value; //選項的值
3.1 選擇選項
(1)對于只允許選擇一項的選擇框,訪問選中項的最簡單方式,就是使用選擇框的 selectedIndex 屬性 ;
var selectedOption = selectbox.options[selectbox.selectedIndex];
(2)另一種選擇選項的方式,就是取得對某一項的引用,然后將其 selected 屬性 設置為 true。
//下面的代碼會選中選擇框中的第一項:
selectbox.options[0].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;
}
3.2 添加選項
(1)第一種方式就是使用如下所示的DOM 方法 。
var newOption = document.createElement("option");
newOption.appendChild(document.createTextNode("Option text"));
newOption.setAttribute("value", "Option value");
selectbox.appendChild(newOption);
(2)第二種方式是使用 Option 構造函數 來創建新選項,Option 構造函數接受兩個參數:文本( text)和值( value);第二個參數可選。
var newOption = new Option("Option text", "Option value");
selectbox.appendChild(newOption); //在 IE8 及之前版本中有問題
(3)第三種添加新選項的方式是使用選擇框的 add()方法 。 DOM 規定這個方法接受兩個參數:要添加的新選項和將位于新選項之后的選項。如果想在列表的最后添加一個選項,應該將第二個參數設置為null。要想編寫跨瀏覽器的代碼,為第二個參數傳入 undefined,就可以在所有瀏覽器中都將新選項插入到列表最后了。
var newOption = new Option("Option text", "Option value");
selectbox.add(newOption, undefined); //最佳方案
3.3 移除選項
(1)首先,可以使用 DOM 的 removeChild() 方法,為其傳入要移除的選項
selectbox.removeChild(selectbox.options[0]); //移除第一個選項
(2)可以使用選擇框的 remove() 方法。這個方法接受一個參數,即要移除選項的索引
selectbox.remove(0); //移除第一個選項
(3)最后一種方式,就是將相應選項設置為 null
selectbox.options[0] = null; //移除第一個選項
//要清除選擇框中所有的項
function clearSelectbox(selectbox){
for(var i=0, len=selectbox.options.length; i < len; i++){
selectbox.remove(i);
}
}
3.4移動和重排選項
(1) DOM 的appendChild() 方法,就可以將第一個選擇框中的選項直接移動到第二個選擇框中。如果為 appendChild()方法傳入一個文檔中已有的元素,那么就會先從該元素的父節點中移除它,再把它添加到指定的位置。 (2)要將選擇框中的某一項移動到特定位置,最合適的 DOM 方法就是 insertBefore() ; appendChild()方法只適用于將選項添加到選擇框的最后。
4、表單序列化
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("&");
}
5、富文本編輯
所見即所得。這一技術 的本質,就是在頁面中嵌入一個包含空 HTML 頁面的 iframe。通過設置 designMode 屬性 ,這個空白的 HTML 頁面可以被編輯,而編輯對象則是該頁面
元素的 HTML 代碼。 designMode 屬性有兩個可能的值: "off"(默認值)和"on"。
5.1 使用contenteditable屬性
另一種編輯富文本內容的方式是使用名為 contenteditable 的特殊屬性,這個屬性也是由 IE 最早實現的。 可以把 contenteditable 屬性應用給頁面中的任何元素,然后用戶立即就可以編輯該元素。
contenteditable 屬性有三個可能的值: "true"表示打開、 "false"表示關閉, "inherit"表示從父元素那里繼承(因為可以在 contenteditable 元素中創建或刪除元素)。
5.2 操作富文本
與富文本編輯器交互的主要方式,就是使用 document.execCommand() ??梢詾?document.execCommand()方法傳遞 3 個參數:要執行的命令名稱、表示瀏覽器是否應該為當前命令提供用戶界面的一個布爾值和執行命令必須的一個值(如果不需要值,則傳遞 null)。為了確??鐬g覽器的兼容性,第二個參數應該始終設置為 false,因為 Firefox 會在該參數為 true 時拋出錯誤。
//可以在任何時候使用這些命令來修改富文本區域的外觀,如下面的例子所示。
//轉換粗體文本
frames["richedit"].document.execCommand("bold", false, null);
//轉換斜體文本
frames["richedit"].document.execCommand("italic", false, null);
//創建指向 www.wrox.com 的鏈接
frames["richedit"].document.execCommand("createlink", false,
"http://www.wrox.com");
//格式化為 1 級標題
frames["richedit"].document.execCommand("formatblock", false, "");
除了命令之外,還有一些與命令相關的方法。第一個方法就是 queryCommandEnabled() ,可以用它來檢測是否可以針對當前選擇的文本,或者當前插入字符所在位置執行某個命令。這個方法接收一個參數,即要檢測的命令。如果當前編輯區域允許執行傳入的命令,這個方法返回true,否則返回 false。
另外, queryCommandState() 方法用于確定是否已將指定命令應用到了選擇的文本。
最后一個方法是 queryCommandValue() ,用于取得執行命令時傳入的值(即前面例子中傳給document.execCommand()的第三個參數)。
5.3 富文本選區
在富文本編輯器中,使用框架( iframe)的 getSelection()方法,可以確定實際選擇的文本。這個方法是 window 對象和 document 對象的屬性,調用它會返回一個表示當前選擇文本的 Selection對象。每個 Selection 對象都有下列屬性:
anchorNode:選區起點所在的節點。
anchorOffset:在到達選區起點位置之前跳過的 anchorNode 中的字符數量。
focusNode:選區終點所在的節點。
focusOffset: focusNode 中包含在選區之內的字符數量。
isCollapsed:布爾值,表示選區的起點和終點是否重合。
rangeCount:選區中包含的 DOM 范圍的數量。
Selection 對象還有下列方法:
addRange(range):將指定的 DOM 范圍添加到選區中。
collapse(node, offset):將選區折疊到指定節點中的相應的文本偏移位置。
collapseToEnd():將選區折疊到終點位置。
collapseToStart():將選區折疊到起點位置。
containsNode(node):確定指定的節點是否包含在選區中。
deleteFromDocument(): 從文檔中刪除選區中的文本, 與document.execCommand("delete",false, null)命令的結果相同。
extend(node, offset):通過將 focusNode 和 focusOffset 移動到指定的值來擴展選區。
getRangeAt(index):返回索引對應的選區中的 DOM 范圍。
removeAllRanges():從選區中移除所有 DOM 范圍。實際上,這樣會移除選區,因為選區中至少要有一個范圍。
reomveRange(range):從選區中移除指定的 DOM 范圍。
selectAllChildren(node):清除選區并選擇指定節點的所有子節點。
toString():返回選區所包含的文本內容
5.4 表單與富文本
由于以這種方式構建的富文本編輯器并不是一個表單字段,因此在將其內容提交給服務器之前,必須將 iframe 或 contenteditable 元素中的 HTML 復制到一個表單字段中。 下面就是通過
//表單的 onsubmit 事件處理程序實現上述操作的代碼。
EventUtil.addHandler(form, "submit", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
target.elements["comments"].value = frames["richedit"].document.body.innerHTML;
});