表单基础
Web表单在HTML中以元素表示,在JavaScript中则以HTMLFormElement类型表示。
HTMLFormElement类型继承自HTMLElement类型,因此拥有与其它HTML元素一样的默认属性,不过,HTMLFormElement也有自己的属性和方法。
acceptCharset:服务器可以接收的字符集,等价于HTML中的accept-charset属性;
action:请求中的URL,等价于HTML中的action属性;
elements:表单中所有控件的HTMLCollection;
enctype:请求的编码类型,等价于HTML中的enctype属性;
length:表单中控件的数量;
method:HTTP请求的方法类型,通常是get或post,等价于HTML中的method方法;
name:表单的名字,等价于HTML中的name属性;
target:用于发送请求和接收相应地窗口的名字,等价于HTML中的target属性;
reset():把表单字段重置为各自的默认值,一般情况下不建议使用;
submit():提交表单;
可以通过document.getElementsByTagname['from'][0]获得元素引用.
也可以通过document.froms[0]获得引用.
1.1 提交表单submit
提交方式
<input type='submit'/>
<button type='submit'>提交</button>
<input type='imge' src='' />
如果表单中有上述任何一个按钮,且焦点在表单中某个控件上,则按回车键就可以提交表单。阻止这个事件的默认行为可以取消提交表单。
let form = document.getElementById("myForm");
form.addEventListener("submit",(event) => {
//阻止表单提交
event.preventDefault();
});
调用preventDefault()就可以阻止表单提交。
也可以通过submit()方法提交表单。
let form = document.getElementById("myForm");
form.submit();
通过submit()方法提交表单时,submit事件不会触发.因此在调用这个方法之前要先做数据处理.
事件提交的最大问题是如何避免二次提交。
如果表单中有上述任何一个按钮,且焦点在表单中某个控件上,则按回车键就可以提交表单。阻止这个事件的默认行为可以取消提交表单。
如果提交表单之后没有什么反应,用户可能会进行第二次点击,甚至更多次,结果肯定是很烦人的,比如服务器要处理重复的请求,甚至可能造成损失(比如用户在购物,则可能会下多个单,引起不必要的客户投诉。)。解决这个问题的方式,① 在表单提交后禁用提交按钮。② 通过onsubmit()事件处理程序取消之后的表单提交。
1.2 重置表单reset
重置方式
<input type='reset' />
<button type='reset' >重置</button>
与submit()方法不同,使用reset()方法会触发reset事件.
1.3 表单字段
访问表单元素可以通过document.forms[0].elements[0]
1.3.1 表单的公共属性
disabled:布尔值,表示表单字段是否禁用;
form:指针,指向表单字段所属的表单,这个属性是只读的;
name:字符串,这个字段的名字;
readOnly:只读
tabIndex:数值,表示这个字段在按Tab键时的切换顺序;
type:字符串,表示字段类型,比如checkbox、radio等;
value:要提交给服务器的字段值
避免多出提交的代码:
let form = document.getElementById("myForm");
for.addEventListener("submit",(event) => {
let target = event.target;
let btn = target.elements["submit"];
btn.disabled = true;
});
1.3.2 表单字段的公共方法
每个表单字段都有两个公共方法:focus()和blur()。
focus()方法把浏览器焦点设置到表单字段,这意味着该字段会变成活动字段并可以响应键盘事件。
注意:如果表单的第一个字段是type为'hidden'的input 元素,或者该字段被css属性display或者visibility隐藏了,以上代码会出错.
blur()是focus()的反向操作,从元素上移除焦点。
可以通过blur()实现readonly属性.focus()实现html5新增的autofocus属性
1.3.3 表单字段的公共事件
blur:在字段失去焦点时触发;
change:在<input>和<textarea>元素的value发生变化且失去焦点时触发,或者在<select>元素中选中项发生变化时触发;
focus:在字段获得焦点时触发;
文本框编程
<!--input size属性为最多显示的字符数,maxlength属性为最多输入的字符数 -->
<input type="text" size='10' mixlength='20' />
<!-- cols每行的字符数,rows 每列的字符数-->
<textarea cols='20' rows='10'>文本</textarea>
对于textarea来说,cols,rows对其限制不大,一般浏览器不会完全根据这两个属性来分配文本宽度和高度.
读取文本框内容可以使用textbox.value来读取
2.1 选择文本 select
select()方法可以选取文本框中所有文本.
2.1.1 select事件
select事件会在用户选择完文本后立即触发.
select()方法也会触发select事件.
2.1.2 取得选中文本
html5为文本框增添了2个属性,selectionStart和selectionEnd
这两个属性包含基于0的数值,分别代表了文本选取的起点和终点.
老版本ie中包含整个文档中文本选择信息的document.selection对象.
得到选中的文本需要先创建一个范围createRange(),然后再从中提取文本.(不建议使用)
2.1.3 部分选中文本
html5 实现了对部分文本进行选中 即setSelectionRange(),接收两个参数要选择的第一个字符的索引和停止选择的字符索引.
老版本ie继续部分文本选中操作,先调用collapse()方法把范围折叠到文本框的开始.再使用createTextRange()方法创建一个范围,并使用moveStart()和moveEnd()范围方法把范围放到正确的位置.(不建议使用)
let tt=document.forms[0].elements['tt']
tt.value='1234569876543'
tt.focus()
tt.setSelectionRange(0,4)
var range=tt.createTextRange();
range.collapse(true);
range.moveStart('character',0);
range.moveEnd('character',3);
range.select();
2.2 输入过滤
2.2.1 屏蔽字符
let text1=form.elements['text1']
text1.addEventListener('keypress',function(e) {
if (!/\d/.test(String.fromCharCode(e.charCode))&&e.charCode>9&&!e.ctrlKey) {
e.preventDefault()
}})
2.2.2 处理剪切板
剪切板事件:
- beforecopy
- beforecut
- beforepaste
- copy
- cut
- paste
beforecopy,beforecut,beforepaste事件可以向剪切板发送或从中检索数据前修改数据.
//在复制前修改复制值
text1.addEventListener('beforecopy',(event)=>{
let target=event.target;
target.focus()
target.setSelectionRange(0, 2);
})
剪切板上的数据可以通过event.clipboardData对象获取.
clipboardData有3个方法,getData(),setData(),clearData()
getData()接收一个参数,参数值为text或者URL
setData()方法接收两个参数,第一个参数为text/plain,第二个参数为修改值.
//复制时,修改复制到剪切板的值
text.addEventListener('copy',(event)=>{
event.preventDefault();
let a= event.clipboardData
a.setData('text/plain','sdad');
})
2.2.3 自动切换
JavaScript可以通过很多方式增强表单字段的易用性,最常见的是在当前字段完成时自动切换到下一个字段,比如对于已知长度的输入框,比如手机号码,在中国手机号码都是11位,可以在手机号码输入框到达11个字符时,自动把焦点移到下一个输入框。
2.2.4约束验证API
2.2.4.1 必填字段
给表单字段添加required属性,将其定义为必填项.
2.2.4.2 更多输入类型
html5新增了一些type值,number,email,url等
2.2.4.3 数值范围
html5新增了一些数值相关的属性,例如:min,max,step等
2.2.4.4 输入模式
html5新增了pattern属性,这个属性可以指定一个正则表达式.
2.2.4.5 检测有效性
checkValidity()方法可以检测表单中任意给定字段是否有效.这个方法在所有表单元素上都可以使用.
可以检验一个表单字段,也可以检测一个表单是否有效,检测表单时,如果一个字段有问题,就会返回false.
validity属性 会告诉我们字段为什么有效或无效,这个属性是一个对象,包含一系列返回布尔值的属性.
- valid:如果其他属性值都为false,则返回true.
- valueMissing:当表单元素设置required属性后,如果表单的值为空,则无法通过表单验证,返回true;否则,返回false
- typeMismatch:当用户输入的内容与表单类型不匹配时,返回true;否则,返回false
- patternMismatch:当用户输入的内容与表单元素patterm特性的正则不匹配时,返回true;否则,返回false
- tooLong:当用户输入的内容超过了表单元素maxLength特性限定的字符长度时,返回true;否则,返回false
- rangeUnderflow:当用户输入的值小于min特性的值时,返回true;否则,返回false
- rangeOverflow:当用户输入的值大于max特性的值时,返回true; 否则,返回false
- stepMismatch:当用户输入的值不符合step特性所推算的规则时,返回true; 否则,返回false
- customError:使用自定义的验证错误提示信息时,当存在自定义错误信息时,返回true: 否则,返回false
2.2.4.6 禁用验证
novalidate 属性可以禁用对表单进行任何验证.
3选择器编程
选择器是使用<select>和<option>元素创建的.
常见属性和方法:
add:在relOption之前向控件中添加新的;
multiple:布尔值,表示十分允许多选;
options:控件中所有元素;
remove(index):移除给定位置的选项;
selectedIndex:选中项基于0的索引值,没有没有选中项则为-1,对于允许多选的列表,始终是第一个选项的索引;
size:选择框中可见的行数;
如果没有选中项,则选择框的值是空字符串。
如果有一个选中项,且其 value 属性有值,则选择框的值就是选中项 value 属性的值。即使 value 属性的值是空字符串也是如此。
如果有一个选中项,且其 value 属性没有指定值,则选择框的值是该项的文本内容。
如果有多个选中项,则选择框的值根据前两条规则取得第一个选中项的值。
<select name="location" id="selLocation">
// 若选中该项,值为Sunnyvale, CA
<option value="Sunnyvale, CA">Sunnyvale</option>
// 若选中该项,值为""
<option value="">China</option>
// 若选中该项,值为"Australia"
<option>Australia</option>
</select>
option的属性:
- index:选项在 options 集合中的索引。
- label:选项的标签,等价于 HTML 的 label 属性。
- selected:布尔值,表示是否选中了当前选项。把这个属性设置为 true 会选中当前选项。
- text:选项的文本。
- value:选项的值(等价于 HTML 的 value 属性.
3.1添加选项
let a= new Option('option text','option value')
select.add(newOption,undefined)
4.表单序列化
5. 富文本编辑
5.1 designMode
<!--为iframe源 1.html>
<!DOCTYPE html>
<html>
<head>
<title>Blank Page for Rich Text Editing</title>
</head>
<body>
</body>
</html>
<!-- 2.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<iframe src="./1.html" name="richedit" style="height: 100px; width: 100px"></iframe>
</body>
<script>
window.addEventListener("load", () => {
frames["richedit"].document.designMode = "on";
});
</script>
</html>
5.2 contenteditable
<div class="editable" id="richedit" contenteditable style="height: 300px; width: 300px;border: 1px solid #000;"></div>
5.3 富文本交互
document.execCommand() 可接收三个参数:要执行的命令、浏览器是否为命令提供用户界面的布尔值(为浏览器兼容,应始为false)、执行命令必需的值
5.4富文本选择
anchorNode:选区开始的节点。
anchorOffset:在 anchorNode 中,从开头到选区开始跳过的字符数。
focusNode:选区结束的节点。
focusOffset:focusNode 中包含在选区内的字符数。
isCollapsed:布尔值,表示选区起点和终点是否在同一个地方。
rangeCount:选区中包含的 DOM 范围数量。 Selection 的属性并没有包含很多有用的信息。好在它的以下方法提供了更多信息,并允许操作 选区。
addRange(range):把给定的 DOM 范围添加到选区。
collapse(node, offset):将选区折叠到给定节点中给定的文本偏移处。
collapseToEnd():将选区折叠到终点。
collapseToStart():将选区折叠到起点。
containsNode(node):确定给定节点是否包含在选区中。
deleteFromDocument():从文档中删除选区文本。与执行 execCommand(“delete”, false, null)命令结果相同。
extend(node, offset):通过将 focusNode 和 focusOffset 移动到指定值来扩展选区。
getRangeAt(index):返回选区中指定索引处的 DOM 范围。
removeAllRanges():从选区中移除所有 DOM 范围。这实际上会移除选区,因为选区中至少 要包含一个范围。
removeRange(range):从选区中移除指定的 DOM 范围。
selectAllChildren(node):清除选区并选择给定节点的所有子节点。
toString():返回选区中的文本内容。
let selection = frames["richedit"].getSelection();
// 取得选中的文本
let selectedText = selection.toString();
// 取得表示选区的范围
let range = selection.getRangeAt(0);
// 高亮选中的文本
let span = frames["richedit"].document.createElement("span");
span.style.backgroundColor = "yellow";
range.surroundContents(span);
5.5 通过表单提交富文本
//frames
form.addEventListener("submit", (event) => {
let target = event.target;
target.elements["comments"].value =
frames["richedit"].document.body.innerHTML;
});
// contenteditable
orm.addEventListener("submit", (event) => {
let target = event.target;
target.elements["comments"].value =
document.getElementById("richedit").innerHTML;
});