表单脚本
(一)表单的基础知识
1.提交表单
使用<input>或<button>将其type特性设置为submit后便可定义提交按钮,图片按钮通过将<input>的type特性值设置为"image"来定义。
使用preventDefault()方法阻止表单提交。一般在表单数据无效而不能发送给服务器时可以这么做。
//取得事件对象 event = EventUtil.getEvent(event); //阻止默认事件 EventUtil.preventDefault(event);
以编程方式也可以提交表单,不会触发submit事件,因此提交前要验证表单数据。
重复提交表单:在第一次提交表单后就禁用提交按钮,或者利用onsubmit事件处理程序取消后续的表单提交操作。
2.重置表单
用户点击重置按钮时,会触发reset事件,我们可以在必要时取消重置操作。调用reset()方法回想单击重置按钮一样触发reset事件。
3.表单字段
每个表单都有elements属性,该属性是表单中所有表单元素的集合,可以按照位置和name特性来访问它们。
如果多个表单控件使用一个name,会返回该name的第一个NodeList。
①共有的表单字段属性
除了<fieldset>所有表单字段都有共同的一组属性。
能动态修改表单字段,意味着我们能在任何时候以任何方式动态操作表单。
//避免多次提及表单 EventUtil.addHandler(form, "submit", function(event){ event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); //取得提交按钮 var btn = target.elements["submit-btn"]; //禁用它 btn.disabled = true;
不能用onclick事件处理程序实现因为有得浏览器会在触发表单的submit事件之前先触发click事件。
②共有的表单字段方法
每个表单字段都有两个方法:focus()和blur()。
focus方法用于将浏览器焦点设置到表单字段,使其可以响应键盘事件。
HTML5为表单字段新增了autofocus属性,把焦点移动到响应的字段。在支持的浏览器值为true。
<input type="text" autofocus>
Firefox4+、Safari5+、Chrome和Opera。
blur()是从元素移走焦点,不会把焦点转移到某个特定的元素上。
③公有的表单字段事件
除了支持鼠标、键盘、更改和HTML事件外,所有表单字段都支持者3个事件。
blur:子弹失去焦点时触发。
change:对<input>和<textarea>元素,在它们失去焦点且value值改变;对<select>元素,在其选项改变时触发。
focus:当前字段获得焦点。
可以使用focus事件修改文本框的背景颜色,以便更清楚表明字段获得焦点,可以利用blur事件恢复背景颜色,利用change事件在用户输入非数值字符时再次修改背景颜色。
(二)文本框脚本
文本框:一种是使用<input>元素的单行文本框,另一种是使用<textarea>的多行文本框。
文本框要将<input>元素的type特性设置为"text",size特性指定文本框能显示的字符数,value设置初始值,maxlength指定可接受最大字符数。
多行文本框用rows好cols分别指定行数和列数,<textarea>的初始值要放在<textarea>和</textarea>之间,且不能在HTML中给<textarea>指定最大字符数。
它们都会将用户输入的内容保存到value属性。
1.选择文本
select()方法用于选择文本框中所有文本,特别是文本框包含默认值时用户不用删除文本。
①选择事件
在IE9+、Opera、Firefox、Chrome和Safari中,只有用户选择了文本(而且释放鼠标),才会触发select事件在IE8及更早版本,只要用户选择一个字母(不必释放鼠标)就会触发。在调用select方法时也会触发select事件。
②取得选择的文本
添加属性selectionStart和selectionEnd可以获取选择的文本。这两个属性保存的是基于0的数值,表示所选择文本的范围。
textbox.value.substring(textbox.selectionStart, textbox.selectionEnd)
因为subString()方法基于字符串的偏移量操作,所以将selectionStart和selectionEnd直接传给它。
IE8及之前版本不支持这两个属性,它们有document.selection对象,保存着用户在整个文档选择的文本信息。与select事件一起用,并要创建一个范围再将文本提取出来。
document.selection.createRange().text;
③选择部分文本
setSelectionRange()方法,接收两个参数:要选择的第一个字符索引和最后一个字符之后的字符的索引。
要看到选择的文本,必须在调用setSelectionRange()之前或之后立即将焦点设置到文本框。
IE9、Firefox、Safari、Chrome和Opera支持。
IE8及之前版本支持使用范围选择部分文本。先使用createTextRange()方法创建一个范围,将其放在恰当的位置。再使用collapse()将范围折叠到文本框的开始位置,调用moveStart()和moveEnd()将范围移动到位。最后使用范围的select()范围选择文本。
2.过滤输入
①屏蔽字符
通过阻止事件的默认行为来屏蔽所有按键
EventUtil.addHandler(textbox, "keypress", function(event){ event = EventUtil.getEvent(event); EventUtil.preventDefault(event); });
屏蔽特定字符:
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){ //fromCharCode将字符编码转换为字符串 !event.ctrlKey:没有按下Ctrl键 EventUtil.preventDefault(event); } });
②操作剪贴板
beforecopy copy beforecut cut beforepaste paste
要访问剪贴板的数据可以使用clipbordData对象:在IE这是window对象的属性,在Firefox 4+、Safari、Chrome里是相应event的属性。在Firefox、Safari和Chrome只有在处理剪贴板事件期间clipboardData对象才有效,在IE里可以随时访问clipboardData对象。
clipboardData对象有3个方法:getData()、setData()、clearData()。
getData()接收一个参数,即要取得的数据格式。IE有"text"和"URL",Firefox、Safari和Chrome里是MIME类型,但可以用"text"代表"text/plain"。
setData()第一个参数也是数据类型,Safari和Chrome只支持MIME类型,第二个参数是要放到剪贴板的文本。Safari和Chrome的setData()方法不能识别"text"类型,在成功放入脚本后返回true。
if (!/^\d*$/.test(text)){ EventUtil.preventDefault(event); }
并非所有浏览器支持访问剪贴板,更简单的做法是屏蔽一或多个剪贴板操作,在Opera需要阻止会触发这些事件的按键,还要阻止文本框显示上下文菜单。
3.自动切换焦点
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; } } } }
比较用户输入的值与文本框的maxlength特性,确定是否达到最大长度。如果相等则需要查找表单字段集合,直到找到下一个文本框。找到后将焦点切换到文本框。然后把这个函数指定为每个文本框的onkeyup事件处理程序。
4.HTML5约束验证API
HTML5新增了一些功能,即使javascript被禁用或没能加载也能确保基本的验证。Firefox 4+、Safari 5+、Chrome和Opera 10+支持。
①必填字段
第一种情况是在表单字段指定required属性
<input type="text" name="username" required>
适用于<input> <textarea> 和 <select>字段。
②其他输入类型
email和url属性
<input type = "email" name = "email"> <input type = "url" name = "homepage">
"email"属性要求输入的文本要符合电子邮件地址的模式,"url"要求输入的文本符合URL模式。但匹配模式存在问题。如果不给<input>元素设置required属性,空文本框也会通过验证。
③数据范围
"number" "range" "datetime" "tatetime-local" "date" "month" "week" "time",但浏览器支持不哈。
对所有这些数值类型的输入元素,可以指定min属性、max属性,和step属性。
stepUp()和stepDown(),接收一个可选参数:要在当前值基础加上或减去的数。
④输入模式
HTML5为文本增加了pattern属性,值是一个正则表达式,用于匹配文本框中的值。
//只允许输入数字 <input type="text" pattern="\d+" name="count">
指定pattern不能阻止用户输入无效的文本。
⑤检测有效性
checkValidity()方法可以检测表单中某个字段是否有效,如果字段有效返回true。字段值是否有效是根据前面的约束。要检测整个表单是否有效,可以在表单自身调用这个方法。
validity属性包含一系列属性,每个属性返回一个布尔值,说明该值是否符合约束。
⑥禁用验证
设置novalidate属性,表单不进行验证。
如果一个表单有多个提交按钮,为了指定点击某个提交按钮不验证表单,可以在相应的按钮上添加formnovalidate属性。
(三)选择框脚本
通过<select>和<option>创建。
HTMLSelectElement类型:
add(newOption,relOption):向插件插入新<option>元素,位置在relOption之前。
multiple:布尔值,是否允许多项选择。
options:所有<option>元素的HTMLCollection。
remove(index):移除指定位置的选项。
selectedIndex:基于0的选中项的索引。没有选中项值为-1。多项选择值保持选中项的第一项。
size:选择框中可见的行数。
选项框的value属性:
没有选中:空字符串。
有一个选中,而且value特性在HTML指定:等于value特性,即使value为空字符串。
有一个选中,value特性在HTML未指定:等于该项的文本。
有多个选中项:根据前两条规则取得第一个选中项的值。
HTMLOptionElement类型
index:当前选中在option的索引。
label:当前选项的标签。
selected:当前选项是否被选中、
text:选项的文本。
value:选项的值。
var selectbox = document.forms[0].elements["location"]; //推荐 var text = selectbox.option[0].text; //选项的文本 var text = selectbox.option[0].value; //选项的值
在未指定value特性时,IE会返回空字符串,IE9+、Safari、Firefox、Chrome和Opera返回与text特性相同的值。
1.选择选项
selectedIndex属性 访问选中项
var selectedOption = selectbox.option[selectbox.selectedIndex];
对选择多项的选择框,selectedIndex属性会取消以前的所有选项并选择指定的那一项。
另一种选择选项的方式——取得对某一项的引用,将其selected属性设置为true。在允许多项选择框设置不会取消对其他选项的选择。但在单选选择框中会取消。将selected设为false对单选选择框没有影响。
2.添加选项
方法一:DOM
创建<option>元素,为它添加文本节点,并设置器value特性,最后将它添加到选择框。
var newOption = document.createElement("option"); newOption.appendChild(document.createTextNode(textTextbox.value)); newOption.setAttribute("value", valueTextbox.value); selectbox.appendChild(newOption);
方法二:option构造函数
接收两个参数text、value(可选)
var newOption = new Option("Option text", "Option value"); selectbox.appendChild(newOption); //在IE8及之前版本有bug
方法三:选择框的add()方法
接收两个参数:要添加的新选项和将位于新选项之后的选项,第二个参数传入undefined可以在所有浏览器将新选项插入到列表最后。
var newOption = new Option("Option text", "Option value"); selectbox.add(newOption, undefined);
3.移除选项
方法一:DOM的removeChild()方法
selectbox.removeChild(selectbox.option[0]);
方法二:选择框的remove()方法,接收一个参数:要移除选项的索引
selectbox.remove(0);
方法三:将相应选项设为null
selectbox.option[0] = null;
移除一个选项后后续选项会自动向上移一个位置。
4.移动和重排选项
将一个选项框的选项移动到另一个选项框——使用DOM的appendChild方法
selectbox2.appendChild(selectbox1.options[parseInt(textbox.value, 10)]);
将某一项移动到特定位置,最合适的DOM方法是insertBefore()
//在选项框中向前移动一个选项的位置 selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index-1]); //向后是Index+2
(四)表单序列化
利用type属性,连同name和value属性一起实现表单序列化。
(五)富文本编辑
本质是在页面嵌入一个包含空HTML页面的iframe。通过设置designMode属性,这个空白的HTML页面可以被编辑,编辑对象是该页面<body>元素的HTML代码。designMode属性值为on时,整个文档可编辑。
只有在页面加载完才能设置designMode属性,因此要用到onload事件。
1.使用contenteditable属性
可以把ontenteditable属性应用给页面上任何元素,用户便可以编辑该元素。有true、false、inherit三个可能的值。
IE、Firefox、Chrome、Safari和Opera
2.操作富文本
与富文本编辑器交互的主要方式是使用document.execCommand()。这个方法对文档执行预定义的命令,可以传递三个参数:要执行的命令名称,表示浏览器是否应该为当前命令提供用户界面的一个布尔值和执行命令必须的一个值(不需要则传递null)。为保持浏览器兼容性第二个参数设置为false。
与剪贴板相关的命令在不同浏览器差异很大。
这些命令产生的HTML在不同浏览器有很大不同。
queryCommandEnabled():检测是否可以针对当前选中的文本或者当前插入字符所在位置执行某个命令,接收一个参数即要检测的命令,如果允许执行这个命令则返回true。
queryCommandState():确定是否已将制定命令应用到了选中的文本。
queryCommandValue():取得执行命令时传入的值。
3.富文本选区
使用frame的getSelection()方法可以确定实际选择的文本。调用它会返回一个表示当前选择文本的Selection对象。
使用默认选区中的DOM范围,通过surroundContents()方法将选区添加到带有黄色背景的<span>元素。
var selection = frames["richedit"].getSelection(); //取得代表选区的范围 var range = selection.getRangeAt(0); //突出显示选择的文本 var span = frames["richedit"].document.createElement("span"); span.style.backgroundColor = "yellow"; range.surroundContents(span);
IE9、Firefox、Safari、Chrome、Opera 8都实现了它,IE8及之前版本可以通过selection对象操作选择的文本。
4.表单与富文本
富文本编辑器的HTML不会被自动提交给服务器,需要我们手工来提取并提交HTML。通常可以添加一个隐藏的表单字段,让它的值等于从iframe中提取出的HTML。
EventUtil.addHandler(document.forms[0], "submit", function(){ event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); target.elements["comments"].value = frames["richedit"].document.body.innerHTML; });
通过文档主体的innerHTML属性取得iframe的HTML,将其插入到"comments"的表单字段。如果想在代码中通过submit()手工提交表单必须这样做。