《JavaScript高級程序設計》筆記:表單腳本(十四)

表單的基礎知識

在HTML中,表單是由<form>元素來表示的,而在JS中,表單對應的是HTMLFormElement類型。HTMLFormElement繼承了HTMLElement,於是與其它HTML元素具備相同的默認屬性。不過HTMLFormElement也有下列獨有的屬性和方法。javascript

  • acceptCharset:服務器可以處理的字符集;等價於HTML中的accept-charset特性。
  • action:接受請求的URL;等價於HTML中的action特性。
  • elements:表單中全部控件的集合。
  • enctype:請求的編碼類型;等價於HTML中的enctype特性。
  • length:表單中控件的數量。
  • method:要發送的http請求類型,一般是"get"或「post」;等價於HTML中method特性。
  • name:表單的名稱;等價於HTML的name特性。
  • reset():將全部表單域重置爲默認值。
  • submit():提交表單。
  • target:用於發送請求和接收響應的窗口名稱;等價於HTML中的target特性。

取得form元素引用的幾種方式,方式一:php

var form = document.getElementById('form1');

方式二:html

經過document.forms能夠取得頁面中的全部表單。在這個集合中,能夠經過索引或者name值來取得特定的表單。java

var firstForm = document.forms[0]; //取得頁面中的第一個表單
var myForm = document.forms['form1']; //取得頁面中名爲"form1"的表單

提交與重置表單

阻止表單提交:node

var form = document.getElementById('myForm');

//使用13章封裝的EventUtil對象
EventUtil.addHandler(form,'submit',function(event){
    
    //取得事件對象
    event = EventUtil.getEvent(event);
    
    //阻止默認事件(取消表單的提交)
    event.preventDefault(event);
})

提交與重置:正則表達式

var form = document.getElementById('myForm');
//提交表單
form.submit();

//重置表單
form.reset();

表單字段

每一個表單都有elements屬性,該屬性是全部表單中全部元素的集合。瀏覽器

var form = document.getElementById('myForm');

//取得表單中的第一個字段
var field1 = form.elements[0];

//取得名爲"textbox1"的字段
var field2 = form.elements['textbox1'];

//取得表單中包含的字段的數量
var fieldCount = form.elements.length;

若是有多個表單控件都在使用同一個name(好比單選按鈕),那麼就會返回以該name命名的一個nodeList。服務器

表單字段共有的屬性和方法:app

  • disabled:布爾值,表示當前字段是否被禁用。
  • form:指向當前字段所屬表單的指針;只讀。
  • name:當前字段的名稱。
  • readOnly:布爾值,表示當前字段是否只讀。
  • tabIndex:表示當前字段的切換(tab)序號。
  • type:當前字段的類型,如「checkbox」、「radio」等。
  • value:當前字段被提交到服務器的值。

除了form屬性以外,能夠經過JS動態修改其它任何屬性。函數

var form = document.getElementById('myForm');
var field = form.elements[0];

//修改value屬性
field.value = "Another value";

//檢查form屬性的值
console.log(field.form == form);

//把焦點設置到當前字段
field.focus();

//禁用當前字段
field.disabled = true;

//修改type屬性(不推薦,但對<input>來講是可行的)
field.type ="checkbox";

避免屢次提交表單,在第一次點擊提交表單後,設置提交按鈕disabled爲true,以下代碼:

var form = document.getElementById('myForm');

//避免屢次提交表單
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()。例如,在頁面加載完成後,把焦點轉移到表單中的第一個字段,以下代碼:

EventUtil.addHandler(window,"load",function(event){
    document.forms[0].elements[0].focus();
})

注意,若是第一個表單字段是<input>元素,且它的type特性的值爲「hidden」,那麼以上代碼會發生錯誤(高版本瀏覽器升級修復了該問題)。

HTML5爲表單字段新增長了一個autofocus屬性。

<input type="text"  autofocus/>

檢測瀏覽器是否支持該屬性:

EventUtil.addHandler(window,"load",function(event){
    var element = document.forms[0].elements[0];
    if(element.autofocus !== true){
        element.focus();
        console.log("JS focus");
    }
})

全部表單都支持focus()change()blur()這三個事件。以下例子:

var textbox = document.forms[0].elements[0];
EventUtil.addHandler(textbox,"focus",function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    if(target.style.background != 'red'){
        target.style.background = 'yellow';
    }
});
EventUtil.addHandler(textbox,"blur",function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    if(/[^\d]/.test(target.value)){
        target.style.background = 'red';
    }else{
        target.style.background = '';
    }
});
EventUtil.addHandler(textbox,"change",function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    console.log(target.value)
    if(/[^\d]/.test(target.value)){
        target.style.background = 'red';
    }else{
        target.style.background = '';
    }
})

文本框腳本

兩種方式表示文本框:<input><textarea>

<input>文本框,經過設置size屬性,能夠指定文本框中顯示的字符數。經過設置value特性,能夠設置文本框默認的初始值。而maxLength用於指定文本框能夠接受的最大字符數。

<input type="text" size="20" value="init value" maxlength="50"/>

對於<textarea>多行文本框而言,要指定文本框的大小,經過設置rows(指定文本框的字符行數)和cols(指定文本框的字符列數)。<textarea>的初始值必須放在<textarea>與</textarea>之間。

<textarea rows="25" cols="5"> init vaule</textarea>

選擇文本

上述兩種文本框都支持select()方法,這個方法用於選擇文本框中的全部文本。

var textbox = document.forms[0].elements["textbox"];
textbox.select();

文本框得到焦點,選擇其中全部文本,代碼以下:

var textbox = document.forms[0].elements["textbox"];
EventUtil.addHandler(textbox,"focus",function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    target.select();
})

1.選擇(select)事件

與select()方法對應的是一個select事件。在選擇了文本框的文本時,就會觸發select事件。不過到底何時觸發select事件,還會因瀏覽器而異。在IE9以及其它高版本瀏覽器中,當用戶選擇了文本(並且要釋放鼠標),纔會觸發select事件。而在IE8以及更早的版本中,只要用戶選擇了一個字母(沒必要釋放鼠標),就會觸發select事件。另外,在調用select()方法時也會觸發select事件。以下代碼:

var textbox = document.forms[0].elements["textbox"];
EventUtil.addHandler(textbox,"select",function(event){
    console.log("Text selected:" + textbox.value);    
})

2.取得選擇的文本

雖然select事件知道用戶何時選擇了文本,可是不知道用戶選擇了什麼文本。HTML5規範爲此添加了兩個屬性:selectionStartselectionEnd。這兩個屬性保存的是基於0的數值,表示所選擇文本的範圍(即文本選區開頭和結尾的偏移量)。

function getSelectedText(textbox){
    return textbox.value.substring(textbox.selectionStart,textbox.selectionEnd);
}
var textbox = document.forms[0].elements["textbox"];
EventUtil.addHandler(textbox,"select",function(event){
    console.log("Text selected:" + getSelectedText(textbox));    
})

IE8及以前的版本不支持這兩個屬性,有一個document.selection對象,其中保存着用戶在整個文檔範圍內選擇的文本信息;也就是說,沒法確認用戶選擇的是頁面中哪一個部位的文本。不過在和select事件一塊兒使用的時候,能夠假定是用戶選擇了文本框中的文本,於是觸發了該事件。要取得選中的文本,首先必須建立一個範圍,而後將文本從其中提取出來。代碼以下:

function getSelectedText(textbox){
    if(typeof textbox.selectionStart == 'number'){
        return textbox.value.substring(textbox.selectionStart,textbox.selectionEnd);
    }else if(document.selection){
        document.selection.createRange().text;
    }    
}

3.選擇部分文本

HTML5也爲選擇文本框中的部分文本提供瞭解決方案,即setSelectionRange(),這個方法接受兩個參數:要選擇第一個字符的索引和要選擇最後一個字符以後的字符索引(相似與substring的兩個參數),以下例子:

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

textbox.focus();

要看到選中的文本,必須在調用setSelectionRange()以前或以後當即將焦點設置到文本框。IE9以及其它高版本支持這種方案。

IE8以及更早版本支持使用範圍選擇部分文本。要選擇文本框中的部分文本,必須首先使用IE在全部文本框上提供的createTextRange()方法建立一個範圍,並將其放到恰當的位置上。而後再使用moveStart()moveEnd()這兩個範圍方法將範圍移動到位。不過,在調用這兩個方法以前,還必須使用collapse()將範圍摺疊到文本框的開始位置。此時,moveStart()將範圍的起點和終點移動到了相同的位置,只要再給moveEnd()傳入要選擇的字符總數便可。最後一步,就是使用範圍的select()方法選擇文本。代碼以下:

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);//hel
range.select();

//選擇第4到第6個字符
range.collapse(true);
range.moveStart("character",4);
range.moveEnd("character",3);//hel
range.select();

跨瀏覽器:

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();
}

 過濾輸入

1.屏蔽字符

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))){
        EventUtil.preventDefault(event);
    }
})

雖然理論上只有在用戶按下字符鍵時纔會觸發keypress事件,但有些瀏覽器也會對其它鍵觸發此事件。Firefox和Safari(3.1版本之前)會對向上鍵、向下鍵、退格鍵和刪除鍵觸發keypress事件。這就意味着,僅考慮到屏蔽不是數值的字符仍是不夠,還要避免屏蔽這些極爲常見和必要的鍵。在Firefox中,全部由非字符鍵觸發的keypress事件對應的字符編碼爲0,而在Safari3.1之前的版本中,對應的字符編碼所有爲8。爲了讓代碼更通用,只要不屏蔽那些字符編碼小於10的鍵便可,故上面代碼變爲以下:

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){
        EventUtil.preventDefault(event);
    }
})

上面代碼能夠屏蔽非數值字符,但不屏蔽那些也會觸發keypress事件的基本按鍵。

還有一個問題須要處理:複製、粘貼以及其它操做還要用到ctrl鍵,最後還有一個檢測,以確保用戶沒有按下ctrl鍵,代碼以下:

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.操做剪貼板

HTML5的6個剪貼板事件。

  • beforecopy:在發生複製操做前觸發。
  • copy:在發生複製操做時觸發。
  • beforecut:在發生剪切操做前觸發。
  • cut:在發生剪切操做時觸發。
  • beforepaste:在發生粘貼操做前觸發。
  • paste:在發生粘貼操做時觸發。

在實際的事件發生前,經過beforecopy、beforecut和beforepaste事件能夠在向粘貼板發送數據,或者從剪貼板取得數據以前修改數據。不過,取消這些事件並不會取消對剪貼板的操做,只有取消copy、cut和paste事件,才能阻止相應的操做發生。

要訪問剪貼板中的數據,可使用clipboardData對象;在IE中,這個對象是window對象的屬性;而在Firefox、Safari和Chrome中,這個對象是相應的event對象的屬性。可是,在Firefox、Safari和Chrome中,只有在處理剪貼板事件期間clipboardData對象纔有效,這是爲了防止對剪貼板的未受權訪問;在IE中,則能夠隨時訪問clipboardData對象。

這個clipboardData對象有三個方法:getData()setData()clearData()

getData():從剪貼板中取得數據,接受一個參數,即要取得的數據的格式。在IE中,有兩種數據格式,「text」和「URL」。在Firefox、Safari和Chrome中,這個參數是一個MIME類型;不過,能夠用「text」表明「text/plain」。

setData():第一個參數也是數據類型,第二參數是放到剪貼板中的文本。對於第一個參數IE照樣支持「text」和「URL」。而在Safari和Chrome中,這個參數仍然只支持MIME類型。可是與getData()方法不一樣的是,Safari和Chrome的setData()方法不能識別「text」類型。這兩個瀏覽器在成功將文本放到剪貼板後,都會返回true,不然返回false。爲了彌合這些差別,能夠向EventUtil對象中添加下列方法:

var EventUtil = {

    //省略的代碼
    
    //獲得剪貼板數據
    getClipboardData:function(event){
        var clipboardData = (event.clipboardData || window.clipboardData);
        return clipboardData.getData("text");
    },
    
    //設置剪貼板數據
    setClipboardData:function(event,value){
        if(event.clipboardData){
            return event.clipboardData.setData("text/plain",value);
        }else if(window.clipboardData){
            return window.clipboardData.setData("text",value);
        }
    }
};

在paste事件中,肯定剪貼板中的數據是否有效,若是無效,取消默認行爲,以下代碼,若是不是數字,則取消粘貼:

var textbox = document.forms[0].elements["textbox"];
EventUtil.addHandler(textbox,"paste",function(event){
    event = EventUtil.getEvent(event);
    var text = EventUtil.getClipboardData(event);
    if(!/^\d*$/.test(text)){
        EventUtil.preventDefault(event);
    }
})

自動切換焦點

 html:

<form>
    <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"/>
</form>

JS代碼:

(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

1.必填字段

在表單字段中添加required屬性。

<form>
    <input type="text" name="text" id="myText" required/>
    <input type="submit" value="提交"/>
</form>

JS檢測某個表單字段是否爲必填字段:

var isUernameRequired = document.forms[0].elements['username'].required;

使用下面這段代碼能夠測試瀏覽器是否支持required屬性:

var isRequiredSupported = "required" in document.createElement("input");

2.其餘輸入類型

HTML5爲<input>元素的type值新添了幾個值。其中「email」和「url」是兩個獲得支持最多的類型,以下代碼:

<form>
    <input type="email" name="email" required/>
    <input type="url" name="url" required/>
    <input type="submit" value="提交"/>
</form>

檢測瀏覽器是否支持這些新類型,不支持它們的舊版本瀏覽器會自動將未知的值設置爲「text」,而支持的瀏覽器會返回正確的值。例如:

var input = document.createElement("input");
input.type ="email";

var isEmailSupported = (input.type == "email");

3.數值範圍

number、range、datetime、datetime-local、date、month、week、time。

對於這些數值類型的輸入元素,能夠指定min屬性(最小的可能值)、max屬性(最大的可能值)和step屬性(從min到max的兩個刻度之間的差值)。

例如,想用戶輸入0到100的值,而且只能是5的倍數,代碼以下:

<input type="number" min="0" max="100" step="5" name="acount"/>

還有兩個方法stepUp()和stepDown(),尚未任何瀏覽器支持,使用以下:

input.stepUp();//加1
input.stepUp(6);//加6
input.stepDown();//減1
input.stepDown(6);//減6

4.輸入模式

HTML5爲文本字段新增了pattern屬性。這個屬性的值是一個正則表達式,用於匹配文本框中的值。以下,只運行文本輸入數字,代碼以下:

<input type="number" pattern="\d+" name="acount"/>

注意,模式的開頭和結尾不用加^和$符號。

檢測瀏覽器是否支持pattern屬性:

var isPatternSupported = "pattern" in document.createElement("input");

5.檢測有效性

使用checkValidity()方法能夠檢測整個表單,也能夠檢測某個表單字段。

//檢測具體的某個表單字段
if(document.forms[0].elements[0].checkValidity()){
    alert("有效的值");
}else{
    alert("無效的值");
}

//檢測整個表單
if(document.forms[0].checkValidity()){
    alert("表單有效");
}else{
    alert("表單無效");
}

 6.禁用驗證

經過設置novalidate屬性,告訴表單不進行驗證。

<form method="post" action="signup.php" novalidate>
    <!--這裏插入表單元素-->
</form>

在JS中使用noValidate屬性能夠取得或設置這個值,若是這個屬性存在,值爲true,不存在則爲false。

document.forms[0].noValidate = true; //禁用驗證

若是一個表單中有多個提交按鈕,能夠指定某個提交按鈕沒必要驗證表單,能夠在相應的按鈕上添加formnovalidate屬性。

<form method="post" action="foo.php">
    <!--這裏插入表單元素-->
    <input type="submit" value="Regular Submit"/>
    <input type="submit" formnovalidate name="btnNovalidate" value="Non-validating Submit"/>
</form>

使用JS設置這個屬性:

document.forms[0].elements['btnNovalidate'].formNoValidate = true; //禁用驗證

選擇框腳本

選擇框是經過<select><option>元素建立的。除了全部表單字段共有的屬性和方法外,HTMLSelectElement類型還提供了下列屬性和方法。

  • add(newOption,relOption):向控件中插入新<option>元素,其位置在相關項(relOption)以前。
  • multiple:布爾值,表示是否容許多項選擇;等價於HTML中的multiple特性。
  • options:控件中全部<option>元素的HTMLCollection。
  • remove(index):移除給定位置的選項。
  • selectedIndex:基於0的選中項的索引,若是沒有選中項,則值爲-1。對於支持多選的控件,只保存選中項中第一項的索引。
  • size:選擇框中可見的行數;等價於HTML中的size特性。

選擇框的type屬性不是「select-one」,就是「select-multiple」。這取決於HTML代碼中有沒有multiple特性。

在DOM中,每一個<option>元素都有一個HTMLOptionElement對象。爲便於訪問數據,HTMLOptionElement對象添加了下列屬性:

  • index:當前選項在options集合中的索引。
  • label:當前選項的標籤;等價於HTML中的label特性。
  • selected:布爾值,表示當前選項是否被選中。將這個屬性設置爲true能夠選中當前選項。
  • text:選項的文本。
  • value:選項的值(等價於HTML中的value特性)。

以下代碼,HTML:

<form>
    <select name="location">
        <option value="1">北京</option>
        <option value="2">天津</option>
        <option value="3">上海</option>
    </select>
</form>

JS代碼:

var selectbox = document.forms[0].elements['location'];
var text = selectbox.options[0].text; //選項的文本
var value = selectbox.options[0].value;//選項的值

選擇選項

使用選擇框的selectedIndex屬性。如上面代碼默認選中了天津。

var selectbox = document.forms[0].elements['location'];
var selectOption = selectbox.options[selectbox.selectedIndex];

選中選擇框的第一項:

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;
}
var selectbox = document.forms[0].elements['location'];
getSelectedOptions(selectbox);

添加選項

第一種,DOM方式添加:

var selectbox = document.forms[0].elements['location'];
var newoption = document.createElement('option');
newoption.appendChild(document.createTextNode('Option text'));
newoption.setAttribute('value',"option value");
selectbox.appendChild(newoption);

第二種方式,使用Option構造函數,Option構造函數接受兩個參數:文本(text)和值(value),第二個參數可選。雖然這個構造函數會建立一個Option實例,但兼容DOM的瀏覽器會返回一個<option>元素。以下代碼:

var selectbox = document.forms[0].elements['location'];
var newoption = new Option("Option text","option value");
selectbox.appendChild(newoption); //在IE8以及以前版本有問題

第三種方式使用選擇框的add()方法。該方法接受兩個參數:要添加的新選項和將位於新選項以後的選項。

var selectbox = document.forms[0].elements['location'];
var newoption = new Option("Option text","option value");
selectbox.add(newoption,undefined); 

移除選項

三種方式以下:

var selectbox = document.forms[0].elements['location'];

//removeChild()傳入要移除的選項
selectbox.removeChild(selectbox.options[0]); //移除第一個選項

//remove(index)傳入移除項的索引
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('location1');
var selectbox2 = document.getElementById('location2');
selectbox2.appendChild(selectbox1.options[0]);

移動選項和移除選項有一個共同之處,即會重置每個選項的index屬性。

要將選擇框中的某一項移動到特定的位置,最適合的DOM方法insertBefore()

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]);

表單序列化

在編寫代碼以前,有必須先搞清楚在表單提交期間,瀏覽器是怎樣將數據發送給服務器的。

  • 對錶單字段的名稱和值進行URL編碼,使用和號(&)分隔。
  • 不發送禁用的表單字段。
  • 只發送勾選的複選框和單選按鈕。
  • 不發送type爲「reset」和「button」的按鈕。
  • 多選選擇框的每一個選中的值單獨一個條目。
  • 在單擊提交按鈕提交表單的狀況下,也會發送提交按鈕;不然,不發送提交按鈕。也包括type爲「image」的<input>元素。
  • <select>元素的值,就是選中的<option>元素的value特性的值。若是<option>元素沒有value特性,則是<option>元素的文本值。

表單序列化代碼:

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[i];
                        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('&');
}

富文本編輯

富文本編輯,這一技術的本質,就是在頁面中嵌入一個包含空HTML頁面的iframe。經過設置designMode屬性,這個空白的HTML頁面能夠被編輯,而編輯對象則是該頁面<body>元素的HTML代碼。designMode屬性有兩個可能的值:「off」(默認值)和「on」。在設置爲「on」時,整個文檔都會變得能夠編輯(顯示插入符號),而後就能夠像使用字處理軟件同樣,經過鍵盤將文本內容加粗、變成斜線等等。

<iframe name="richedit" style="width:100px;height:100px;" src="index2.html"></iframe>
<script type="text/javascript">
    EventUtil.addHandler(window,"load",function(event){
        frames["richedit"].document.designMode = "on";
    })
</script>

使用contenteditable屬性

另外一種編輯富文本內容的方式是使用名爲contenteditable的特殊屬性。這個屬性最先由IE實現。使用它,不須要使用iframe、空白頁和JS,只要給元素設置該屬性便可,以下:

<div class="editable" id="richedit" contenteditable style="width:100px;height:100px;border:1px solid grey"></div>

經過在這個元素上設置contenteditable屬性,也能打開或關閉編輯模式,代碼以下:

var div = document.getElementById('richedit');
div.contentEditable = "false";

contentEditable屬性有三個可能值:「true」表示打開,「false」表示關閉,「inherit」表示從父元素那裏繼承。

操做富文本

document.execCommand(),這個方法能夠對文檔執行預約義的命令,這個方法接受三個參數:要執行的命令名稱、表示瀏覽器是否應該爲當前命令提供用戶界面的一個布爾值(跨瀏覽器兼容性,通常都設置爲false)和執行命令必須的一個值。

使用命令來修改富文本區域的外觀,以下例子:

//轉換粗體文本
frames["richedit"].document.execCommand("bold",false,null);

//轉換斜體文本
frames["richedit"].document.execCommand("italic",false,null);

一樣的方法適用於頁面中contenteditable屬性爲true的區塊:

//轉換粗體文本
document.execCommand("bold",false,null);

//轉換斜體文本
document.execCommand("italic",false,null);

富文本選區

表單與富文本

EventUtil對象方法:

var EventUtil = {
    
    //事件處理程序
    addHandler:function(element,type,handler){
        if(element.addEventListener){
            element.addEventListener(type,handler,false);
        }else if(element.attachEvent){
            element.attachEvent("on" + type,handler);
        }else{
            element["on" + type] = handler;
        }
    },
    
    //獲得event對象
    getEvent:function(event){
        return event ? event : window.event;
    },
    
    //獲得事件目標
    getTarget:function(event){
        return event.target || event.srcElement;
    },
    
    //獲得相關元素信息
    getRelatedTarget:function(event){
        if(event.relatedTarget){
            return event.relatedTarget;
        }
        else if(event.toElement){
            return event.toElement;
        }
        else if(event.fromElement){
            return event.fromElement;
        }else{
            return null;
        }
    },
    
    //取消默認行爲
    preventDefault:function(event){
        if(event.preventDefault){
            event.preventDefault();
        }else{
            event.returnValue = false;
        }
    },
    
    //獲得button屬性
    getButton:function(event){
        if(document.implementation.hasFeature("MouseEvents","2.0")){
            return event.button;
        }else{
            switch(event.button){
                case 0:
                case 1:
                case 3:
                case 5:
                case 7:
                    return 0;
                case 2:
                case 6:
                    return 2;
                case 4:
                    return 1;
            }
        }
    },
    
    //取得鼠標滾輪增量值(delta)
    getWheelDelta:function(event){
        if(event.wheelDelta){
            return event.wheelDelta;
        }else{
            return -event.detail * 40;
        }
    },
    
    //字符編碼
    getCharCode:function(event){
        if(typeof event.charCode == 'number'){
            return event.charCode;
        }else{
            return event.keyCode;
        }
    },
    
    //移除事件處理程序
    removeHandler:function(element,type,handler){
        if(element.removeEventListener){
            element.removeEventListener(type,handler,false);
        }else if(element.detachEvent){
            element.detachEvent("on" + type,handler);
        }else{
            element["on" + type] = null;
        }
    },
    
    //阻止事件捕獲或冒泡
    stopPropagation:function(event){
        if(event.stopPropagation){
            event.stopPropagation();
        }else{
            event.cancelBubble = true;
        }
    },
    
    //獲得剪貼板數據
    getClipboardData:function(event){
        var clipboardData = (event.clipboardData || window.clipboardData);
        return clipboardData.getData("text");
    },
    
    //設置剪貼板數據
    setClipboardData:function(event,value){
        if(event.clipboardData){
            return event.clipboardData.setData("text/plain",value);
        }else if(window.clipboardData){
            return window.clipboardData.setData("text",value);
        }
    }
};
相關文章
相關標籤/搜索