第十四章 表单脚本

144 阅读10分钟

表单的基础知识

在 HTML 中,表单是由<form>元素来表示的,而在 JavaScript 中,表单对应的则是 HTMLFormElement 类型。

HTMLFormElement 具有下列独有的属性和方法:

  • 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 特性

获取表单

  1. 通过document.getElementById() :与其他元素一样

  2. 通过document.forms:通过集合的方式获取,可以通过数值索引或name值获取表单

    var firstForm = document.forms[0]; //获取页面中的第一个表单
    var myForm = document.forms["form2"]; //获取页面中name属性值为form2的表单
    

提交表单

  1. 通过提交按钮或图像按钮提交表单

    在表单中使用<input>或者<button>标签,并将其type属性设置为submit,图像按钮则是将<input>的type属性设置为image。以这种方式提交表单时,浏览器将请求发送给服务器之前会触发submit事件,并可以验证表单是否提交,不提交的话通过阻止该事件的默认行为取消提交表单。如下:

    <input type = "submit" value = "提交表单">
    <button type = "submit" value = "提交表单">
    <input type = "image" src = "...">
        
    var form = document.getElementById("myForm");
    EventUtil.addHandler(form , "submit" , function(event) {
        event = EventUtil.getEvent(event);//取得事件对象
        EventUtil.preventDefault(event);//阻止默认行为,取消提交表单
    })
    
  2. 调用submit() 方法提交表单

    这种方法无需提交按钮,任何时候都可以提交表单,但是调用submit() 方法的时候,不会触发submit事件,所以要在调用submit() 方法之前验证表单。

    var form = document.getElementById("myForm");
    form.submit();
    

重置表单

  1. 使用type值为reset的<input><button>

    用户单击重置按钮时,会触发reset事件,因此可以取消重置操作

    <input type = "reset" value = "重置表单">
    <button type = "reset" value = "重置表单">
    
    var form = document.getElementById("myForm");
    EventUtil.addHandler(form , "reset" , function({
        event = EventUtil.getEvent(event);
        EventUtil.preventDefault(event);//阻止表单重置
    }))
    
  2. 使用表单的reset() 方法

    调用reset() 方法时,也会触发reset事件

表单字段

每个表单都有elements 属性,是表单中所有表单元素(字段)的有序列表。可以按照位置和 name 特性来访问表单中的字段。

var form = document.getElementById("form1"); 
//取得表单中的第一个字段
var field1 = form.elements[0]; 
//取得 name 为 textbox1 的字段
var field2 = form.elements["textbox1"]; 
//取得表单中包含的字段的数量
var fieldCount = form.elements.length; 
  1. 表单共有的字段属性
    • disabled:布尔值,表示当前字段是否被禁用
    • form:指向当前字段所属表单的指针;只读
    • name:当前字段的名称
    • readOnly:布尔值,表示当前字段是否只读
    • tabIndex:表示当前字段的切换(tab)序号
    • type:当前字段的类型,如"checkbox"、"radio",等等
    • value:当前字段将被提交给服务器的值。对文件字段来说,这个属性是只读的,包含着文在计算机中的路径
  2. 表单共有的字段方法
    • focus() :将浏览器的焦点设置到表单字段
    • blur() :移出元素的焦点
  3. 表单共有的字段事件
    • blur:当前字段失去焦点时触发
    • change:对于<input>和<textarea>元素,在它们失去焦点且 value 值改变时触发;对<select>元素,在其选项改变时触发
    • focus:当前字段获得焦点时触发

文本框脚本

选择脚本

文本框的 select() 方法用于选择文本框中所有文本,没有参数。

  1. 选择事件

    用户选择文本的时候,会触发 select 事件

  2. 取得选择的全部文本

    使用 selectionStart 和 selectionEnd 两个属性可以取得所选文本。

    function getSelectedText (textbox) {
        return textbox.value.substring(textbox.selectionStart , textbox.selectionEnd);
    }
    
  3. 取得选择的部分文本

    使用 setSelectionRange () 方法获得所选的部分文本,该方法接收两个参数:第一个字符的索引和最后一个字符的索引(从0开始算,不包括最后一个字符索引)。

    textbox.value = "Hello World!";
    textbox.setSelectionRange(0 , textbox.value.length);//"Hello World!"
    textbox.setSelectionRange(0 , 3);//前3个字符——"Hel"
    

过滤输入

  1. 屏蔽字符

    //只允许输入数值
    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. 操作剪贴板

    6个剪贴板事件:

    • beforecopy:在发生复制操作前触发
    • copy:在发生复制操作时触发
    • beforecut:在发生剪切操作前触发
    • cut:在发生剪切操作时触发
    • beforepaste:在发生粘贴操作前触发
    • paste:在发生粘贴操作时触发

    clipboardData 对象可以访问剪贴板中的数据,这个对象有三个方法:getData() 、setData() 、clearData()

    • getData():接收一个参数,要取得的数据类型
    • setData():接收两个参数,数据类型、要放在剪贴板中的文本
    • clearData()
    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); 
      		} 
      	}, 
      //省略的代码
    }; 
    
    

自动切换焦点

可以在前一个文本框中的字符达到最大数量后,自动将焦点切换到下一个文本框。

HTML5约束验证API

  1. 必填字段

    在 DOM 元素中添加 required 属性

  2. 其他输入类型

    HTML5 为 <input> 元素的 type 属性添加了 email 类型和 url 类型,"email"类型要求输入的文本必须符合电子邮件地址的模式,"url"类型要求输入的文本必须符合 URL 的模式。

  3. 数值范围类型

    <input> 中数值范围类型包括:"number"、"range"、"datetime"、"datetime-local"、"date"、"month"、"week"、"time"。

    对所有数值类型的输入元素,可以指定 min 属性(最小的可能值)、max 属性(最大的可能值)和 step 属性(刻度值)。

    stepUp() 和 stepDown() ,都接收一个可选的参数:要在当前值基础上加上或减去的数值。(默认是加或减 1)

    input.stepUp(); //加 1 
    input.stepUp(5); //加 5 
    input.stepDown(); //减 1 
    input.stepDown(10); //减 10 
    
    
  4. 输入模式

    HTML5 为文本字段新增了 pattern 属性。这个属性的值是一个正则表达式,用于匹配文本框中的值。

  5. 检测有效性

    使用 checkValidity()方法可以检测表单中的某个字段是否有效,如果字段的值有效,这个方法返回 true,否则返回 false。

    validity 属性检测字段有效或无效的原因。这个对象中包含一系列属性,每个属性会返回一个布尔值。

    • customError :如果设置了setCustomValidity(),则为true,否则返回false
    • patternMismatch:如果值与指定的pattern 属性不匹配,返回true
    • rangeOverflow:如果值比max 值大,返回true
    • rangeUnderflow:如果值比min 值小,返回true
    • stepMisMatch:如果min 和max 之间的步长值不合理,返回true
    • tooLong:如果值的长度超过了maxlength 属性指定的长度,返回true
    • typeMismatch:如果值不是"mail"或"url"要求的格式,返回true
    • valid:如果这里的其他属性都是false,返回true
    • valueMissing:如果标注为required 的字段中没有值,返回true
    if(document.forms[0].checkValidity()){ 
      	//表单有效,继续
    } else { 
      	//表单无效
    } 
    
    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."); 
      	} 
    } 
    
    
  6. 禁用验证

    通过设置 novalidate 属性,可以告诉表单不进行验证。

    如果一个表单中有多个提交按钮,为了指定点击某个提交按钮不必验证表单,可以在相应的按钮上添加 formnovalidate 属性。

选择框脚本

<select> 元素的属性方法:

  • add(newOption, relOption):向控件中插入新<option>元素,其位置在相关项(relOption)之前
  • multiple:布尔值,表示是否允许多项选择
  • options:控件中所有<option>元素的 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 属性将依据前两条规则取得第一个选中项的值

<options> 元素的属性和方法:

  • index:当前选项在 options 集合中的索引
  • label:当前选项的标签;等价于 HTML 中的 label 特性
  • selected:布尔值,表示当前选项是否被选中,将这个属性设置为 true 可以选中当前选项
  • text:选项的文本
  • value:选项的值

选择选项

对于单选的选择框,访问选中项可以使用选择框的 selectedIndex 属性,也可以利用选项的 selected 属性为 true 。

var selectedOption = selectbox.options[selectbox.selectedIndex]; 
selectbox.options[0].selected = true; 

对于多选的选择框,访问选择框的 selectedIndex 属性只能获取第一个选中项,访问选项的 selected 属性为 true 可以获取所有的选中项。

添加选项

有两种方式:

  • 使用 Option 构造函数创建选项,接收两个参数:文本(text)、值(value),第二个参数可选,兼容 DOM 的浏览器会返回一个 <option> 元素

    var newOption = new Option("Option text", "Option value"); 
    selectbox.appendChild(newOption); //在 IE8 及之前版本中有问题
    
  • 使用选择框的 add() 方法,接收两个参数:要添加的新选项、位于新选项之后的选项,第二个参数设置为null表示在列表的最后添加一个选项

    var newOption = new Option("Option text", "Option value"); 
    selectbox.add(newOption, undefined); //最佳方案,undefined可以兼容IE
    

移除选项

有两种方式:

  • 利用选择框的 remove() 方法移除选项,接收一个参数:要移除选项的索引

    selectbox.remove(0);//移除第一个选项
    
  • 利用将选项设置为 null 可以移除选项

    selectbox.options[0] = null;//移除第一个选项
    

移动和重排选项

移动选项

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

表单序列化

富文本编辑

方式一:

页面嵌入一个包含空 HTML 页面的 iframe 。通过设置 designMode 属性,这个空白的 HTML 页面可以被编辑,而编辑对象则是该页面<body> 元素的 HTML 代码。designMode 属性有两个可能的值:"off"(默认值)和"on"。"on"表示整个文档可以编辑。

方式二:

把 contenteditable 属性应用给页面中的任何元素,然后用户立即就可以编辑该元素。

操作富文本

document.execCommand() :对文档执行命令,接收3个参数:命令名称、表示浏览器是否应该为当前命令提供用户界面的一个布尔值(保证兼容最好传 false )、执行命令的必要值(如果没有传 null )

富文本选区

使用框架(iframe)的 getSelection() 方法,可以确定实际选择的文本,调用它会返回一个表示当前选择文本的 Selection 对象。 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():返回选区所包含的文本内容
var selection = frames["richedit"].getSelection(); 
//取得选择的文本
var selectedText = selection.toString(); 
//取得代表选区的范围
var range = selection.getRangeAt(0); 
//突出显示选择的文本
var span = frames["richedit"].document.createElement("span"); 
span.style.backgroundColor = "yellow"; 
range.surroundContents(span); 

表单与富文本