打算实现模拟表单控件的DEMO,首先把《JavaScript高级程序设计》“表单脚本”这章的内容复习一下,有针对性地看书,希望可以提高效率。
表单对应的是HTMLFormElement类型,HTMLFormElement继承了HTMLElement,具有其他HTML元素的默认属性,同时享有一些独特的属性和方法。
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>中的submit和reset按钮都有默认行为的,所以不需要onclick(你要添加其他功能除外)。而且为了配合submit()和reset()方法,Form对象还提供了事件句柄onsubmit和onreset,前者用来探测表单的提交,后者用来探测表单的重置。onsubmit是在表单提交前调用的,如果它返回false,就取消表单的提交。这给Javascript提供一个检查不正确数据的机会。注意,只有真正点击submit按钮才会触发onsubmit,调用表单的submit()方法则不会触发它。
onreset与onsubmit相似,如果返回false,则取消重置,也是点击按钮才会触发。
例子:<form...
onreset = "return confirm("确认重置?")">
(1)使用getElementById()方法找到
var form = document.getElementById("form1");
(2)通过document.forms取得页面中的所有的表单,可以通过数值索引或name值来取得特定的表单
var firstForm = document.forms[0]; //取得页面中第一个表单 var myForm = document.forms["form2"]; //取得页面中名称为“form2”的表单
var fieldCount = document.elements.length; //取得表单中包含的字段的数量
每个表单都有elements属性,该属性是表单中所有表单元素(字段)的集合。这个elements集合是一个有序列表,其中包含着表单中的所有字段,例如<input>、<textare>、<button>等。每个表单字段在elements集合中的顺序,与它们出现在标记中的顺序相同,可以按照位置和name特性来访问它们。
var form = document.getElementById("form1"); var field1 = form.elements[0]; var field2 = form.elements["textbox1"];
如果有多个表单控件都在使用一个name(如checkbox、radio),那么就会返回以该name命名的一个NodeList。
var colorFields = forms.elements["color"]; //返回NodeList alert(colorFields.length);
disabled | bool,表示当前字段是否被禁用 |
form | 指向当前字段所属表单的指针;只读 |
name | 当前字段的名称 |
readOnly | bool,表示当前字段是否只读 |
tabIndex | 表示当前字段的切换(tab)序号 |
type | 当前字段的类型,如“checkbox”,“radio”等等,除了<fieldset>之外,所有表单字段都有type属性。 |
value | 当前字段将被提交给服务器的值 |
var form = document.getElementById("myForm"); var fields = form.elements[0]; field.value = "123"; //修改value值 field.disable = true; //禁用当前字段
(2)共有的表单字段方法
focus():将浏览器的焦点设置到表单字段,即激活表单字段,使其可以相应键盘事件;
blur():将焦点从调用这个方法的元素上移走;
blur | 当前字段失去焦点时触发 |
change | 对于<input>和<textarea>元素,在它们失去焦点且value值改变时触发;对于<select>元素,在其选项改变时触发 |
focus | 当前字段获得焦点时触发 |
//在HTML中有两种方式表示文本框:<input>单行文本框和<textarea>多行文本框 <input type="text" size="25" maxlength="50" value="initial value" /> <textarea rows="25" cols="5">initial value</textarea>
由于对value属性的修改,不一定能反映在DOM中,所以在处理文本框的值时,最好不要使用DOM方法。
<input>和<textarea>文本框都支持select()方法来选择文本框中的所有文本。该函数不接受任何参数,可在任何时候调用。
var textbox = document.form[0].elements["textbox1"]; textbox.select();
(1)在选择了文本框中的文本时,会触发选择(select)事件。
(2)取得选择的文本
selectionStart和selectionEnd属性中保存的是基于0的数值,表示所选择文本的范围(即文本选区开头和结尾的偏移量)。
function getSelectedText(textbox){ if(typeof textbox.selectionStart == "number") return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd); else if(document.selection) //IE8及更早版本中的对象 return document.selection.createRange().text; }
(3)选择部分文本
最早由Firefox引入的HTML5解决方案:setSelectionRange()方法接收两个参数:要选择的第一个字符的索引和要选择的最后一个字符之后的字符的索引。IE8及更早版本提供的是createTextRange()方法。
function selectText(textbox, startIndex, stopIndex){ if(textbox.setSelectedRange) textbox.setSelectedRange(startIndex, stopIndex); else if(textbox.createTextRange){ //IE8及更早版本 var range = textbox.createTextRange(); range.collapse(true); //将范围折叠到文本框的开始位置 range.moveStart("character",startIndex); range.moveEnd("character",stopIndex - startIndex); range.select(); } textbox.focus(); }
<input type="text" name="tel" id="txtText" maxLength="3" /> <script> (function(){ function tabForward(event){ event = event || window.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 true; } } } var textbox = document.getElementById("txtText"); EventUtil.addHandler(textbox, "keyup", tabForward); })(); </script>
(1)必填字段:required属性
任何标注有required的字段,在提交表单时都不能空着。这个属性适合于<input>、<textarea>和<select>字段。在JavaScript中,通过对应的required属性检查某个表单字段是否为必填字段。
<input type="text" name="username" required> var isUsernameRequired = document.forms[0].elements["username"].required; //检查某个表单字段是否为必填字段 var isRequiredSupported = "required" in document.createElement("input"); //测试浏览器是否支持required属性
(2)输入模式:pattern属性
该属性的值是一个正则表达式,用于匹配文本框中的值。需要注意的是:模式的开头和结尾不用加^和$符号(如果已有),这两个符号表示输入的值必须从头到尾都与模式匹配。
<input type="text" name="count" pattern="\d+"> var pattern = document.forms[0].elements["count"].pattern; //浏览器判断值是有效还是无效 var isPatternSupported = "pattern" in document.createElement("input"); //测试浏览器是否支持pattern属性
(3)检测有效性:checkValidity()方法和validity属性
checkValidity()方法检测表单中的某个字段是否有效。如果字段的值有效该方法返回true,否则返回false。
if(document.form[0].elements[0].checkValidity()){ //字段有效 } else { //字段无效 }
checkValidity()方法仅简单的判断字段是否有效,而validity属性则会告诉你为什么字段有效或无效。这个对象中包含一系列属性,每个属性返回一个布尔值。
(4)禁用验证:novalidate属性,告诉表单不进行验证
在JavaScript中使用novalidate属性可以取得或设置这个值,如果这个属性存在,值为true,如果不存在,值为false。如果一个表单中有多个提交按钮,为了指定点击某个提交按钮不必验证表单,可以在相应的按钮上添加formnovalidate属性。
<form method="post" action="" novalidate> </form> <form method="post" action=""> <input type="submit" formnovalidate name="btnNoValidate" value="" /> </form> document.forms[0].noValidate = true; document.forms[0].elements["btnNoValidate"].formNoValidate = true;
选择框是通过<select>和<option>元素创建的,除了所有表单字段共有的属性和方法外,HTMLSelectElement类型还提供了下列属性和方法。
add(newOption, relOption) | 向控件中插入新<option>元素,其位置在relOption之前 |
multiple | bool,表示是否允许多项选择,等价于HTML中的multiple特性 |
options | 控件中所有<option>元素的HTMLCollection |
remove(index) | 移出给定位置的索引 |
selectedIndex | 基于0的选中项的索引,如果没有选中项,则值为-1。对于支持多选的控件,只保存选中项中第一项的索引。 |
size | 选中框中可见的行数;等价于HTML中的size特性 |
在DOM中,每个<option>元素都有一个HTMLOptionElement对象表示。为便于访问数据,HTMLOptionElement属性有如下属性:
index | 当前选项在options集合中的索引 |
label | 当前选项的标签;等价于HTML中的label特性 |
selected | bool,表示当前选项是否选中。将这个属性设置为true可以选中当前选项 |
text | 选项的文本 |
value | 选项的值;等价于HTML中的value特性 |
var selectbox = document.forms[0].elements["location"]; //不推荐 var text = selectbox.options[0].firstChild.nodeValue; var value = selectbox.options[0].getAttribute("value"); //推荐 var text = selectbox.options[0].text; var value = selectbox.options[0].value;
(1)只允许选择一项
使用selectedIndex属性:
var selectbox = document.getElementById("selLocation"); var selectedIndex = selectbox.selectedIndex; var selectedOption = selectbox.options[selectedIndex];
(2)允许选择多项
设置selectedIndex会导致取消以前的所有选项并选择指定的那一项,而读取selectedIndex则只会返回选中项中第一项的索引;而selected属性不会取消对其他选中项的选择,可以动态选中任意多个项。其实selected属性只能确定用户选中了哪些项,若要取得所有选中的项需要使用循环遍历集合,测试每个选项的selected属性。
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; }
方法一:使用DOM方法
var newOption = document.createElement("option"); newOption.appendChild(document.createTextNode("Option text")); newOption.setAttribute("value", "Option value"); selectbox.appendChild(newOption);
方法二:使用appendChild()方法
var newOption = new Option("Option text", "Option text"); selectbox.appendChild(newOption);
方法三:DOM规定add()方法接受两个参数:要添加的新选项和将位于新选项之后的选项。如果想在列表的最后添加一个选项,为了兼容所有浏览器,应传入null。
var newOption = new Option("Option text", "Option text"); selectbox.add(newOption, undefined);
移除选项可以使用DOM的removeChild()方法或者选择框的remove()方法。remove()函数接受一个参数,即要删除选项的索引。
selectbox.removeChild(selectbox.options[0]);
或 selectbox.remove(0); //移除第一项
或
selectbox.options[0] = null;
搞清浏览器是怎样把数据发送到服务器的:
(1)对表单字段的名称和值进行URL编码,使用和号(&)分隔;
(2)不发送禁用的表单字段;
(3)只发送勾选的复选框和单选按钮;
(4)不发送type为“reset”和“button”的按钮;
(5)多选选择框中的每个选中的值单独一个条目;
(6)在单击提交按钮提交表单的情况下,也会发送提交按钮;否则,不发送提交按钮;
(7)<select>元素的值,就是选中的<option>元素的value特性的值。如果<option>元素没有value特性,则是<option>元素的文本值。
序列化过程中最麻烦的就是<select>元素,因为需要遍历控件中的每一个选项,并在相应选项被选中的情况下向数组中添加一个值。