JavaScript 表单处理实现代码


Posted in Javascript onApril 13, 2015

一 表单介绍

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

// HTMLFormElement继承了HTMLElement;因此它拥有HTML元素具有的默认属性,别且还独有自己的属性和方法;
HTMLFormElement属性和方法
属性或方法 说明
acceptCharset 服务器能够处理的字符集;
action 接受请求的URL;
elements 表单中所有控件的集合;
enctype 请求的编码类型;
length 表单中控件的数量;
method 要发送的HTTP请求类型,通常是'get'或'post';
name 表单的名称;
target 用于发送请求和接受响应的窗口名称;
reset() 将所有表单重置;
submit() 提交表单;

 1.获取表单<form>对象;
document.getElementById('myForm'); // 使用ID获取<form>元素;
document.getElementsByTagName('form')[0]; // 使用获取form元素集合里的第一个元素;
document.forms[0]; // 使用forms的数字下标获取元素;
document.forms['myForm']; // 使用forms的名称下标获取元素;

2.提交表单

(1).通过事件对象,可以阻止submit的默认行为,submit事件的默认行为就是携带数据跳转到指定页面;

    addEvent(fm,'submit',function(evt){

        preDef(evt);

    });

(2).我们可以使用submit()方法来自定义触发submit事件;也就是说,并不一定非要点击submit按钮才能提交;

    if(e.ctrlKey && e.keyCode ==13){

        fm.submit();                           // 判断按住了ctrl和enter键触发提交;

    }

    // PS:在表单中尽量避免使用name="submit"或id="submit"等命名,这会和submit()方法发生冲突导致无法提交;

(3).重复提交
// 当一条数据提交到服务器的时候会出现延迟等长时间没反映,导致用户不停的点击提交,
// 从而使得重复提交了很多相同的请求,或造成错误或写入数据库多条相同信息;

    addEvent(fm,'submit',function(evt){        // 模拟服务器延迟;

        preDef(evt);

        setTimeout(function(){                 // 3秒后才处理提交到服务器;

            fm.submit();

        },3000);

    });
// 解决重复提交方案

// 第一种:提交之后,立刻禁用点击按钮;

    document.getElementById('sub').disabled = true;      // 将按钮禁用;

// 第二种:提交之后,取消后续的表单提交操作;

    var flag = false;                                    // 设置一个监听变量;

    if(flag == true)return;                              // 如果存在则返回退出事件;

    flag = true;                                         // 否则确定是第一次,改变监听变量的值;

3.重置表单

// 用户点击重置按钮时,表单会被初始化;
// 虽然这个按钮还得以保留,但目前Web已经很少去使用了;因为用户填好信息后,不小心点击了重置就会全部清空,用户体验极差;
// 有两种方法调用reset事件:第一个就是直接type="reset"即可;第二个就是使用fm.reset()方法调用;
  <input type="reset" value="重置" />          // 不需要JS代码即可实现;
  addEvent(document,'click',function(){
    fm.reset();                   // 使用JS方法实现重置;
  });

4.表单字段

// 表单处理中,建议使用HTMLDOM,它有自己的elements属性,该属性是表单中所有元素的集合;
    fm.elements[0];                                     // 获取第一个表单字段元素;
    fm.elements['user'];                                // 获取name值是user的表单字段元素;
    fm.elements.length;                                 // 获取所有表单字段的数量;

(1).共有的表单字段属性
// 除了<fieldset>元素之外,所有表单字段都拥有相同的一组属性;
属性                     说明
disabled         布尔值,表示当前字段是否被禁用;
form             指向当前字段所属表单的指针,只读;
name             当前字段的名称;
readOnly         布尔值,表示当前字段是否只读;
tabIndex         表示当前字段的切换;
type             当前字段的类型;
value            当前字段的值;
    fm.elements[0].value;                               // 获取和设置value;
    fm.elements[0].disabled = true;                     // 禁用当前字段;

(2).共有的表单字段方法
方法                     说明
focus()          将焦点定位到表单字段里;
blur()           从元素中将焦点移走;

(3).共有的表单字段事件

事件名                     说明
blur             当字段失去焦点时触发;
change           对于<input>和<textarea>元素,在改变value并失去焦点时触发;对于<select>元素,在改变选项时触发;
focus            当前字段获取焦点时触发;

// 利用focus事件修改文本框的背景色;
// 利用change事件在用户输入非数值字符时再次修改背景色;
  var bextbox = document.forms[0].elements[0];
  EventUtil.addHandler(textbox,'focus',function(evt){
    evt = EventUtil.getEvent(evt);
    var target = EventUtil.getTarget(evt);
    if(target.style.backgroundColor != 'red'){
      target.style.backgroundColor = 'yellow';    // 选中状态时文本框的背景是黄色;
    }
  });

  EventUtil.addHandler(textbox,'blur',function(evt){   // 失去焦点事件;
    evt = EventUtil.getEvent(evt);
    var target = EventUtil.getTarget(evt);
    if(/[^\d]/.test(target.value)){           // 输入非数值字符时;
      target.style.backgroundColor = 'red';      // 文本框背景变成红色;
    }else{
      target.style.backgroundColor = '';
    }
  });

  EventUtil.addHandler(textbox,'change',function(evt){  // 改变value值且失去焦点事件;
    evt = EventUtil.getEvent(evt);
    var target = EventUtil.getTarget(evt);
    if(/[^\d]/.test(target.value)){
      target.style.backgroundColor = 'red';      // 文本框变成红色;
    }else{
      target.style.backgroundColor = '';
    }
  });

二 文本框脚本
// 在HTML中,有两种方式来表现文本框:

// 一种是单行文本框<input type="text">;

// 一种是多行文本框<textarea>;

1.获取value值

// 虽然<input>在字面上有value值,而<textarea>却没有,但可以通过value获取它们的值;
    var textField = fm.elements[0];
    var areaField = fm.elements[1];
    alert(textField.value+','+areaField.value);           // 得到<input>和<textarea>的value值;
    // PS:使用表单的value是最推荐的,它是HTMLDOM中的属性,不建议使用标准的DOM的方法getAttribute();
    // 原因是:对value属性的修改,不一定反映在DOM中;

// defaultValue:得到原本的value值;不会因为值的改变而变化;
    alert(textField.defaultValue);                        // 得到最初设置的value值;

2.选择文本

// 使用select()方法,可以将文本框里的内容选中,并将焦点设置到文本框中;
  textField.select();                   // 在文本框获得焦点时选择其所有文本;

// 选取部分文本
// 在使用文本框内容的时候,我们有时要直接选定部分文本,这个行为还没有标准;
// Firefox的解决方案是:setSelectionRange()方法;它接受两个参数:索引和长度;
  textField.setSelectionRange(0,1);            // 选择第一个字符;
  textField.setSelectionRange(0,textField.value.length);  // 选择全部; 
  // IE8以下不支持这种写法,可以使用IE的范围操作代替;
  var range = textField.createTextRange();         // 创建一个文本范围对象;
  range.collapse(true);                  // 将指针移动到起点;
  range.moveStart('character',0);             // 移动指针,character表示逐字移动;
  range.moveEnd('character',1);              // 移动终点;
  range.select();                     // 焦点选定;

// 选择部分文本兼容函数
  function selectText(text,start,stop){
    if(text.setSelectionRange){
      text.setSelectionRange(start,stop);
      text.focus();
    }else if(text.createTextRange){
      var range = text.createTextRange();
      range.collapse(true);
      range.moveStart('character',start);
      range.moveEnd('character',sotp-start);
      range.select();
    }
  }

// 与select()方法对应的,是一个select事件,可以选中文本框文本后触发;
  addEvent(textField,'select',function(){
    alert(this.value);                // IE事件需要传递this才可以这么写;
  });
// 获得选择的文本
// Firefox提供了两个属性:selectionStart和selectionEnd;
  addEvent(textField,'select',function(){
    alert(this.value.substring(this.selectionStart,this.selectionEnd));
  });
  // IE8以下,提供了另一个方案:selection对象,属于document;
  // 这个对象保存着用户在整个文档范围内选择的文本信息;
  // 兼容函数
  function getSelecText(text){
    if(typeof text.selectioinStart =='number'){     // 非IE;
      return text.value.substring(text.selectionStart,text.selectionEnd);
    }else if(document.selection){            // IE;
      return document.selection.createRange().text;  // 获取IE选择的文本;
    }
  }
  // PS:存在问题:IE在触发select事件的时候,在选择一个字符后立即触发,而其他浏览器是选择想要的字符后释放鼠标键时再触发;
  // 所以使用alert()的话,导致跨浏览器的不兼容;
  // 所以我们可以通过将得到的选择文本赋值给别的对象;
  addEvent(textField,'select',function(){
    // alert(getSelecText(this));            // 导致用户行为结果不一致; 
    document.getElementById('box').innerHTML = getSelecText(this);
  })

3.过滤输入

// 为了使文本框输入指定的字符,我们必须对输入进文本框的字符进行验证;
  addEvent(areaField,'keypress',function(evt){
    var e = evt || window.event;
    var charCode = getCharCode(evt);      // 得到字符编码;
    if(!/\d/.test(String.formCharCode(charCode)) && charCode>9 && !e.ctrlKey){
      preDef(evt);              // 条件阻止默认;
    }
  });
  // PS:前半段条件判断只有数字才可以输入,导致常规按键,比如光标键/退格键/删除键等无法使用;
  // 部分浏览器比如Firefox,需要解放这些键,而非字符触发的编码均为0;
  // 在Safari3之前的浏览器,也会被阻止,而它对应的字符编码全部为8,所以最后加上charCode>9的判断;
  // 确保用户没有按下ctrl键;
// 阻止文本框裁剪/复制和粘贴;
事件名        说明
copy     在发生复制操作时触发;
cut      在发生裁剪操作时触发;
paste     在发生粘贴操作时触发;
beforecopy  在发生复制操作时触发;
beforecut   在发生裁剪操作时触发;
beforepaste  在发生粘贴操作时触发;
// 如果我们想要禁用裁剪/复制/粘贴,那么可以阻止默认行为即可;
  addEvent(areaField,'cut',function(evt){
    preDef(evt);
  });
  addEvent(areaField,'copy',function(evt){
    preDef(evt);
  });
  addEvent(areaField,'paste',function(evt){
    preDef(evt);
  });

// 最后一个影响输入的因素,就是:输入法;
// 中文输入法,它的原理是在输入法面板上先储存文本,按下回车就写入英文文本,按下空格就写入中文文本;
// 解决方案:通过CSS来禁止调出输入法;
  style='ime-mode:disabled';          // CSS直接编写;
  areaField.style.imeMode='disabled';      // 在JS中设置;
  // PS:Chrome无法禁止输入法调出,所以,最后使用正则验证已输入的文本;
  addEvent(areaField,'keyup',function(evt){
    this.value = this.value.replace(/[^\d]/g,'');  // 把非数字都替换成空;
  });

4.自动切换焦点

// 为了增加表单字段的易用性,很多字段在满足一定条件时(比如长度),就会自动切换到下一个字段上继续填写;
  <input type='text' name='user1' maxlength='1'/>    // 只能写1个;
  <input type='text' name='user2' maxlength='2'/>   
  <input type='text' name='user3' maxlength='3'/>
  function tabForward(evt){
    var e = evt || window.event;
    var target = getTarget(evt);
    // 判断当前长度是否和指定长度一致;
    if(target.value.length == target.maxLength){
      // 遍历所有字段;
      for(var i=0; i<fm.elements.length; i++){
        // 找到当前字段;
        if(fm.elements[i]==target){
          // 就把焦点移入下一个字段;
          if(fm.elements[i+1]){
            fm.elements[i+1].focus();
          }
          // 中途返回;
          return;
        }
      }
    }
  }

三 选择框脚本

选择框是通过<select>和<option>元素创建的;

HTMLSelectElement对象

属性/方法                 说明
add(new,rel)        插入新元素,并指定位置;
multiple            布尔值,是否允许多项选择;
options             <option>元素的HTMLCollection集合;
remove(index)       移除给定位置的选项;
selectedIndex       基于0的选中项的索引,如果没有选中项,则值为-1;
size                选择框中可见的行数;

// 在DOM中,每个<option>元素都有一个HTMLOptionElement对象,以便访问数据;
HTMLOptionElement对象
属性 说明
index 当前选项在options集合中的索引;
label 当前选项的标签;
selected 布尔值,表示当前选项是否被选中;
text 选项的文本;
value 选项的值;

var city = fm.elements['city'];      // HTMLSelectElement;
  alert(city.options);            // HTMLOptionsCollection;
  alert(city.options[0]);          // HTMLOptionElement;
  alert(city.type);             // select-one;
  // PS:选择框里的type属性有可能是:select-one,也有可能是:select-multiple;
  // 这取决于HTML代码中有没有multiple属性;

  alert(city.options[0].text);       // 上海text,获取text值;
  alert(city.options[0].value);      // 上海value,获取value值;
  // PS:操作select时,最好使用HTMLDOM,以为浏览器兼容性比较好;
  // 如果使用标准DOM,会因为不同的浏览器导致不同的结果;
  // PS:当选项没有value值的时候,IE会返回空字符串,其他浏览器会返回text值;

2.选择选项

对于只能选择一项的选择框,使用selectedIndex属性最为简单;

    addEvent(city,'change',function(){

        alert(this.selectedIndex);                        // 得到当前选项的索引,从0开始;

        alert(this.options[this.selectedIndex].text);     // 得到当前选项的text值;

        alert(this.options[this.selectedIndex].value);    // 得到当前选项的value值;

    });

    city.selectedIndex = 1;                               // 设置selectedIndex可以定位某个索引;

通过option的属性selected(布尔值),也可以设置定位某个索引,设置为true即可;
    city.options[0].selected = true;                      // 设置第一个索引;

selected和selectedIndex区别:
1.selected是返回的布尔值;所以一般用于判断上;
2.selectedIndex返回的是数值,一般用于设置和获取;

    addEvent(city,'change',function(){

        if(this.options[2].selected == true){             // 判断第三个选项是否被选定;

            alert('正确!');

        }

    });

3.添加选项
// 如需要动态的添加选项,我们提供两种方案:DOM和Option构造函数;
(1).DOM
var option = document.createElement('option');
option.appendChild(document.createTextNode('北京 text'));
option.setAttribute('value','北京 value');
city.appendChild(option);

(2).Option构造函数
var option = new Option('北京 text','北京 value');
city.appendChild(option); // IE出现bug;

(3).使用add()方法来添加选项:
var option = new Option('北京 text','北京 value');
city.add(option,0); // 0,表示添加到第一位;
// PS:在DOM规定,add()中两个参数是必须的,如果不正确索引,那么第二个参数设置null即可,即默认移入最后一个选项;
// 但在IE中第二个参数是可选的,所以设置null表示放入不存在的位置,导致失踪;
// 为了兼容性,可以传递undefined即可兼容;
city.add(option,null); // IE不显示了;
city.add(option,undefined); // 兼容;

 4.移除选项

// 有三种方式可以移除某一个选项:DOM移除/remove()方法移除和null移除;
city.removeChild(city.option[0]); // DOM移除;
city.remove(0); // remove()移除,推荐;
city.options[0] = null; // null移除;
// PS:当第一项移除后,下面的项,往上移,所以不停的移除第一项,即可全部移除;

5.移动选项

// 如果有两个选择框,把第一个选择框里的第一个选项移到第二个选择框里,并且第一个选择框里的第一项被移除;
var city = fm.elements['city']; // 第一个选择框;
var info = fm.elements['info']; // 第二个选择框;
info.appendChild(city.options[0]); // 移动,并在第一个选择框中删除;

 6.排列选项

选择框提供了一个index属性,可以得到当前选项的索引值,和selectedIndex的区别是,一个是选择框对象的调用,一个是选项对象的调用;

     var option1 = city.options[1];

     city.insertBefore(option1,city.options[option1.index-1]);    // 往上移位;

7.单选按钮

// 通过checked属性来获取单选按钮的值;
  for(var i=0; i<fm.sex.length; i++){          // 循环单选按钮; 
    if(fm.sex[i].checked == true){           // 遍历每一个,找出处于选中状态的那一个;
      alert(fm.sex[i].value);            // 得到值;
    }
  }
  // PS:除了checked属性之外,单选按钮还有一个defaultChecked按钮,
  // 它获取的是原本的checked按钮对象,而不会因为checked的改变而改变;
  if(fm.sex[i].defaultChecked == true){
    alert(fm.sex[i].value);
  }

8.复选按钮

// 通过checked属性来获取复选按钮的值,
  var love = '';
  for(var i=0; i<fm.love.length; i++){
    if(fm.love[i].checked == true){
      love += fm.love[i].value;
    }
  }
  alert(love);
Javascript 相关文章推荐
IE8提示Invalid procedure call or argument 异常的解决方法
Sep 30 Javascript
jQuery异步获取json数据方法汇总
Dec 22 Javascript
JavaScript实现的一个倒计时的类
Mar 12 Javascript
利用jQuery实现漂亮的圆形进度条倒计时插件
Sep 30 Javascript
纯JavaScript基于notie.js插件实现消息提示特效
Jan 18 Javascript
整理AngularJS框架使用过程当中的一些性能优化要点
Mar 05 Javascript
Javascript闭包与函数柯里化浅析
Jun 22 Javascript
JS获取当前页面名称的简单实例
Aug 19 Javascript
jquery实现的回旋滚动效果完整实例【附demo源码下载】
Sep 20 Javascript
js文件中直接alert()中文出来的是乱码的解决方法
Nov 01 Javascript
深入浅析javascript继承体系
Oct 23 Javascript
JS实现简单省市二级联动
Nov 27 Javascript
JavaScript 事件绑定及深入
Apr 13 #Javascript
JavaScript 事件对象介绍
Apr 13 #Javascript
JavaScript 事件入门知识
Apr 13 #Javascript
JavaScript 动态加载脚本和样式的方法
Apr 13 #Javascript
JavaScript DOM元素尺寸和位置
Apr 13 #Javascript
JavaScript DOM操作表格及样式
Apr 13 #Javascript
JavaScript DOM进阶方法
Apr 13 #Javascript
You might like
真正的ZIP文件操作类(php)
2007/07/21 PHP
PHP的array_diff()函数在处理大数组时的效率问题
2011/11/27 PHP
php curl登陆qq后获取用户信息时证书错误
2015/02/03 PHP
php使用GD实现颜色渐变实例
2015/06/02 PHP
Laravel学习教程之model validation的使用示例
2017/10/23 PHP
javascript之锁定表格栏位
2007/06/29 Javascript
jquery插件开发之实现md5插件
2014/03/17 Javascript
JavaScript通过this变量快速找出用户选中radio按钮的方法
2015/03/23 Javascript
jquery实现可自动收缩的TAB网页选项卡代码
2015/09/06 Javascript
js+css实现select的美化效果
2016/03/24 Javascript
详解ES6通过WeakMap解决内存泄漏问题
2018/03/09 Javascript
详解原生JS动态添加和删除类
2019/03/26 Javascript
Vue Element UI + OSS实现上传文件功能
2019/07/31 Javascript
JS+html5实现异步上传图片显示上传文件进度条功能示例
2019/11/09 Javascript
[01:00:53]OG vs IG 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
详解python之简单主机批量管理工具
2017/01/27 Python
使用matplotlib画散点图的方法
2018/05/25 Python
详解用python自制微信机器人,定时发送天气预报
2019/03/25 Python
Python使用sax模块解析XML文件示例
2019/04/04 Python
python3 selenium自动化 下拉框定位的例子
2019/08/23 Python
Python with关键字,上下文管理器,@contextmanager文件操作示例
2019/10/17 Python
HTML5制作3D爱心动画教程 献给女友浪漫的礼物
2014/11/05 HTML / CSS
迪卡侬荷兰官网:Decathlon荷兰
2017/10/29 全球购物
Falconeri美国官网:由羊绒和羊毛制成的针织服装
2018/04/08 全球购物
英国第一的市场和亚马逊替代品:OnBuy
2019/03/16 全球购物
兰蔻英国官网:Lancome英国
2019/04/30 全球购物
什么是JNDI的上下文?如何初始化JNDI上下文
2012/03/10 面试题
如何在Shell脚本中使用函数
2015/09/06 面试题
英文版银行求职信
2013/10/09 职场文书
初中科学教学反思
2014/01/21 职场文书
《商鞅南门立木》教学反思
2014/02/16 职场文书
领导班子整改方案
2014/10/25 职场文书
防暑降温通知书
2015/04/27 职场文书
党员“一帮一”活动总结
2015/05/07 职场文书
JavaScript canvas实现流星特效
2021/05/20 Javascript
前端框架ECharts dataset对数据可视化的高级管理
2022/12/24 Javascript