表单的常用操作

知识点:

表单是前后端数据交互的一种重要方式,使用js操作表单也是十分常见的。不过好像每次到表单操作我都要去查API,所以本次想对表单的常用操作做个小结,以备后面随时查看。

首先,我们要知道如下的一些知识:

1. 表单字段在向后台提交数据时,使用的是表单控件的name属性的value,与id无关。(大家可以在百度搜细说表单找到Fish Li大神的这篇文章看看)

 

2. 表单向服务端传数据时会经过编码。目前基本上只会只使用二种编码规则:application/x-www-form-urlencoded 和 multipart/form-data , 这二个规则的使用场景简单地说就是:后者在上传文件时使用,其它情形则使用前者(默认)。当使用ajax的post方式向后端传数据时,也会常常设置其header头来模拟表单的数据提交方式:xhr.setRequestHeader(‘cotent-type’, ‘application/x-www-form-urlencoded ’);这样后端程序就可以像处理表单数据那种处理传过来的参数了

 

3. 表单字段共有的属性包括:

① disbled: 布尔值,表示当前字段是否禁用

② readOnly: 布尔值,表示当前字段是否是只读的

③ type: 当前字段类型,对input元素来说,type属性就等于其html中写定的type属性,如text, password, checkbox, radio, submit, textarea..

但要注意select元素的type,对于单选的select元素,其type为select-one, 多远的select元素,type为select-multiple

④ name:当前字段的名称,也是作为有效控件默认向服务器传送数据时的key

⑤ value: 对多远的select元素的value,select.value只能取到第一个选中option的value; 要获取checkbox和radio的value只有通过遍历。除此之外,其它元素的value即是将发向服务器的value,可以通过element.value直接得到

⑥ tabIndex: 当前字段的tab切换序号

⑦ form: 字段所属的表单

除了form属性不能写之外,其它共有属性都是可读写的

 

4 . 表单字段共的有方法有:focus(), blur()

 

5. 表单字段共有的事件有:focus, blur, change

 

6. select元素的额外方法:

除了表单字段共有的属性和方法外,select元素还有下列属性和方法:

① add(newOption, relOption), 向select元素中插入新的option, 新插入的option的位置在relOption之前

② opitions: 得到所有的option的HTMLCollection

③ remove(index): 移除指定位置的option

④ selectIndex: 获取选中项的索引(从0开始),若没有选中项,返回-1,对于支持多选项的select,返回第一个选中的项

⑤ size: 选择框中可见的行数,等价于HTML中的size属性

⑥ select的type属性为select-one/select-multiple

⑦ 如果没有选中项,select的value为空字符串 (“”);如果有一个选中项,且其option的value已经指定,则select的value为选中的option的value, 即使选中的option的value的值为空串;若选中的option的value值没有指定,则select的value为此option的文本;若有多个选中项,select的value以第一个选中的项为准

 

对于option元素,为了方便访问数据,HTMLOptionElement包含了以下属性:

① index: 此选项在options集合中的索引

② label:此选项的标签,等价于HTML中的label特性

③ selected:此选项是否被选中

④ text: 此选项的文本

⑤ value:此选项的值,等价于HTML中的value

 

实际练习

select操作封装:

select: {
    //select操作
    addItem: function(select, value, text, pos) {
        var option = document.createElement('option');
        option.setAttribute('value', value);
        option.innerHTML = text;
        if(pos) {
            select.insertBefore(option, select.querySelectorAll('option')[pos]);
        }
        //注意这里传了一个undefined参数,
        select.add(option, undefined);
        return option;
    },
    removeItem: function(select, index) {
        //可以使用select.options访问所有的options元素
        select.removeChild(select.options[index]);
        //select.remove(index) 这样也可以
    },
    selectItemByIndex: function(select, index) {
        var options = select.options;
         options[index].selected = true;
    },
    selectItemByVal: function(select, val) {
        var options = select.options, index;
        for(var i = 0, l = options.length; i < l; i++) {
            if(options[i].value === val) {
                index = i;
                break;
            }
        }
        this.selectItemByIndex(select, index);
    },
    val: function(select, value) {
        if(value) {
            this.selectItemByVal(select, value);
        } else {
            return select.value;
        }

    },
    getSelectedIndex: function(select) {
        //获取当前选中项的索引, 如果对象有设置mutiple属性,则返回一个索引数组
        var ret = [], i = 0, options, temp;

        if(! select.multiple) {
            return select.selectedIndex;
        }

        options = select.options;
        while(temp = options[i]) {
            if(temp.selected)
                ret.push(i)
            i++;
        }
        return ret;
    }
}

checkbox封装:

checkbox: {
    all: function(checkboxs, flag) {
        //全选, 全不选, flag === true,全选中, flag === false,全不选
        var checkbox, i = 0;
        while(checkbox = checkboxs[i]) {
            checkbox.checked = flag;
            i++;
        }
    },
    inverse: function(checkboxs) {
        //反选
        var checkbox, i = 0;
        while(checkbox = checkboxs[i]) {
            checkbox.checked = !checkbox.checked;
            i++;
        }
    },
    selectItemByVal: function(checkboxs, val) {
        var index;
        for(var i = 0, l = checkboxs.length; i < l; i++) {
            if(checkboxs[i].value === val) {
                checkboxs[i].checked = true;
                break;
            }
        }
    }
}

radio封装

radio: {
    selectItemByIndex: function(radios, index) {
        if(radios[index]) {
            radios[index].checked = true;
        }
    },
    selectItemByVal: function(radios, val) {
        var index;
        for(var i = 0, l = radios.length; i < l; i++) {
            if(radios[i].value === val) {
                radios[i].checked = true;
                break;
            }
        }
    }
}

取得有效表单控件的name和value,组成一个dataMap

dataMap: function(form) {
    //取得把有效的表单控件的name和值,组成一个数据map
    var nameMap = {},
        dataMap = {}, name, _slice = [].slice;

    //查找表单中有效的表单控件:
    /**
     * 什么是有效表单控件(参考Fish Li博客-细说表单):
     1. 控件不能是【禁用】状态,即指定【disabled="disabled"】。即:禁用的控件将不是成功控件。
     2. 如果一个表单包含了多个提交按键,那么仅当用户点击的那个提交按钮才算是成功控件。
     3. 对于checkbox控件来说,只有被用户勾选的才算是成功控件。
     4. 对于radio button来说,只有被用户勾选的才算是成功控件。
     5. 对于select控件来说,所有被选择的选项都做为成功控件,name由select控件提供。
     6. 对于file上传文件控件来说,如果它包含了选择的文件,那么它将是一个成功控件。
     */

        //收集input元素的name
    _slice.call(form.querySelectorAll('input')).forEach(function(e, i) {
        var name = e.name;
        if(! nameMap[name])
            nameMap[name] = name;
    });

    //收集select元素的name
    _slice.call(form.querySelectorAll('select')).forEach(function(e, i) {
        var name = e.name;
        if(! nameMap[name])
            nameMap[name] = name;
    });

    //收集textarea
    _slice.call(form.querySelectorAll('textarea')).forEach(function(e, i) {
        var name = e.name;
        if(! nameMap[name])
            nameMap[name] = name;
    });

    //遍历nameMap,并取得相应的表单控件的值,组成dataMap
    for(name in nameMap) {
        if(nameMap.hasOwnProperty(name)) {
            _slice.call(document.getElementsByName(name)).forEach(function(e, i) {
                if(e.type === 'checkbox'|| e.type === 'radio') {
                    //可能多远
                    dataMap[name] = dataMap[name] || [];
                    if(e.checked) {
                        dataMap[name].push(e.value);
                    }
                } else if(e.type === 'select-multiple') {
                    //注意可以多选的select的type属性为 select-multiple
                    //可能多选
                    dataMap[name] = dataMap[name] || [];
                    _slice.call(e.options).forEach(function(e, i) {
                        if(e.selected) {
                            dataMap[name].push(e.value);
                        }
                    });
                } else {
                    dataMap[name] = e.value;
                }
            })
        }
    }
    return dataMap;
}

练习时的源代码:下载地址

posted @ 2014-06-21 22:50  jagus720  阅读(450)  评论(0编辑  收藏  举报