1、表单元素一、编写表单的步骤: 1、构建表单----------------》2、服务器处理(主要是提供负责接收数据的接口,用来处理数据的存储等信息)------------》3、配置表单 示例: 披萨预定表单: <p><label>姓名:<input></label></p><!--用label标签来做元素的关联--> <p><label>电话:<input type='tel'></label></p> <p><label>邮箱:<input type='email'></label></p> <label><input type='radio' name='size'> 小 </label> <label><input type='radio' name='size'> 中 </label> <label><input type='radio' name='size'> 大 </label> <label><input type='checkbox'> 熏肉 </label> <label><input type='checkbox'> 奶酪 </label> <label><input type='checkbox'> 洋葱 </label> <label><input type='checkbox'> 蘑菇 </label> <p><label>配送时间:<input type='time' min='11:00' max='21:00' step='900'></label></p> <p><button>提交订单</button></p>
配置表单: <form method='post' action='https://pizza./order' enctype='application/x-www-form-urlencoded'> <!--action属性配置接收数据的地址,enctype指定编码方式--> <p><label>姓名:<input name='custname'></label></p> <p><label>电话:<input type='tel' name='custtel'></label></p> <p><label>邮箱:<input type='email' name='custemail'></label></p> <label><input type='radio' name='size' value='small'> 小 </label> <label><input type='radio' name='size' value='medium'> 中 </label> <label><input type='radio' name='size' value='large'> 大 </label> <label><input type='checkbox' name='topping' value='bacon'> 熏肉 </label> <label><input type='checkbox' name='topping' value='cheese'> 奶酪 </label> <label><input type='checkbox' name='topping' value='onion'> 洋葱 </label> <label><input type='checkbox' name='topping' value='mushroom'> 蘑菇 </label> <p><label>配送时间:<input type='time' name='delivery' min='11:00' max='21:00' step='900'></label></p> <p><button>提交订单</button></p>
二、表单元素 1、form标签: name属性:主要用于之后的API:var pizzaForm = document.forms.pizza; autocomplete属性:属性值有on / off ,当值为on时,鼠标焦点到“姓名”的输入框中时,下面会出现之前输入过的值以备候选,候选值也会根据输入情况更改;当值为off时,也出现提示,就与浏览器的设置有关了。 elements:包含:①该表单子孙表单控件(除图片按钮(<input type='image'>))(表单控件有 button、fieldset、input、keygen、object、output、select、textarea) ②归属于该表单的表单控件(除图片按钮),示例看下面的代码:(动态节点集合) <p><label><input name='a'></label></p><!--符合①--> <p><select name='b'><option>1</option></select></p><!--符合①--> <p><label><input name='c'></label></p><!--不符合--> <p><label><input name='d' form='f'></label></p><!--符合②-->
length:elements.length 2、获取form表单中的表单控件:
testForm[0]; //form[index] testForm['a']; //form[name]
*form[name]:---------------------返回id或name为指定名称的表单控件(除图片按钮) ---------------------如果结果为空、则返回id为指定名称的img元素 ---------------------如果有多个同名元素,则返回这些元素的动态节点集合 ---------------------一旦用指定名称取过该元素,则不管该元素的id或者name怎么变化,只要节点还在页面上均可使用原名称获取该元素:
testForm['a'].name = 'b'; testForm['a'];//<input name='b' /> testForm.elements['a'];//null
3、接口:-----reset() 可重置元素:input、keygen、output、select、textarea 触发表单reset事件,阻止该事件的默认行为可取消重置 元素重置时不再触发元素上的change和input事件 示例:有一个文件选择器,已经选择了一个文件,现在我们想要把这个选择的文件删除: <input name='image' type='file' /> fileForm['image'].value = ''; //根据浏览器的安全限制,这样做是无法删除已选中文件的
-----submit() -----checkValidity() 4、label标签 <label for='txtId' form='formId'></label> 主要通过for属性关联到相关的表单控件上①、htmlFor -------------------关联表单控件激活行为,也就是说关联之后,点击label的行为与表单控件的行为保持一致 -------------------可关联元素:button、input(除hidden外)、keygen、meter、output、progress、select、textarea <input id='file' name='image' type='file'><!--0*0尺寸不可见--> <label for='file' class='m-upload'>选择图片</label><!--上传按钮效果,这里最重要的就是将for属性指到input id为file,这里点击label就有与点击input标签选择文件行为相同的操作-->
②control---------------------如果指定了for属性,则为该for属性对应ID的可关联元素 ---------------------如果没有指定for属性,则为第一个子孙可关联元素 <label for='txtId'>文字<input name='desc'></label> <span id='txtId'>only for test content here</span>
在上面代码中:a、指定了for属性 b、for属性对应ID的元素span为非可关联元素 c、label.control——>null ③form ----------------------关联归属表单 ----------------------可关联元素:button,fieldset,input,keygen,label,object,output,select,textarea ----------------------只读属性,不可在程序中修改 label.setAttribute('form','newFormId');
5、input标签①type --------------------控件外观 --------------------数据类型 --------------------默认为text 示例:本地图片预览: <input type='file' accept='image/*' multiple> multiple表示可以多选,accept支持的属性值:audio/*、video/*、image/*、不带“;”的MIME type、以“.”开始的文件后缀名。 file.addEventListener('change', function(event){ var files = Array.prototype.slice.call(event.target.files,0); files.forEach(function(item){ <strong>file2dataurl</strong>(item,function(url){ parent.appendChild(image);
file2dataurl接口没有实现,思考。 6、select标签 <optgroup label='1. DOM基础'> <option value='1.1'>1.1 文档树</option> <option value='1.2'>1.2 节点操作</option> <option value='1.3'>1.3 元素遍历</option> <option value='1.4'>1.4 样式操作</option> <option value='1.5'>1.5 属性操作</option> <option value='1.6'>1.6 表单操作</option> <optgroup label='2. 事件模型'> <option value='2.1'>2.1 事件类型</option> <option value='2.2'>2.2 事件模型</option> <option value='2.3'>2.3 事件应用</option>
①select属性和接口:select:name、value、multiple、options、selectedOptions、selectedIndex、add(element[,before])、remove([index]) optgroup:disabled 、label(对相关性较大的做分组,disabled表示当前分组里的都是不可选的) option:disabled、label、value、text、index、selected、defaultSelected *创建选项: ------document.createElement ------new Option([text[,value[,defaultSelected[,selected]]]]) 这两个方式的效果是一样的。 new Option('1.2 节点操作','1.2'); var option = document.createElement('option'); option.textContent = '1.2 节点操作';
生成了:<option value='1.2'>1.2 节点操作</option> *添加选项:------insertAdjacentElement ------select.add var option = new Option('1.0 概述','1.0'); opt11.insertAdjacentElement(option,'beforeBegin'); select.add(option,opt11);
*删除选项------removeChild ------select.remove opt12.parentNode.removeChild(opt12);
②示例:级联下拉选择器案例描述:两个select选择器,后一个选择器根据前一个选择的所选的内容发生改变: 涉及到的知识点:onchange、remove、add
接下来对章节的数据内容进行定义: {text:'1. DOM基础',value:'1'}, {text:'2. 事件模型',value:'2'} {text:'1.1 文档树',value:'1.1'}, {text:'1.2 节点操作',value:'1.2'}, {text:'1.3 元素遍历',value:'1.3'}, {text:'1.4 样式操作',value:'1.4'}, {text:'1.5 属性操作',value:'1.5'}, {text:'1.6 表单操作',value:'1.6'} {text:'2.1 事件类型',value:'2.1'}, {text:'2.2 事件模型',value:'2.2'}, {text:'2.3 事件应用',value:'2.3'}
提取通用的接口: function fillSelect(select,list){ for(var i=select.length-1; i>0; i --){ list.forEach(function(data){ var option = new Option(data.text,data.value); fillSelect(chapterSelect,chapters); chapterSelect.addEventListener('change', function(event){ var value = event.target.value, list = sections[value] || []; fillSelect(sectionSelect,list);
7、textarea ①属性和接口: name、value、select()(对内容全选之后就会触发这个接口)、selectionStart、selectionEnd、selectionDirection(用来控制shift+方向键的行为,当值为forward时,改变的是selectionEnd,值为backward时,改变的是selectionStart)、setSelectionRange(start,end[,direction])、setRangeText(replacement[,start,end[,mode]]) ②@输入提示: 描述:比如QQ聊天时,对话框中输入@就会出现好友列表,可以选择其中的一个值填充到@后面,之后再输入其他文本。 涉及到的知识点:oninput、selectionStart、setRangeText textarea.addEventListener( var target = event.target, cursor = target.selectionStart; if(target.value.charAt(cursor - 1) === '@'){ doShowAtList(function(name){ var end = cursor+name.length; target.setRangeText(name,cursor,end,'end');
2、表单验证 <form method='post' action='https://pizza./order' enctype='application/x-www-form-urlencoded'> <!--action属性配置接收数据的地址,enctype指定编码方式--> <p><label>姓名:<input name='custname' required></label></p> <p><label>电话:<input type='tel' name='custtel' required></label></p> <p><label>邮箱:<input type='email' name='custemail'></label></p> <label><input type='radio' name='size' value='small' required> 小 </label> <label><input type='radio' name='size' value='medium' required> 中 </label> <label><input type='radio' name='size' value='large' required> 大 </label> <label><input type='checkbox' name='topping' value='bacon'> 熏肉 </label> <label><input type='checkbox' name='topping' value='cheese'> 奶酪 </label> <label><input type='checkbox' name='topping' value='onion'> 洋葱 </label> <label><input type='checkbox' name='topping' value='mushroom'> 蘑菇 </label> <p><label>配送时间:<input type='time' name='delivery' min='11:00' max='21:00' step='900'></label></p> <p><button>提交订单</button></p>
在必须要填写的表单标签中添加“required”属性,当用户没有填写完整时点击提交按钮就会马上返回提示信息。 一、验证: 1、验证元素: ---------可验证元素:button、input、select、textarea
---------以下情况不做验证: ①input && type = {hidden、reset、button} ②button && type = {reset、button} ③input / textarea && readonly ④作为datalist的子孙节点 ⑤disabled 2、验证涉及到的属性或接口: element:willValidate(判断表单提交时元素是否会被验证)、checkValidity()(用来验证元素,通过的话就会返回true,否则会触发validate事件)、validity、validationMessage(显示验证异常信息)、setCustomValidity(message) ①validity:存储了验证过程中可能出现的错误验证信息 ②自定义异常: -------oninvalid事件
-------setCustomValidity接口 a、将必填字段的提示信息自定义设置,默认为“请填写此字段。”,改为“请输入姓名!” <form action='./api' method='post'> <p><label>姓名:<input name='username' required /></label></p> <p><button>submit</button></p>
input.addEventListener('invalid', function(event){ var target = event.target; if(target.validity.valueMissing){ target.setCustomValidity('请输入姓名!');
③禁止验证:描述案例:当一个input的type为number,而作用是输入电话号码,其中电话号码带有“-”,提交时就会显示验证错误信息“请输入一个数字”。(这种情况下设置type可能是为了唤起特定的键盘,这里就是数字键盘) <form action='./api' method='post' novalidate> <label>电话:<input type='number' name='tel' /></label>
3、表单提交一、隐式提交: -------如:聚焦在输入框时按回车提交表单 -------需满足以下任一条件: ①表单有非禁用的提交按钮 ②没有提交按钮时,不超过一个类型为text、search、url、email、password、date、time、number的input元素 1、提交过程: ①根据表单enctype指定的值构建要提交的数据结构 ②使用method指定的方式发送数据到action指定的目标 1.1、构建提交数据(浏览器):从可提交元素中提取数据组装成指定的数据结构的过程。 可提交元素:button、input、keygen、object、select、textarea 1.2、编码方式(enctype) 可指定为以下三种方式之一:①application/x-www-form-urlencoded【默认】 ②multipart/form-data ③text/plain (一般文件上传使用这种方式)
以上三种编码方式分别使用method='post'提交数据: <form action='./api' method='post'>
enctype | Content-Type | 数据格式组织形式 | ① | ① | 使用&分割的键值对 | ② | ② | 用回车换行分割的键值对 | ③ | ③ | 字节流 |
特殊案例: -------name='isindex' && type='text' *编码方式为application/x-www-form-urlencoded *作为表单的第一个提交元素 *提交时只发送value值,不包含name <form action='./api' method='post'> <p><input name='isindex' /></p> <p><input name='a' /></p> <p><button>submit</button></p>
提交111111、22222,则之后看到提交的数据为:111111&a=22222-------name='_charset_' && type='hidden'
*没有设置value值 *提交时value自动用当前提交的字符集填充 <form action='./api' method='post'> <input type='hidden' name='_charset_' /> <p><input name='a' /></p> <p><button>submit</button></p>
提交111111,而_charset_的值就会用当前数据的编码字符集来填充,则提交的数据为:_charset_=UTF-8&a=1111112、submit() 提交
在表单提交中的一个重要接口就是submit(),除了用提交按钮来提交数据之外,我们还可以调用form上的submit()接口来提交表单。 ①onsubmit——不管用什么方式提交表单都会触发onsubmit事件。 ——表单提交事件 ——在这个事件触发的时候我们可以做一些提交之前的数据验证 ——如果这个验证没有通过,可以阻止事件的默认行为来取消表单提交。 form.addEventListener('submit', function(event){ var elements = event.target.elements;
示例:无刷新表单提交常用的可能是ajax,但这里用另外一种方式: 涉及到的知识点:form、target、iframe 使用iframe做中间代理,结合表单的target。 说明:指定一个iframe的name,将form的target指向iframe的name,当form表单的数据提交到服务器上,服务器返回的结果就会到iframe中,然后就只需要将iframe中的结果提交到页面上就可以了。 <iframe name='targetFrame' class='f-hidden'></iframe> <form action='./api' method='post' target='targetFrame'> <p><input name='b' /></p> <p><button>submit</button></p>
4、表单应用当重新输入时,错误信息就会消失。 一、登录接口: ——请求地址:/api/login ——请求参数: *telephone 手机号码 *password 密码,MD5加密 ——返回结果: *code 请求状态,200表示成功 *result 请求结果数据 登录表单: <form action='/api/login' class='m-form' name='loginForm' target='result' autocomplete='off'> <div class='msg' id='message'></div> <label for='telephone'>手机号:</label> <input id='telephone' name='telephone' class='u-txt' type='tel' maxlength='11' required pattern='^0?(13[0-9]|15[012356789]|18[0236789]|14[57])[0-9]{8}$' /><br/> <span class='tip'>11位数字手机号码</span> <label for='password'>密 码:</label> <input id='password' name='password' type='password' class='u-txt' /><br/> <span class='tip'>至少6位,同时包含数字和字母</span> <div><button name='loginBtn'>登 录</button></div>
var form = document.forms.loginForm;//登录表单的引用 var nmsg = document.getElementById('message');//信息提示节点的引用
.m-form .j-err{display:block;color:#FF0000;} .m-form .j-suc{display:block;color:#158226;} .m-form .j-error{border-color:#f00;background-color: #FFE7E7;} .m-form .j-disabled{cursor:default;background-color:#ddd;}
①通用方法: function showMessage(clazz,msg){ nmsg.classList.remove('j-suc'); nmsg.classList.remove('j-err'); nmsg.classList.add(clazz); function invalidInput(node,msg){ showMessage('j-err',msg); node.classList.add('j-error'); function clearInvalid(node){ node.classList.remove('j-error'); //提交表单以后,服务器没有返回结果的这段时间,禁用登录按钮,防止用户重复提交 function disableSubmit(disabled){ form.loginBtn.disabled = !!disabled; var method = !disabled?'remove':'add'; form.loginBtn.classList[method]('j-disabled');
②验证手机号: form.telephone.addEventListener('invalid', function(event){ invalidInput(form.telephone,'请输入正确的手机号码');
③验证密码: //验证密码,注意:验证时机是提交表单的时候,不是点击提交按钮的时候。原因:用户提交表单不一定是要点击提交按钮,还可以隐式提交 form.addEventListener('submit', function(event){ var input = form.password, }else if(!/\d/.test(pswd)||!/[a-z]/i.test(pswd)){ invalidInput(input,emsg);
④表单提交: form.addEventListener('submit', function(event){
⑤状态恢复: form.addEventListener('input', function(event){ clearInvalid(event.target);
案例介绍:利用iframe无刷新提交 <iframe name='result' id='result' style='display:none;'></iframe> <form target='result' action='/api/login' class='m-form' name='loginForm'>
var frame = document.getElementById('result'); frame.addEventListener('load', function(event){ var result = JSON.parse(frame.contentWindow.document.body.textContent); showMessage('j-suc','登录成功!');
|