本章内容:
理解表单
文本框验证和交互
使用其他表单控制
14.1 表单的基础知识
在JavaScript中,表单对应的是HTMLFormElement类型,该类型继承了HTMLElement,因而与其他html元素具有相同的默认属性,另外,它有自己独有的属性和方法。
acceptCharset, action , elements, enctype , length , method , name , reset() , submit() , target
取得 form 元素的方式
通过 id 访问
var form = document.getElementById("form1");
通过 document.forms 可以取得页面中所有的表单。在这个集合中,可以通过数值索引或 name值来取得特定的表单
var firstform = document.forms[0];//取得页面中第一个表单
var secondform = document.forms["form2"];//取得页面中名称为 form2 的表单
14.1.1 提交表单的方式
页面中定义提交按钮,按enter 键提交,或者点击按钮提交,或者直接调用表单的 submit() 方法
<!-- 通用提交按钮 -->
<input type="submit" value = "Submit">
<!-- 自定义提交按钮 -->
<button type = "submit">Submit</button>
<!-- 图像按钮 -->
<input type="image" src = "graphic.gif">
以这种方式提交表单,浏览器会在请求发送给服务器之前触发 submit 事件。
var firstform = document.forms[0];//取得页面中第一个表单
firstform.submit();//提交表单
阻止表单提交:
var firstform = document.forms[0];//取得页面中第一个表单
firstform.onsubmit = function(e){
console.log(e);
e.preventDefault();//阻止表单提交
}
如何避免重复提交表单的两种解决办法:
在第一次提交表单后禁用提交按钮;
利用onsubmit 事件处理程序取消后续表单的提交操作;
14.1.2、重置表单
<!-- 通用重置按钮 -->
<input type="reset" value = "resetForm">
<!-- 自定义重置按钮 -->
<button type = "reset">resetForm</button>
重置表单时,所有表单字段都会恢复到页面刚加载完毕时的初始值。
14.1.3、表单字段
每个表单都有elements 属性,该属性是表单中所有表单元素(字段)的集合。
var firstform = document.forms[0];//取得页面中第一个表单
// 取得表单中的第一个字段
var filed1 = firstform.elements[0];
// 取得名为textbox1 的字段
var field2 = firstform.elements["textbox1"];
// 取得表单中包含的字段的数量
var fieldCount = firstform.elements.length;
如果多个表单控件都在使用一个name (如单选按钮),
在访问 elements["color"] 时就会返回以该name命名的一个nodeList .
在访问 form.elements[0] 时,访问到的是第一个表单字段,与包含在 form.elements["color"] 中的第一个元素相等
<body>
<form action="">
<input type="radio" name = "color" value = "red">
<input type="radio" name = "color" value = "yellow">
<input type="radio" name = "color" value = "orange">
</form>
<script>
var form = document.forms[0];
var filed = form.elements["color"];
var field2 = form.elements[0];
console.log(filed[0] == field2);//true
</script>
共有的表单字段
disabled , name , readOnly , tabIndex, type , value
可以 通过js 动态修改其他任何属性
filed.value = "xixi";
console.log(filed.form === form);
filed.focus();
filed.disabled = true;
最好通过submit 事件来禁用提交按钮,这种方式适合表单中包含提交按钮的情况
除了filedset 之外,所有表单字段都有type属性,
input元素 type值等于html特性的type 值,其他元素如下
共有的表单字段方法
focus() 和 blur()
对 type 为 hidden 的表单使用 focus( ),会导致代码报错
使用 css 的 display 和 visibility 属性隐藏了该字段,同样也会导致错误
autofocus 属性
<input type="text" autofocus>
在默认情况下,只有表单字段可以获得焦点。对于其他元素而言,如果先将其tabIndex属性设置为 -1,然后再调用 focus() 方法,也可以让这些元素获得焦点。只有opear不支持这种技术
早起web开发中,表单字段没有 readonly 属性,因此使用 blur() 方法来创建只读字段。现在使用blur() 的场合不多了
共有的表单字段事件
blur() 、change() 、focus()
change 对于 input 和 textarea 元素,在他们失去焦点且 value 值改变时触发,对于select 元素,在其选项改变时触发。
14.2 、文本框脚本
单行文本
<input type="text" size = "25" maxlength = "50" value = "initial value">
size 指定文本框中能够显示的字符数
value 设置文本框的初始值
maxlength 指定文本框可以接受的最大字符数
多行文本
<textarea name="" id="" cols="30" rows="10">initial value</textarea>
rows 指定文本框的字符行数
cols 指定文本框的字符列数
不能再 html 中给 textarea 指定最大字符数
input 和 textarea 都是通过 value 属性读取和设置文本框的值
var textbox = document.forms[0].elements["textbox"];
console.log(textbox.value);
textbox.value = "some new value";
建议像上面这样使用 value 属性读取或者设置文本框的值,不建议使用标准的 DOM 方法
换句话说,不要使用 setAttribute() 设置input 元素的value 特性,也不要去修改 textarea 元素的第一个子节点。原因是 对 value 属性所作的修改,不一定反应在 DOM 中
14.2.1、选择文本
1、选择(select) 事件
select() 用于选择文本框中的所有文本
与select() 方法对应的是一个select事件
2、取得选中的文本
selectionStart selectionEnd
3、选择部分文本
setSelectionRange() 接收两个参数,类似于substring()方法的两个参数
14.2.2、过滤输入
1、屏蔽字符
eg: 屏蔽非数值字符
2、操作剪贴板
beforecopy , copy , beforecut , cut ,beforepaste(粘贴前) , paste(粘贴时)
clipboardData 对象:
getData() ,setData() , clearData()
14.2.3、自动切换焦点
14.2.4、HTML5 约束验证API
1、必填字段 required
2、其他输入类型
email ,url
3、数值范围
number , range , datetime , datetime-local ,date ,month ,week, time
eg: 只能输入 0 到100 的值,而且这个值必须是 5 的倍数
4、输入模式
pattern 属性
eg: 只允许输入数值
也可以通过js 访问 pattern 属性
5、检测有效性
checkValidity()
可以检查某个表单(字段)是否有效
也可以检查整个表单是否有效
validity 属性 会告诉你为什么字段有效或无效,这个对象中包含一下属性,每个属性返回一个布尔值。
customError ,patternMismatch , rangeOverflow, rangeUnderflow, stepMismatch , tooLong , typeMismatch , valid , valueMissing
6、禁用验证
novalidate 属性 可以在html 中设置 novalidate 属性告诉表单不进行验证
<form action="" method = "POST" novalidate></form>
也可以在js 中取得或者设置这个值,如果这个属性存在,值为 true ,否则为 false。
14.3、选择框脚本
由 selec option 构成
属性和方法:
add(newOption,relOption)
multiple
options 控件中所有 option 元素的集合
remove(index)
selectedIndex 基于0 的选中项的索引,如果没有选中项,则值为 -1, 对于支持多选的控件,只保存选中项第一项的索引。
size 选择框中可见的行数
type select-one / select-multiple
value
在DOM 中,每个 option 元素都有一个 HTMLOptionElement 对象表示。它有以下属性:
index , label , selected , text , value
<body>
<select name="myselect" id="myselect">
<option value="嘻嘻">1</option>
<option value="">2</option>
</select>
<button type = "button" id = "mybtn">click me </button>
<script type="text/javascript">
var myselect = document.getElementById("myselect");
var mybtn = document.getElementById("mybtn");
mybtn.onclick = function(){
console.log(myselect.options[0].text);//1
console.log(myselect.options[0].value);//嘻嘻
}
</script>
</body>
select 的change 事件只要选中了选项就会触发
14.3.1、选择选项
对于只允许选择一项的选择框,访问选中项的最简单的方式
<body>
<select name="myselect" id="myselect">
<option value="嘻嘻">1</option>
<option value="">2</option>
</select>
<button type = "button" id = "mybtn">click me </button>
<script type="text/javascript">
var myselect = document.getElementById("myselect");
var mybtn = document.getElementById("mybtn");
mybtn.onclick = function(){
console.log(myselect.options[myselect.selectedIndex]);//<option value="嘻嘻">1</option>
}
</script>
</body>
另外一种选择选项的方式,是取得对某一项的引用,然后将其selected 属性设置为 true
myselect.options[0].selected = true;
选择多选框的所有选中项
function getSelectedOptions(selectbox){
var result = [];
var option = null;
for(var i = 0;i<selectbox.options.length;i++){
option = selectbox.options[i];
if(option.selected == true){
result.push(option) ;
}
}
return result;
}
14.3.2、 添加选项【js 动态创建选项】
第一种方式:DOM 方法
var newOption = document.createElement("option");
newOption.appendChild(document.createTextNode("option text"));
newOption.setAttribute("value","option value");
myselect.appendChild(newOption)
第二种方式:使用 Option构造函数,接收两个参数(文本和值)【在IE8及之前的版本中使用有问题】
var newOption = new Option("option text","option value");
myselect.appendChild(newOption)
第三种方式:使用选择器的 add() 方法
var newOption = new Option("option text","option value");
myselect.add(newOption,undefined);
// add方法接收两个参数:要添加的新选项和将位于新选项之后的选项
// 如果想在列表的最后添加一个选项,应该将第二个参数设置为 null
如果想将新选项添加到其他位置(不是最后一个),就应该使用标准的 DOM 技术和 insertBefore() 方法。
var newOption = new Option("option text","option value");
var nextOption = myselect.options[1];
console.log(nextOption)
myselect.add(newOption,nextOption);
// add方法接收两个参数:要添加的新选项和将位于新选项之后的选项
// 如果想在列表的最后添加一个选项,应该将第二个参数设置为 null
14.3.3、移除选项
第一种方式: 使用 DOM 的removeChild() 方式,传入要移除的选项
myselect.removeChild(myselect.options[0])
第二种方式:使用选择框的 remove() 方法,传入移除选项的索引
myselect.remove(0);
第三种方式:将相应的选项设置为 null
myselect.options[0] = null;
要清除选择框中所有的项,需要迭代所有选项,并逐个移除他们
function clearSelectBox(selectbox){
for(var i = 0;i<selectbox.options.length;i++){
selectbox.remove(0)
}
}
//每次只移除第一个选项,重复移除第一个选项就可以移除所有选项
14.3.4、移动和重排选项
appendChild() insertBefore() 结合
14.4、表单序列化
注意:【序列化一定要设置name属性,否则序列化结果不包含该字段】
利用 type ,name ,value 属性进行序列化表单
function serialize(form){
var parts = [],
field = null,
i,
len,
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.attribute["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(field.value));
}
}
}
return parts.join("&");
}
let form = document.forms[0];
console.log(serialize(form));
可以使用jquery 的serialize()
console.log($("#myform").serialize())
14.5、富文本编辑
这一技术的本质就是,就是在页面中嵌入一个包含空 HTML 页面的 iframe 。
通过设置 designMode 属性,这个空白的 HTML 页面可以被编辑,编辑对象就是该页面 body 种的html代码。
designMode 属性有两个可能的值:
off (默认值) , on 文档可编辑
<body>
<iframe src="./drag.html" frameborder="0" name = "frame1"></iframe>
<script type="text/javascript"src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
<script type="text/javascript">
window.onload = function(){
frames["frame1"].document.designMode = "on";
}
</script>
</body>
14.5.1、使用 contenteditable 属性
可以把该属性应用给页面中的任何元素,然后用户立即就可以编辑该元素。
也可以通过js 打开或者关闭编辑模式
box.contentEditable = false;
contentEditable 属性有三个值:true,false,inherit :从父元素继承【这个方法试了半天没啥效果】
document.execCommand("bold",false,"solid")
document.execCommand("backcolor",false,"red")
document.execCommand("createlink",false,"http://www.baidu.com")
document.execCommand("2D-Position","false","true")
queryCommandEnabled() 用来检测是否可以针对当前选择的文本,或者当前插入字符所在位置执行某个命令。
console.log(document.queryCommandEnabled("bold"));//false
queryCommandState() 用于确定是否已经将指定命令应用到了选择的文本。
queryCommandValue() 用于取得执行命令时传入的第三个参数
14.5.3、富文本选区
getSelection() 可以确定实际选择的文本,这个方法是window和 document对象的属性,调用它会返回一个表示当前文本的 Selection 对象,每个对象都有下列属性
anchorNode , anchorOffset , focusNode , focusOffset, isCollapsed ,
rangeCount
该对象的提供了下列方法:
该部分暂时感觉用不到,没做笔记-------------------------------
14.5.4、表单与富文本
富文本编辑器并不属于表单,因此富文本里面的 html 不会被自动提交给服务器,需要我们手工来提取并提交 html。为此,通常可以添加一个隐藏的表单字段,让它的值等于从 iframe 中提取出的 html。
<body>
<input type="hidden" id = "hiddeninput">
<button id = "submitBtn">click</button>
<iframe src="./drag.html" name = "richedit" frameborder="0" contenteditable></iframe>
<script>
var box = document.getElementById("richedit");
var submitBtn = document.getElementById("submitBtn");
var hiddeninput = document.getElementById("hiddeninput");
submitBtn.onclick = function(){
console.log(frames["richedit"].document.body.innerHTML);
hiddeninput.value = frames["richedit"].document.body.innerHTML;
}
</script>
</body>
14.6、小结:
哈哈看完了终于看完了,有一些工作当中不常用的地方,原谅自己没有细看,等到用的时候再认真研究吧