JavaScript 高级程序设计(第14章 表单脚本)

第14章 表单脚本

1. 表单的基础指示

在 JavaScript 中,表单对应的则是 HTMLFormElement类型。HTMLFormElement 继承了 HTMLElement,因而与其他 HTML 元素具有相同的默认属 性。

HTMLFormElement 自己独有的属性和方法:

(1) acceptCharset:服务器能够处理的字符集;等价于 HTML 中的 accept-charset 特性。
(2) action:接受请求的 URL;等价于 HTML 中的 action 特性。
(3) elements:表单中所有控件的集合(HTMLCollection)。
(4) enctype:请求的编码类型;等价于 HTML 中的 enctype 特性。
(5) length:表单中控件的数量。
(6) method:要发送的 HTTP 请求类型,通常是"get"或"post";等价于 HTML 的 method 特性。
(7) name:表单的名称;等价于 HTML 的 name 特性。
(8) reset():将所有表单域重置为默认值。
(9) submit():提交表单。
(10) target:用于发送请求和接收响应的窗口名称;等价于 HTML 的 target 特性。

取得
元素引用的方式:

  1. getElementById()方法
var form = document.getElementById("form1");
  1. 通过 document.forms 可以取得页面中所有的表单。在这个集合中,可以通过数值索引或name 值来取得特定的表单。
var firstForm = document.forms[0]; //取得页面中的第一个表单
var myForm = document.forms["form2"]; //取得页面中名称为"form2"的表单

(1) 提交表单

  1. 用户单击提交按钮图像按钮时,就会提交表单。使用






  1. 提交表单时,浏览器会在将请求发送给服务器之前触发 submit 事件
var form = document.getElementById("myForm");
EventUtil.addHandler(form, "submit", function(event){
    //取得事件对象
    event = EventUtil.getEvent(event);
    //阻止默认事件
    EventUtil.preventDefault(event);
});
  1. 在 JavaScript 中,以编程方式调用 submit()方法也可以提交表单。(以调用 submit()方法的形式提交表单时,不会触发 submit 事件)
var form = document.getElementById("myForm");
//提交表单
form.submit();
  1. 避免重复提交表单的方法:在第一次提交表单后就禁用提交按钮,或者利用 onsubmit 事件处理程序取消后续的 表单提交操作。

(2) 重置表单

  1. 在用户单击重置按钮时,表单会被重置。使用 type 特性值为"reset"




  1. 用户单击重置按钮重置表单时,会触发reset 事件
  1. 在 JavaScript 中,以编程方式调用reset()方法也可以重置表单。(以调用 reset()方法的形式重置表单时,不会触发 reset 事件)

(3) 表单字段

  1. 可以像访问页面中的其他元素一样,使用原生 DOM 方法访问表单元素。
  2. 每个表单都有elements 属性,该属性是表单中所有表单元素(字段)的集合。
  3. elements 集合是一个有序列表, 其中包含着表单中的所有字段,例如之间。
  4. 
    
    • 这两种文本框都会将用户输入的内容保存在 value 属性中。可以通过这个属性读取和设置文本框的值。

    (1) 选择文本

    select()方法这个方法用于选择文本框中的所有文本。

    在文本框获得焦点时选择其所有文本,这样做可以让用户不必一个一个地删除文本。

    EventUtil.addHandler(textbox, "focus", function(event){
        event = EventUtil.getEvent(event);
        var target = EventUtil.getTarget(event);
        target.select();
    });
    
    * 选择(select)事件

    在选择了文本框中的文本时,就会触发 select 事件。

    (1) 在 IE9+、Opera、Firefox、Chrome 和 Safari 中,只有用户选择了文本(而且要释放鼠标),才会触发 select 事件。
    (2) 在 IE8 及更早版本中,只要用户选择了一个字母(不必释放鼠标),就会触发 select 事件。
    (3) 在调用 select()方法时也会触发 select 事件。

    * 取得选择的文本
    1. selectionStartselectionEnd,这两个属性中保存的是基于 0 的数值,表示所选择 文本的范围(即文本选区开头和结尾的偏移量)。

    要取得用户在文本框中选择的文本,可以使用 如下代码:

    function getSelectedText(textbox){
            return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd);
    }
    
    1. 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;
            }
    }
    
    * 选择部分文本
    1. setSelectionRange()方法,这个方法接收两个参数:要选择的第一个字符的索引和要选择的最后一个字符之后的字符的索引。
    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"
    
    1. IE8 及更早版本支持使用范围选择部分文本。

    (1) 要选择文本框中的部分文本,必须 首先使用 IE 在所有文本框上提供的 createTextRange()方法创建一个范围,并将其放在恰当的位置 上。
    (2)然后,再使用 moveStart()和 moveEnd()这两个范围方法将范围移动到位。
    (3)不过,在调用这两个 方法以前,还必须使用 collapse()将范围折叠到文本框的开始位置。此时,moveStart()将范围的起 点和终点移动到了相同的位置,只要再给 moveEnd()传入要选择的字符总数即可。
    (4)最后一步,就是使 用范围的 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);
     range.select();//"Hel"
    
    //选择第4到第6个字符
    range.collapse(true); 
    range.moveStart("character", 4); 
    range.moveEnd("character", 3); 
    range.select();//"o w"
    
    1. 实现跨浏览器编程
    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();
    }
    
    

    想在文本框中看到文本被选择的效果,必须让文本框获得焦点。

    (2) 过滤输入

    *屏蔽字符

    响应向文本框中插入字符操作的是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))){
                    EventUtil.preventDefault(event);
            }
    });
    

    理论上只应该在用户按下字符键时才触发 keypress 事件,但有些浏览器也会对其他键触发此 事件。Firefox 和 Safari(3.1 版本以前)会对向上键、向下键、退格键和删除键触发 keypress 事件;在 Firefox 中,所 有由非字符键触发的 keypress 事件对应的字符编码为 0,而在 Safari 3 以前的版本中,对应的字符编 码全部为 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);
            }
    });
    

    最后还要添加一 个检测条件,以确保用户没有按下 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);
            }
    });
    
    *操作剪贴板

    6 个剪贴板事件:

    (1) beforecopy:在发生复制操作前触发。
    (2) copy:在发生复制操作时触发。
    (3) beforecut:在发生剪切操作前触发。
    (4) cut:在发生剪切操作时触发。
    (5) beforepaste:在发生粘贴操作前触发。
    (6) paste:在发生粘贴操作时触发。

    clipboardData 对象:访问剪贴板中的数据。

    1. 在 IE 中,这个对象是 window 对象的 属性;而在 Firefox 4+、Safari 和 Chrome 中,这个对象是相应 event 对象的属性。
    2. clipboardData 对象有三个方法:getData()、setData()和 clearData()。
      (1) getData()用于从剪贴板中取得数据,它接受一个参数,即要取得的数据的格式。在 IE 中,有两种数据格式:"text" 和"URL"。在 Firefox、Safari 和 Chrome 中,这个参数是一种 MIME 类型;不过,可以用"text"代表 "text/plain"。
      (2)setData()方法的第一个参数也是数据类型,第二个参数是要放在剪贴板中的文本。对于 第一个参数,IE 照样支持"text"和"URL",而 Safari 和 Chrome 仍然只支持 MIME 类型。成功将文本放到剪贴板中后,都会返回 true;否则,返回 false。
    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);
                 }
             },
            //省略的代码 
    };
    

    如果一个文本框只接受数值,在 paste 事件中,可以确定剪贴板中的值是否有效,如果无效,就可以像下面示例中那样,取消默认的行为。

    EventUtil.addHandler(textbox, "paste", function(event){
        event = EventUtil.getEvent(event);
        var text = EventUtil.getClipboardText(event);
        if (!/^\d*$/.test(text)){
            EventUtil.preventDefault(event);
        }
    });
    

    (3) 自动切换焦点

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

    (4) HTML5 约束验证API

    * 必填字段

    required 属性: 任何标注有 required 的字段,在提交表单时都不能空着。这个属性适用于