表单脚本

JavaScript 2020-07-16 969

1.基础知识

表单对应的是HTMLFormElement类型,继承自HTMLElement。
属性和方法如下:

  • 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,可以通过getElementById获取,也可以通过数值索引和name值获取。document.forms[0]或者document.forms['forms0'];

1.1提交表单
<!--通用提交按钮-->  
<input type="submit" value="submit form">  
<!--自定义提交按钮-->  
<button type="submit">submit form</button>  
<!--图像按钮-->  
<input type="image" src="test.jpg">  

只要表单中存在上面列出的任何一种按钮,那么在相应表单控件拥有焦点的情况下,按回车键就可以提交表单。(textarea是一个例外,在文本区回车换行。)如果表单里没有提交按钮,按回车键不会提交表单。
使用preventDefault()事件,可以阻止提交事件。

var myForm = document.getElementById('myForm');  
myForm.onsubmit = function (ev) {  
    ev.preventDefault(); // 取消表单提交  
}  

使用submit()可以直接提交表单。

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

在调用submit()方法的形式提交表单时,不会触发submit()事件,因此要记得在调用此方法之前先验证表单数据。

1.2 重置表单

<!--自定义重置按钮-->  
<button type="reset">恢复</button>  
<!--通用重置按钮-->  
<input type="reset" value="reset">  

通过event.preventDefault()可以阻止重置表单
通过获取表单的节点,重置表单。

<button type="button" onclick="resetForm()">恢复</button>  
function resetForm() {  
    var myForm = document.getElementById('myForm');  
    myForm.reset();  
}  

1.3表单字段

每个表单都有elements属性,该属性是表单中所有表单元素(字段)的集合。这个elements集合是一个有序元素,包含表单所有字段。每个表单字段在elements集合中的顺序,与它们出现标记中的顺序相同,可以按照位置和name特性来访问它们。

var form = document.getElementById('form1');  
// 取得表单中的第一个字段  
var field1 = form.elements[0];  
// 取得名为“textbox1”的字段  
var field2 = form.elements['textbox1];  
// 取得表单中包含的字段的数量  
var fieldCount = form.elemenets.length;  

如果有多个表单控件都在使用同一个name,那么返回以该name命名的NodeList。

<form id="form2">  
    <ul>  
        <li><input type="radio" name="color" value="red" checked>red</li>  
        <li><input type="radio" name="color" value="blue">blue</li>  
        <li><input type="radio" name="color" value="pink">pink</li>  
    </ul>  
</form>  
<script>  
    function myForm2() {  
        let form2 = document.getElementById('form2');  
        let colorFields = form2.elements['color'];  
        console.log(colorFields) // RadioNodeList(3) [input, input, input, value: "red"]  
        console.log(colorFields.value) // 获取选中值  
    }  
</script>  
1.表单共有的属性

除了<fieldset>外,所有表单字段都包括disabled,form,name,readOnly,tabIndex,type,value
除了form属性外,可以通过js动态修改其他任何属性。
除了<fieldset>外,所有表单字段都有type属性。

2.共有的表单字段方法

每个表单字段都有两个方法:focus()和blur()。其中,focus()方法用于将浏览器的焦点设置到表单字段,即激活表单字段,使其可以响应键盘事件。
HTML5为表单字段新增了一个autofocus的属性,在支持此属性的浏览器中,只要设置这个属性,可以将焦点移动到相应字段。

<input type="text" autofocus>  

使用element.autofocus可以判断浏览器是否支持该属性,因为在支持的浏览器中该值为true,而不支持的浏览器中该值为空字符串。支持此属性的浏览器有Firefox4+,Safari5+,Chrome,Opera9.6.
注意在默认情况下,只有表单字段可以获取焦点。其他元素,如果先将其tabIndex置为-1,然后再调用focus()方法,也可以让这些元素获得焦点。
blur()的作用是移除焦点。

3.共有表单字段事件

blur,focus不介绍了
change:对于<input><textarea>元素,在它们失去焦点且value值改变时触发;对于<select>元素,在其选项改变时触发。

<ul id="ul0">  
    <li><input type="radio" name="color" value="red">red</li>  
    <li><input type="radio" name="color" value="blue">blue</li>  
    <li><input type="radio" name="color" value="pink">pink</li>  
</ul>  
// 事件委托  
var ul0 = document.getElementById('ul0');  
ul0.addEventListener('change', function (event) {  
    console.log(event.target.value) // 获取radio的值  
})  

获取复选框的值

<ul id="ul1">  
    <li><input type="checkbox" name="color" value="red">red</li>  
    <li><input type="checkbox" name="color" value="blue">blue</li>  
    <li><input type="checkbox" name="color" value="pink">pink</li>  
</ul>

var checkValues = [];  
    var ul1 = document.getElementById('ul1');  
    ul1.addEventListener('change', function (event) {  
    if (event.target.checked && checkValues.indexOf(event.target.value) === -1 ) {  
        console.log(event.target.value);  
        checkValues.push(event.target.value);  
    } else {  
        var index = checkValues.indexOf(event.target.value);  
        checkValues.splice(index)  
    }  
});  

2.文本框脚本

两种文本框:1.使用<input>的单行文本框2.使用<textarea>的多行文本框。

2.1选择文本

以上两种文本框都支持select()方法,这个方法用于选择文本框中的所有文本。在调用select()方法时,大多数浏览器都会将焦点设置到文本框中。这个方法不接受参数,可以在任何时候调用。

2.1.1选择事件

select事件支持所有的浏览器,只是触发select事件的方式不同。在IE9+、Opera、Firefox、Chrome和Safari浏览器中,只要用户选择了文本就会触发该事件,而在IE8及更早版本中,只要用户选择了一个字母(不必释放鼠标),就会触发select事件。另外在调用select()方法时,也会触发select事件

2.1.2取得选择的文本

该规范是添加两个属性:selectionStart和selectionEnd。这两个属性中保存的都是基于0的数值,表示所选择的文本范围(即文本选区开头和结尾的偏移量)。要取得用户在文本框中选择的文本,可以采用如下代码:

<textarea placeholder="请输入文字" id="textarea0"></textarea>  
var textarea = document.getElementById('textarea0');  
        textarea.addEventListener('select', function (event) {  
            console.log(textarea.value, textarea.selectionStart, textarea.selectionEnd);        console.log(textarea.value.substring(textarea.selectionStart, textarea.selectionEnd)) // 获取选中的文本  
})  

IE8不支持这两个属性。为了使IE8也实现此效果,可以使用document.selection对象。

if (document.selection){  
    return document.selection.createRange().text;  
    }  
2.1.3选择部分文本

HTML5为选择文本框中的部分文本提供了解决方案,现在所有的文本框都有一个setSelectionRange()方法。这个方法支持两个参数:要选择的第一个字符的索引和要选择的最后一个字符的索引。此方法不是获取选中部分的值,而是控制光标的位置。

var textarea = document.getElementById('textarea0');

textarea.addEventListener('select', function (event) {  
    const text0 = textarea.value;  
    console.log(text0, text0.length);  
    textarea.setSelectionRange(0, 10)  
})  


IE8及之前的浏览器,需要使用createTextRange()方法创建范围。
跨浏览器兼容的代码如下:

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(textbox, 0, textbox.value.length)  

2.2过滤输入

需求:希望用户输入的文本中包含或者不包含特定的字符。
用户在输入时会调用keypress事件。因此可以阻止这个事件的默认行为来屏蔽不希望出现的字符。
如果只希望屏蔽部分字符,可以参考下方代码:

if (!/\d/.test(String.fromCharCode(charCode)) && charCode > 9 && !event.ctrlKey){  
    event.preventDefault();  
}  
2.3操作剪贴板

6个剪贴板事件:
beforecopy:在发生复制操作前触发
copy:在发生复制操作时触发
beforecut:在发生剪切操作前触发
cut:在发生剪切操作时触发
beforepaste:在发生粘贴操作前触发
paste:在发生粘贴操作时触发

在实际的事件发生之前,通过beforecopy,beforecut和beforepaste事件可以在向剪贴板发送数据,或者从剪贴板取得数据之前修改数据。
访问剪贴板的数据,可以使用cliboardData对象,在IE中这个对象是window对象的属性;而在Firefox 4+,Safari和Chrome中是event的属性。
这个clipboardData对象有三个方法:getData(),setData()和clearData().
getData():从剪贴板中取得数据,它接受一个参数,即要取得的数据的格式。在IE中,有两种数据格式:“text”和“URL”。在Firefox,Safari,Chrome中,这三个参数是一种MIME类似;可以使用text代替‘text/plain’
setData():第一个参数数据类型,第二个参数是放在剪贴板中的文本。对于第一个参数,IE支持text和URL,而Safari和Chrome只支持MIME类型。但是Safari和Chrome不能识别text类型。两个浏览器在成功将文本放到剪贴板中后,都会返回true;否则,返回false。

// 获取剪贴板数据  
var getData =  function (event) {  
    var clipboardData = (event.clipboardData || window.clipboardData);  
    return clipboardData.getData('text');  
}  
// 设置数据  
var setData = function (event, value) {  
    if (event.clipboardData) {  
        return event.clipboardData.setData("text/plain", value);  
    } else if (window.clipboardData){  
        return window.clipboardData.setData("text", value);  
    }  
}  

前面讲到在剪贴时,可以修改数据,下面提供一个示例:

function copyText(){  
    var textbox = document.getElementById('text1');  
    textbox.addEventListener('copy', function (event) {  
        console.log(event.target.value);  
        event.clipboardData.setData("text/plain", "你好" + event.target.value);  
        console.log(event.clipboardData.getData('text'))  
    })  
}  
2.4HTML5约束字段API

1.必填字段
required属性
2.其他输入类型
html5新增了几个类型,如email,url等
3.数值范围
新增了几个数值类型,如number,datetime,date,month,week,range,time。但是部分浏览器可能不兼容。
4.输入模式
h5为文本字段新增了pattern属性。这个属性是一个正则表达式,用来匹配文本框中的值。

<input type="text" pattern="\d+" name="count">  

注意,模式的开头和结尾不需要加^$
5.检测有效性
使用checkValidity()方法可以检测表单中某个字段是否有效。所有表单字段都有这个方法,如果有效返回true否则返回false。
如果要检测整个表单是否有效,可以在表单自身调用checkValidity()方法。如果所有表单字段都有效,这个方法返回true,即使一个字段无效,也会返回false。
validity属性可以告诉你为什么字段有效或者无效。这个对象包含一系列属性。如下图

6.禁用验证
设置novalidate属性,可以让表单不进行验证

<form method="post" novalidate>  
</form>  

在js中使用noValidate属性可以取得或者设置这个值,若值存在为true,否则false。

3.选择框脚本

select选择框,是HTMLSelectElement类型:

  • add(newOption, relOption):向控件中插入新<option>元素,其位置在相关项(relOption)之前。
  • multiple:布尔值,表示是否允许多项选择;等价于HTML中的multiple特性。
  • options:控件中所有<option>元素的HTMLCollection.
  • remove(index): 移除给定位置的选项
  • selectedIndex:基于0的选中项,如果没有选中项,则值为-1。对于支持多选的控件,只保存选中项中的第一项的索引。
  • size:选择框中可见的行数;等价于HTML中的size特性。size是设置在<select>中,表示options的可见数目

选择框的type属性取决于multiple,如果没有此属性,那么type就是select-one,否则就是select-multiple。

  • 如果没有选中项,则value为空字符串
  • 有一个选中项,则value等于选中项的值
  • 如果有一项选中,但该项value特性未指定,则选择框的value属性等于该项文本(<option>aaa</option>
  • 如果有多个选中项,则选择框value属性将依据前2条规则取得第一个选中项的值。

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

示例:

<select name="hobby" id="hobby">  
    <option value="篮球">篮球</option>  
    <option value="乒乓球">乒乓球</option>  
    <option value="网球">网球</option>  
</select>  
<script>  
var hobby = document.getElementById('hobby');  
console.log(hobby.options) // HTMLOptionsCollection(3) [option, option, option, selectedIndex: 0]  
hobby.options[0].value // 篮球  
hobby.options[0].text // 篮球  
hobby.options[0].selected // true  
// 向末尾添加option  
var newoption = document.createElement('option');  
newoption.text = '羽毛球'  
newoption.value = '羽毛球'  
hobby.add(newoption, null)  
// 向篮球后面加入option  
var newoption2 = document.createElement('option');  
newoption2.text = '桌球'  
newoption2.value = '桌球'  
var rel = hobby.options[1]  
hobby.add(newoption2, rel)  
</script>  

4.表单序列化

利用表单字段的type属性,连同name和value属性一起实现对表单的序列化。推荐使用jQuery的表单序列化,比原生简单很多。
jq:

$("button").click(function(){  
  $("div").text($("form").serialize());  
});  

原生:

Object.prototype.serialize = function(){  
    var res = [],   //存放结果的数组  
        current = null, //当前循环内的表单控件  
        i,  //表单NodeList的索引  
        len, //表单NodeList的长度  
        k,  //select遍历索引  
        optionLen,  //select遍历索引  
        option, //select循环体内option  
        optionValue,    //select的value  
        form = this;    //用form变量拿到当前的表单,易于辨识

    for(i=0, len=form.elements.length; i<len; i++){  

        current = form.elements[i];  

        //disabled表示字段禁用,需要区分与readonly的区别  
        if(current.disabled) continue;  

        switch(current.type){  

            //可忽略控件处理  
            case "file":    //文件输入类型  
            case "submit":  //提交按钮  
            case "button":  //一般按钮  
            case "image":   //图像形式的提交按钮  
            case "reset":   //重置按钮  
            case undefined: //未定义  
                break;  

            //select控件  
            case "select-one":  
            case "select-multiple":  
                if(current.name && current.name.length){  
                    console.log(current)  
                    for(k=0, optionLen=current.options.length; k<optionLen; k++){  

                        option = current.options[k];  
                        optionValue = "";  
                        if(option.selected){  
                            if(option.hasAttribute){  
                                optionValue = option.hasAttribute('value') ? option.value : option.text  
                            }else{  
                                //低版本IE需要使用特性 的specified属性,检测是否已规定某个属性  
                                optionValue = option.attributes('value').specified ? option.value : option.text;      
                            }  
                            res.push(encodeURIComponent(current.name) + "=" + encodeURIComponent(optionValue));  
                        }  
                    }  
                }  
                break;  

            //单选,复选框  
            case "radio":  
            case "checkbox":  
                //这里有个取巧 的写法,这里的判断是跟下面的default相互对应。  
                //如果放在其他地方,则需要额外的判断取值  
                if(!current.checked) break;  

            default:  
                //一般表单控件处理  
                if(current.name && current.name.length){  
                    res.push(encodeURIComponent(current.name) + "=" + encodeURIComponent(current.value));  
                }  

        }  
    }  


    return res.join("&");  
}  

5.富文本编辑

详情点击此处查看

标签:JavaScript

文章评论

评论列表

已有0条评论