虽然HTML和Web应用自诞生以来已经发生了天翻地覆的变化,但Web表单相对却没有什么改变。
使用JavaScript可以增强已有的表单字段,从而创造出新的功能,或者提升表单的易用性。
为此,表单、表单字段都引入了相应的属性和方法,以便JavaScript使用。下面介绍几个概念:
1)可以使用一些标准或非标准的方法选择文本框中的部分或部分文本。
2)大多数浏览器都采用了Firefox操作选择文本的方式,但ie仍然坚持自己的实现。
3)在文本框的内容变化时,可以通过侦听键盘事件以及检测插入的字符,来允许或禁止用户输入的某些字符。
除Opera之外的所有浏览器都支持剪贴板事件,包括copy、cut和paste.其他浏览器在实现剪贴板事件时也可以分
以下几种不同的情况:
1)IE、Firefox、Chrome和Safari允许通过JavaScript访问剪贴板中的数据,而Opera不允许这种访问方式。
2)即使是IE、Chrome和Safari,它们各自的实现方式也不相同。
3)Firefox、Chrome和Safari只允许在paste事件发生时读取剪贴板数据,而IE没有这个限制。
4)Firefox、Chrome和Safari只允许在发生剪贴板事件时访问与剪贴板相关的信息,而IE允许在任何时候访问相关信息。
在文本框内容必须限制为某些特定字符的情况下,就可以利用剪贴板事件来屏蔽通过粘贴向文本框中插入内容的操作。
选择框也是经常要通过JavaScript来控制的一个表单字段。由于有了DOM,对选择框的操作比以前要方便多了。
添加选项、移除选项、将选项从一个选择框移动到另一个选择框,甚至对选项进行排序等操作,都可以使用标准的DOM技术来实现。
富文本编辑功能是通过一个包含空HTML文档的iframe元素来实现的。通过将空文档的designMode属性设置为"on",就可以将该页面转换为可编辑状态,此时其表现如同字处理软件。另外,也可以将某个元素设置为contenteditable。
在默认情况下,可以将字体加粗或者将文本转换为斜体,还可以使用剪贴板。JavaScript通过使用execCommand()方法也可以实现相同的一些功能。另外,使用queryCommandEnabled()、queryCommandState()和queryCommandValue()方法则可以取得有关文本选区的信息。由于以这种方式构建的富文本编辑器并不是一个表单字段,因此在将其内容提交给服务器之前,必须将iframe或contenteditable元素中的HTML复制到一个表单字段中。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表单脚本</title>
<style>
.editable{
width:100px;
height: 100px;
border: 1px solid green;
}
</style>
</head>
<body>
<form name="myForm" id="myForm">
<!--通用提交按钮-->
<input type="submit" value="提交表单">
<!--自定义提交按钮-->
<button type="submit">提交表单</button>
<!--图像按钮-->
<input type="image" src="submit.png">
<!--通用重置表单-->
<input type="reset" value="重置表单">
<!--自定义重置表单-->
<button type="reset">重置表单</button>
<input type="text" name="textBox">
<!--自动获取焦点-->
<input type="text" autofocus>
<input type="submit" value="确定" name="submit_btn">
<!--自定义文本框-->
<input type="text" size="25" maxlength="50" value="文本框" name="textbox1">
<textarea rows="5" cols="25">多行文本框</textarea>
<input type="text" name="textbox2">
<input type="text" name="tel1" id="txtTel1" maxlength="3">
<input type="text" name="tel2" id="txtTel2" maxlength="3">
<input type="text" name="tel3" id="txtTel3" maxlength="4">
<!--填字段必-->
<input type="text" name="username" required>
<!--html5指定输入类型-->
<input type="email" name="email">
<input type="url" name="homepage">
<!--指定用户输入0~100之间5的倍数的值-->
<input type="number" min="0" max="100" step="5" name="count">
<!--只允许输入数值-->
<input type="text" pattern="\d+" name="count">
<!--选择框-->
<select name="location" id="selLocation">
<option value="上海">上海</option>
<option value="北京">北京</option>
<option value="深圳">深圳</option>
<option value="">中国</option>
<option>意大利</option>
</select>
<!--富文本编辑-->
<div class="editable" id="richedit" contenteditable></div>
</form>
<script src="l14.js"></script>
</body>
</html>
/**
* 表单脚本
*/
function cl(x){
console.log(x);
}
//跨浏览器事件对象
var EventUtil={
//添加事件监听
addHandler:function(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);//w3c
}else if(element.attachEvent){
element.attachEvent("on"+type,handler);//IE
}else{
element["on"+type]=handler;//低版本浏览器
}
},
//获取事件元素
getEvent:function(event){
return event?event:window.event;
},
//获取事件目标
getTarget:function(event){
return event.target||event.srcElement;
},
//阻止默认事件
preventDefault:function(event){
if(event.preventDefault){
event.preventDefault();//W3C
}else{
event.returnValue=false;//IE
}
},
//移除事件监听
removeHandler:function(element,type,handler){
if(element.removeEventListener){
element.removeEventListener(type,handler,false);//W3C
}else if(element.detachEvent){
element.detachEvent("on"+type,handler);//IE
}else{
element["on"+type]=null;//低版本浏览器
}
},
//阻止冒泡
stopPropagation:function(event){
if(event.stopPropagation){
event.stopPropagation();//W3C
}else{
event.cancelBubble=true;//IE
}
},
//相关元素属性
getRelatedTarget:function(event){
if(event.relatedTarget){
return event.relatedTarget;
}else if(event.toElement){
return event.toElement;
}else if(event.fromElement){
return event.fromElement;
}else{
return null;
}
},
//获取鼠标按钮属性
getButton:function(event){
if(document.implementation.hasFeature("MouseEvents","2.0")){
return event.button;
}else{//IE8及以下
switch (event.button){
case 0:
case 1:
case 3:
case 5:
case 7:
return 0;
case 2:
case 6:
return 2;
case 4:
return 1;
}
}
},
//获取鼠标滚轮事件属性
getWheelDelta:function(event){
if(event.wheelDelta){
return (client.engine.opera && client.engine.opera<9.5 ?
-event.wheelDelta:event.wheelDelta);
}else{
return -event.detail*40;
}
},
//获取字符编码属性
getCharCode:function(event){
if(typeof event.charCode=="number"){
return event.charCode;
}else{
return event.keyCode;
}
},
//获取剪贴板属性
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);
}
}
};
/**
*14.1 表单的基础知识
*/
//HTMLFormElement有独有的属性和方法
//acceptCharset、action、element、enctype、length、method、name、reset()、submit()、target
//取得<form>元素引用的方式:
var form=document.getElementById("myForm");
var firstForm=document.forms[0];
var myForm=document.forms["myForm"];
//14.1.1 提交表单
//form.submit();
//如何阻止表单提交
var form=document.getElementById("myForm");
EventUtil.addHandler(form,"submit",function(event){
//取得事件对象
event=EventUtil.getEvent(event);
//阻止默认事件
EventUtil.preventDefault(event);
});
//如何不让用户重复提交表单
//1.在第一次提交表单后就禁用提交按钮;2.利用onsubmit事件处理程序取消后续的表单提交操作
//14.1.2 重置表单(慎用)
//form.reset();
//阻止重置表单
var form=document.getElementById("myForm");
EventUtil.addHandler(form,"reset",function(event){
//取得事件对象
event=EventUtil.getEvent(event);
//阻止默认事件
EventUtil.preventDefault(event);
});
//14.1.3 表单字段
//每个表单都有elements属性,该属性是表单中所有元素的集合
var form=document.getElementById("myForm");
//取得表单中的第一个字段
var field1=form.elements[0];
//取得名为"textBox"的字段
var field2=form.elements["textBox"];
//取得表单中包含的字段的数量
var filedCount=form.elements.length;
//14.1.3.1 共有的表单字段属性
//disabled、form、name、readOnly、tabIndex、type、value
//通过js动态修改字段的属性
var form=document.getElementById("myForm");
var field=form.elements[0];
field.value="确认提交";//修改value属性
cl(field.form===form);//=>true 检查form属性的值
field.disabled=true;//禁用当前字段
field.type="email";//修改type属性
//避免多次提交表单
EventUtil.addHandler(form,"submit",function(event){
event=EventUtil.getEvent(event);
var target=EventUtil.getTarget(event);
//取得提交按钮
var btn=target.elements["submit_btn"];
//禁用按钮
btn.disabled=true;
});
//14.1.3.2 共有的表单字段方法
//focus()、blur()
//侦听load事件,在指定字段上调用focus方法
EventUtil.addHandler(window,"load",function(event){
var element=document.forms[0].elements["textBox"];
if(element.autofocus!==true){
element.focus();
}
});
//14.1.3.3 共有的表单字段事件
//focus事件、blur事件、change事件
var textBox=document.forms[0].elements["textBox"];
//获取焦点时设置背景色
EventUtil.addHandler(textBox,"focus",function(event){
event=EventUtil.getEvent(event);
var target=EventUtil.getTarget(event);
if(target.style.backgroundColor!="red"){
target.style.backgroundColor="yellow";
}
});
//失去焦点时改变背景色
EventUtil.addHandler(textBox,"blur",function(event){
event=EventUtil.getEvent(event);
var target=EventUtil.getTarget(event);
if(/[^\d]/.test(target.value)){//输入非数字后失去焦点,背景变红
target.style.backgroundColor="red";
}else{//输入的是数字失去焦点,背景恢复为无
target.style.backgroundColor="";
}
});
//改变文本内容时改变背景色
EventUtil.addHandler(textBox,"change",function(event){
event=EventUtil.getEvent(event);
var target=EventUtil.getTarget(event);
if(/[^\d]/.test(target.value)){//输入非数字后失去焦点,背景变红
target.style.backgroundColor="red";
}else{//输入的是数字失去焦点,背景恢复为无
target.style.backgroundColor="";
}
});
/**
* 14.2 文本框脚本
*/
var textbox1=document.forms[0].elements["textbox1"];
cl(textbox1.value);
textbox1.value="新的文本框";
cl(textbox1.value);
//14.2.1 选择文本
//调用select()方法,可以把焦点设置到文本框中
EventUtil.addHandler(textbox1,"focus",function(event){
event=EventUtil.getEvent(event);
var target=EventUtil.getTarget(event);
//获得焦点即选中所有的文本
target.select();
});
//14.2.1.1 选择(select)事件
EventUtil.addHandler(textbox1,"select",function(event){
cl("文本框选中了:"+textbox1.value);
});
//14.2.1.2 取得选择的文本
function getSelectedText(textBox){
return textBox.value.substring(textBox.selectionStart,textBox.selectionEnd);
}
//14.2.1.3 选择部分文本
textbox1.value="Hello world";
//选择所有文本
var str1=textbox1.setSelectionRange(0,textbox1.value.length);
//选择前3个字符
var str2=textbox1.setSelectionRange(0,3);
//14.2.2 过滤输入
//14.2.2.1 屏蔽字符
var textbox2=document.forms[0].elements["textbox2"];
EventUtil.addHandler(textbox2,"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);
}
});
//14.2.2.2 操作剪贴板
//剪贴板事件:beforecopy、copy、beforecut、cut、beforepaste、paste
EventUtil.addHandler(textbox2,"paste",function(event){
event=EventUtil.getEvent(event);
var text=EventUtil.getClipboardText(event);
if(!/^\d*$/.test(text)){
EventUtil.preventDefault(event);
}
});
//14.2.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("texTel1");
var textbox2=document.getElementById("texTel2");
var textbox3=document.getElementById("texTel3");
EventUtil.addHandler(textbox1,"keyup",tabForward);
EventUtil.addHandler(textbox2,"keyup",tabForward);
EventUtil.addHandler(textbox3,"keyup",tabForward);
})();
//14.2.4 HTML5约束验证API
//14.2.4.1 必填字段
//检查某个表单字段是否为必填字段
var isUsernameRequired=document.forms[0].elements["username"].required;
//测试浏览器是否支持required属性
var isRequiredSupported="required" in document.createElement("input");
//14.2.4.2 其他输入类型 email、url
//测试浏览器是否支持email类型
var input=document.createElement("input");
input.type="email";
var isEmailSupported=(input.type=="email");
//14.2.4.3 数值范围
//14.2.4.4 输入模式
//访问字段的pattern属性
var pattern=document.forms[0].elements["count"].pattern;
//检测浏览器是否支持pattern属性
var isPatternSupported="pattern" in document.createElement("input");
//14.2.4.5 检测有效性
//checkValidity()方法 validity属性
if(input.validity && !input.validity.valid){
if(input.validity.valueMissing){
alert("请输入一个值");
}else if(input.validity.typeMismatch){
alert("请输入一个email")
}else{
alert("没有输入值");
}
}
//14.2.4.6 禁用验证
//form标签中加novalidate属性
//input标签中formnovalidate属性
document.forms[0].noValidate=true;
document.forms[0].elements["btnNoValidate"].formNoValidate=true;
/**
* 14.3 选择框脚本
*/
//HTMLSelectElement类型提供了下列属性和方法:
//add(newOption,relOption)、multiple、options、remove(index)、selectedIndex、size
//<option>元素都有一个HTMLOptionElement对象,有下列属性
//index、label、selected、text、value
var selectbox=document.forms[0].elements["location"];
var text=selectbox.options[0].text; //选项的文本
var value=selectbox.options[0].value; //选项的值
//14.3.1 选择选项
//获得选中项
var selectedOption=selectbox.options[selectbox.selectedIndex];
//显示选中项的信息
cl("选项序号:"+selectbox.selectedIndex+"\n 选项文本:"+
selectedOption.text+"\n选项值:"+selectedOption.value);
//取得所有选中的项
function getSelectedOptions(selectbox){
var result=new Array();
var option=null;
for(var i= 0,len=selectbox.options.length;i<len;i++){
option=selectbox.options[i];
if(option.selected){
result.push(option);
}
}
return result;
}
//14.3.2 添加选项:add()方法、insertBefore()方法
var newOption=new Option("选项文本","选项值");
selectbox.add(newOption,undefined);//最佳方案
//14.3.3 移除选项:remove()方法
function clearSelectbox(selectbox){
for(var i= 0,len=selectbox.options.length;i<len;i++){
selectbox.remove(i);
}
}
//14.3.4 移动和重排选项
//将第一个选择框中的第一个选项移动到第二个选择框中
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]);
/**
* 14.4 表单序列化
*/
function serialize(form){
var parts=[],
field=null, i,len, j,optLen,option,optValue;
for(i=0,len=form.elements.length;i<len;i++){
field=form.elements[i];
switch(field.type){
case "select-one":
case "select-multiple":
if(field.name.length){
for(j=0,optLen=field.options.length;j<optLen;j++){
option=field.options[j];
if(option.selected){
optValue="";
if(option.hasAttribute){
optValue=(option.hasAttribute("value")?option.value:option.text);
}else{
optValue=(option.attributes("value").specified?option.value:option.text);
}
parts.push(encodeURIComponent(field.name)+"="+encodeURIComponent(optValue));
}
}
}
break;
case undefined: //字符集
case "file": //文件输入
case "submit": //提交按钮
case "reset": //重置按钮
case "button": //自定义按钮
break;
case "radio": //单选按钮
case "checkbox": //复选框
if(!field.checked){
break;
}
/*执行默认操作 */
default :
//不包含没有名字的表单字段
if(field.name.length){
parts.push(encodeURIComponent(field.name)+"="+encodeURIComponent(optValue));
}
}
}
return parts.join("&");
}
/**
* 14.5 富文本编辑
*/
//designMode属性
EventUtil.addHandler(window,"load",function(){
frames["richedit"].document.designMode="on";
});
//14.5.1 使用contenteditable属性
var richedit=document.getElementById("richedit");
richedit.contentEditable="true";
//14.5.2 操作富文本
//document.execCommand()
//转换粗体文本
document.execCommand('bold',false,null);
//转换斜体文本
document.execCommand('italic',false,null);
//创建指向www.baidu.com的链接
document.execCommand("createlink",false,"http://www.baidu.com");
//格式化为1级标题
document.execCommand("formatblock",false,"<h1>");
//14.5.3 富文本选区
//使用框架(iframe)的getSelection()方法
//14.5.4 表单与富文本
EventUtil.addHandler(form,"submit",function(event){
event=EventUtil.getEvent(event);
var target=EventUtil.getTarget(event);
target.elements["comments"].value=document.getElementById("richedit").innerHTML;
})