表单基础1、获取表单引用2、提交表单提交提交前验证(阻止直接提交)重复提交3、重置表单4、表单字段公共属性公共方法焦点 focus()移除焦点 blur()公共事件文本框编程文本框 input / textarea选中文本框 select()选中文本selectionStart 和 selectionEndsetSelectionRange输入过滤屏蔽输入表单验证(HTML5)必填数值范围输入模式检测有效性剪贴板事件自动切换JavaScript 较早的一个用途是承担一部分服务器端表单处理的责任。 虽然 Web 和 JavaScript 都已经发 展了很多年,但 Web 表单的变化不是很大。 由于不能直接使用表单解决问题,因此开发者不得不使用 JavaScript 既做表单验证,又用于增强标准表单控件的默认行为。 表单基础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 属性。 reset():把表单字段重置为各自的默认值。 submit():提交表单。 target:用于发送请求和接收响应的窗口的名字,等价于 HTML 的 target 属性。 1、获取表单引用let form = document.getElementById("form1");document.forms//可以获取页面上所有的表单元素。// 取得页面中的第一个表单let firstForm = document.forms[0];// 取得名字为"form2"的表单let myForm = document.forms["form2"]; 注意,表单可以同时拥有 id 和 name,而且两者可以不相同。 2、提交表单表单是通过用户点击提交按钮或图片按钮的方式提交的。 提交按钮可以使用 type 属性为”submit” 的或元素来定义,图片按钮可以使用 type 属性为”image”的元素来定义。 提交<!-- 通用提交按钮 --> <input type="submit" value="Submit Form"> <!-- 自定义提交按钮 --> <button type="submit">Submit Form</button> <!-- 图片按钮 --> <input type="image" src="graphic.gif"> 如果表单中有上述任何一个按钮,且焦点在表单中某个控件上,则按回车键也可以提交表单。(textarea 例外,按回车键会换行) 注意,没有提交按钮的表单在按回 车键时不会提交。 以这种方式提交表单会在向服务器发送请求之前触发 submit 事件。 提交前验证(阻止直接提交)这样就提供了一个验证表单数 据的机会,可以根据验证结果决定是否真的要提交。 阻止这个事件的默认行为可以取消提交表单。 let form = document.getElementById("myForm"); form.addEventListener("submit", (event) => { // 阻止表单提交 event.preventDefault(); });// 可以调用表单的方法提交表单form.submit(); 重复提交表单提交的一个最大的问题是可能会提交两次表单。 如果提交表单之后没有什么反应,那么没有耐 心的用户可能会多次点击提交按钮。 解决这个问题主要有两种方式:1、在表单提交后禁用提 交按钮,2、或者通过 onsubmit 事件处理程序取消之后的表单提交。 3、重置表单用户单击重置按钮可以重置表单。 重置按钮可以使用 type 属性为”reset”的或 元素来创建 <!-- 通用重置按钮 --> <input type="reset" value="Reset Form"> <!-- 自定义重置按钮 --> <button type="reset">Reset Form</button> 这两种按钮都可以重置表单。 表单重置后,所有表单字段都会重置回页面第一次渲染时各自拥有的 值。 如果字段原来是空的,就会变成空的;如果字段有默认值,则恢复为默认值。 let form = document.getElementById("myForm"); form.addEventListener("reset", (event) => { event.preventDefault(); // 阻止默认的重置方法}); // 与表单提交一样,重置表单也可以通过 JavaScript 调用 reset()方法来完成,如下面的例子所示:// 重置表单form.reset(); 与 submit()方法的功能不同,调用 reset()方法会像单击了重置按钮一样触发 reset 事件。 表单设计中通常不提倡重置表单,因为重置表单经常会导致用户迷失方向,如果意 外触发则会令人感到厌烦。 实践中几乎没有重置表单的需求。 一般来说,提供一个取消按 钮,让用户点击返回前一个页面,而不是恢复表单中所有的值来得更直观。 4、表单字段表单元素可以像页面中的其他元素一样使用原生 DOM 方法来访问。 此外,所有表单元素都是表单 elements 属性(元素集合)中包含的一个值。 这个 elements 集合是一个有序列表,包含对表单中所 有字段的引用,包括所有、、<button>、<select>和<fieldset>元素。</p> <p>elements 集合中的每个字段都以它们在 HTML 标记中出现的次序保存,可以通过索引位置和 name 属性来访问。</p> <pre><code class="lang-javascript">let form = document.getElementById("form1"); // 取得表单中的第一个字段 let field1 = form.elements[0]; // 取得表单中名为"textbox1"的字段 let field2 = form.elements["textbox1"]; // 取得字段的数量 let fieldCount = form.elements.length; </code></pre> <p>如果多个表单控件使用了同一个 name,比如像单选按钮那样,则会返回包含所有同名元素的 HTMLCollection。</p> <pre><code class="lang-javascript">/* <form method="post" id="myForm"> <ul> <li><input type="radio" name="color" value="red">Red</li> <li><input type="radio" name="color" value="green">Green</li> <li><input type="radio" name="color" value="blue">Blue</li> </ul> </form> */ let form = document.getElementById("myForm"); let colorFields = form.elements["color"]; console.log(colorFields.length); // 3 返回的 NodeList 就包含这 3 个元素 let firstColorField = colorFields[0]; let firstFormField = form.elements[0]; console.log(firstColorField === firstFormField); // true </code></pre> <p><a name="avbIs"></a></p> <h3 id="du14ug"><a name="du14ug" class="reference-link"></a><span class="header-link octicon octicon-link"></span>公共属性</h3><p>除<fieldset>元素以外,所有表单字段都有一组同样的属性。</p> <p>由于<input>类型可以表示多种表 单字段,因此某些属性只适用于特定类型的字段。</p> <p>除此之外的属性可以在任何表单字段上使用。</p> <p> disabled:布尔值,表示表单字段是否禁用。 <br /> form:指针,指向表单字段所属的表单。这个属性是只读的。 <br /> name:字符串,这个字段的名字。 <br /> readOnly:布尔值,表示这个字段是否只读。 <br /> tabIndex:数值,表示这个字段在按 Tab 键时的切换顺序。 <br /> type:字符串,表示字段类型,如”checkbox”、”radio”等。 <br /> value:要提交给服务器的字段值。对文件输入字段来说,这个属性是只读的,仅包含计算机上 某个文件的路径。</p> <p>这里面除了 form 属性以外,JavaScript 可以动态修改任何属性。</p> <pre><code class="lang-javascript">let form = document.getElementById("myForm"); let field = form.elements[0]; // 修改字段的值 field.value = "Another value"; // 检查字段所属的表单 console.log(field.form === form); // true // 给字段设置焦点 field.focus(); // 禁用字段 field.disabled = true; // 改变字段的类型(不推荐,但对<input>来说是可能的) field.type = "checkbox"; </code></pre> <p><a name="SlqIG"></a></p> <h3 id="9iha28"><a name="9iha28" class="reference-link"></a><span class="header-link octicon octicon-link"></span>公共方法</h3><p><a name="VuJSD"></a></p> <h4 id="anmi8s"><a name="anmi8s" class="reference-link"></a><span class="header-link octicon octicon-link"></span>焦点 focus()</h4><p>focus()方法把浏览器焦点设置到表单字 段,这意味着该字段会变成活动字段并可以响应键盘事件。</p> <pre><code class="lang-javascript">window.addEventListener("load", (event) => { document.forms[0].elements[0].focus(); }); </code></pre> <p>如果表单中第一个字段是 type 为”hidden”的<input>元素,或者该字段被 CSS 属性 display 或 visibility 隐藏了,以上代码就会出错。</p> <p>HTML5 为表单字段增加了 autofocus 属性,支持的浏览器会自动为带有该属性的元素设置焦点, 而无须使用 JavaScript。</p> <pre><code class="lang-html"><input type="text" autofocus> </code></pre> <p>果设置了 autofocus,就不再调用 focus()</p> <p><a name="kUGqh"></a></p> <h4 id="et84dh"><a name="et84dh" class="reference-link"></a><span class="header-link octicon octicon-link"></span>移除焦点 blur()</h4><p>focus()的反向操作是 blur(),其用于从元素上移除焦点。调用 blur()时,焦点不会转移到任何 特定元素,仅仅只是从调用这个方法的元素上移除了。</p> <pre><code class="lang-javascript">document.forms[0].elements[0].blur(); </code></pre> <p><a name="jXNGi"></a></p> <h3 id="caima1"><a name="caima1" class="reference-link"></a><span class="header-link octicon octicon-link"></span>公共事件</h3><p>除了鼠标、键盘、变化和 HTML 事件外,所有字段还支持以下 3 个事件。</p> <p> blur:在字段失去焦点时触发。 <br /> change:在<input>和<textarea>元素的 value 发生变化且失去焦点时触发,或者在</p> <p><select>元素中选中项发生变化时触发。 <br /> focus:在字段获得焦点时触发。</p> <p>blur 和 focus 事件会因为用户手动改变字段焦点或者调用 blur()或 focus()方法而触发。</p> <p>这两 个事件对所有表单都会一视同仁。</p> <p>change 事件则不然,它会因控件不同而在不同时机触发。</p> <p><input>和<textarea>元素,change 事件会在字段失去焦点,同时 value 自控件获得焦点后发生变 化时触发。<br />对于<select>元素,change 事件会在用户改变了选中项时触发,不需要控件失去焦点。</p> <p>focus 事件可以用来改变控件的背景颜色以便更清楚地表明当前字段获得了焦点。 <br />blur 事件可以用于去掉这个背景颜色。而 change 事件可以用于在用户输入了非数值时把背景改为红 色。</p> <pre><code class="lang-javascript">let textbox = document.forms[0].elements[0]; // 这里的 onfocus 事件处理程序会把文本框的背景改为黄色,更清楚地表明它是当前活动字段。 textbox.addEventListener("focus", (event) => { let target = event.target; if (target.style.backgroundColor != "red") { target.style.backgroundColor = "yellow"; } }); // onblur 和 onchange 事件处理程序会在发现非数值字符时把背景改为红色。 textbox.addEventListener("blur", (event) => { let target = event.target; target.style.backgroundColor = /[^\d]/.test(target.value) ? "red" : ""; }); // 这个功能必须同时在 onblur 和 onchange 事件处理程序上实现,以确保无论文本框是否改变都能执行验证。 textbox.addEventListener("change", (event) => { let target = event.target; target.style.backgroundColor = /[^\d]/.test(target.value) ? "red" : ""; }); </code></pre> <p><a name="ZFnxK"></a></p> <h1 id="e7y9m0"><a name="e7y9m0" class="reference-link"></a><span class="header-link octicon octicon-link"></span>文本框编程</h1><p><a name="W9Asi"></a></p> <h2 id="d09pwl"><a name="d09pwl" class="reference-link"></a><span class="header-link octicon octicon-link"></span>文本框 input / textarea</h2><p>单行使用<input>元素,多行使用<textarea>元素。</p> <pre><code class="lang-html"><input type="text" size="25" maxlength="50" value="初始值"> <!--一次可显示 25 个字符,但最多允许显示 50 个字符的文本框--> <textarea rows="25" cols="5">初始值</textarea> <!--25字符数高度,5字符宽度的多行文本框--> </code></pre> <p>直接用.value 读写输入的值</p> <p><a name="cLKI9"></a></p> <h2 id="flpxew"><a name="flpxew" class="reference-link"></a><span class="header-link octicon octicon-link"></span>选中文本框 select()</h2><p>此方法用于全部选中文本框中的文本,是让用户能够一次性删除所有默认内容</p> <pre><code class="lang-javascript">let textbox = document.forms[0].elements["textbox1"]; // 只要文本框一获得焦点就会自动选中其中的所有文本 textbox.addEventListener("focus", (event) => { event.target.select(); }); </code></pre> <p><a name="YlVpl"></a></p> <h2 id="7oi6p0"><a name="7oi6p0" class="reference-link"></a><span class="header-link octicon octicon-link"></span>选中文本</h2><p><a name="ubfwX"></a></p> <h3 id="2oioyp"><a name="2oioyp" class="reference-link"></a><span class="header-link octicon octicon-link"></span>selectionStart 和 selectionEnd</h3><p>两个属性包含基于 0 的数值,分别表示文本选区的起点和终点(文本选区起点的偏移量和文本选区终 点的偏移量)。</p> <pre><code class="lang-javascript">// 要取得文本框中选中的文本 function getSelectedText(textbox){ return textbox.value.substring(textbox.selectionStart,textbox.selectionEnd); } </code></pre> <p><a name="UPOGP"></a></p> <h3 id="9mdp56"><a name="9mdp56" class="reference-link"></a><span class="header-link octicon octicon-link"></span>setSelectionRange</h3><p>要选择 的第一个字符的索引和停止选择的字符的索引(与字符串的 substring()方法一样)。</p> <pre><code class="lang-javascript">textbox.value = "Hello world!" // 选择所有文本 textbox.setSelectionRange(0, textbox.value.length); // "Hello world!" // 选择前 3 个字符 textbox.setSelectionRange(0, 3); // "Hel" // 选择第 4~6 个字符 textbox.setSelectionRange(4, 7); // "o w" </code></pre> <p><a name="kAido"></a></p> <h2 id="b61scz"><a name="b61scz" class="reference-link"></a><span class="header-link octicon octicon-link"></span>输入过滤</h2><p><a name="zDm9e"></a></p> <h3 id="40sk98"><a name="40sk98" class="reference-link"></a><span class="header-link octicon octicon-link"></span>屏蔽输入</h3><pre><code class="lang-javascript">// 屏蔽输入 textbox.addEventListener("keypress", (event) => { // 先用String.fromCharCode()把事件的charCode 转换为字符串,再用正则表达式/\d/来测试 if (!/\d/.test(String.fromCharCode(event.charCode))){ event.preventDefault(); } }); </code></pre> <p><a name="V2JSV"></a></p> <h2 id="emfo6w"><a name="emfo6w" class="reference-link"></a><span class="header-link octicon octicon-link"></span>表单验证(HTML5)</h2><p>HTML5为浏览器新增了在提交表单前验证数据的能力。</p> <p>这些能力实现了基本的验证,即使JavaScript 不可用或加载失败也没关系。</p> <p><a name="iCrSM"></a></p> <h3 id="21n3ph"><a name="21n3ph" class="reference-link"></a><span class="header-link octicon octicon-link"></span>必填</h3><p>任何带有 required 属性的字段都必须有值,否则无法提交表单。</p> <p>这个属性适用于<input>、</p> <p><textarea>和<select>字段</p> <pre><code class="lang-html"><input type="text" name="username" required> </code></pre> <p>可以通过 JavaScript 检测对应元素的 required 属性来判断表单字段是否为必填</p> <pre><code class="lang-javascript">let isUsernameRequired = document.forms[0].elements["username"].required; //还可以使用下面的代码检测浏览器是否支持 required 属性 let isRequiredSupported = "required" in document.createElement("input"); </code></pre> <p><a name="F6lgA"></a></p> <h3 id="5za0dw"><a name="5za0dw" class="reference-link"></a><span class="header-link octicon octicon-link"></span>数值范围</h3><p>包括:”number”、”range”、”datetime”、”datetime-local”、”date”、”month”、”week” 和”time”</p> <p>并非所有主流浏览器都支持这些类型,因此使用时要当心。</p> <p>对上述每种数值类型,都可以指定 min 属性(最小可能值)、max 属性(最大可能值),以及 step 属性(从 min 到 max 的步长值)。</p> <pre><code class="lang-html"><input type="number" min="0" max="100" step="5" name="count"> </code></pre> <p><a name="xVbPI"></a></p> <h3 id="xqkcw"><a name="xqkcw" class="reference-link"></a><span class="header-link octicon octicon-link"></span>输入模式</h3><p>HTML5 为文本字段新增了 pattern 属性。这个属性用于指定一个正则表达式,用户输入的文本必 须与之匹配。</p> <pre><code class="lang-html"><input type="text" pattern="\d+" name="count"> </code></pre> <p>指定 pattern 属性也不会阻止用户输入无效内容。</p> <pre><code class="lang-javascript">// 通过访问 pattern 属性可以读取模式: let pattern = document.forms[0].elements["count"].pattern; // 使用如下代码可以检测浏览器是否支持 pattern 属性: let isPatternSupported = "pattern" in document.createElement("input"); </code></pre> <p><a name="yfgYz"></a></p> <h3 id="8frig9"><a name="8frig9" class="reference-link"></a><span class="header-link octicon octicon-link"></span>检测有效性</h3><p>使用 checkValidity()方法可以检测表单中任意给定字段是否有效。</p> <p>这个方法在所有表单元素上 都可以使用,如果字段值有效就会返回 true,否则返回 false。</p> <pre><code class="lang-javascript">if(document.forms[0].checkValidity()){ // 表单有效,继续 } else { // 表单无效 } </code></pre> <p>validity 属性会告诉我们字段为什么有 效或无效。这个属性是一个对象,包含一系列返回布尔值的属性。<br /> customError:如果设置了 setCustomValidity()就返回 true,否则返回 false。 <br /> patternMismatch:如果字段值不匹配指定的 pattern 属性则返回 true。 <br /> rangeOverflow:如果字段值大于 max 的值则返回 true。 <br /> rangeUnderflow:如果字段值小于 min 的值则返回 true。 <br /> stepMisMatch:如果字段值与 min、max 和 step 的值不相符则返回 true。 <br /> tooLong:如果字段值的长度超过了 maxlength 属性指定的值则返回 true。某些浏览器,如 Firefox 4 会自动限制字符数量,因此这个属性值始终为 false。 <br /> typeMismatch:如果字段值不是”email”或”url”要求的格式则返回 true。 <br /> valid:如果其他所有属性的值都为 false 则返回 true。与 checkValidity()的条件一致。 <br /> valueMissing:如果字段是必填的但没有值则返回 true。 <br /></p> <pre><code class="lang-javascript">if (input.validity && !input.validity.valid){ if (input.validity.valueMissing){ console.log("Please specify a value.") } else if (input.validity.typeMismatch){ console.log("Please enter an email address."); } else { console.log("Value is invalid."); } } </code></pre> <p><a name="VjTZ2"></a></p> <h2 id="cuouat"><a name="cuouat" class="reference-link"></a><span class="header-link octicon octicon-link"></span>剪贴板事件</h2><p> beforecopy:复制操作发生前触发。 <br /> copy:复制操作发生时触发。 <br /> beforecut:剪切操作发生前触发。 <br /> cut:剪切操作发生时触发。 <br /> beforepaste:粘贴操作发生前触发。 <br /> paste:粘贴操作发生时触发。</p> <p>通过 beforecopy、beforecut 和 beforepaste 事件可以在向剪贴板发送或从中检索数据前修改 数据。</p> <p>不过,取消这些事件并不会取消剪贴板操作。</p> <p>要阻止实际的剪贴板操作,必须取消 copy、cut 和 paste 事件。</p> <p>剪贴板上的数据可以通过 window 对象(IE)或 event 对象(Firefox、Safari 和 Chrome)上的 clipboardData 对象来获取。</p> <p>clipboardData 对象上有 3 个方法:getData()、setData()和 clearData(),<br />其中 getData() 方法从剪贴板检索字符串数据,并接收一个参数,该参数是要检索的数据的格式,Firefox、Safari 和 Chrome 则期待 MIME 类型。<br />setData()方法也类似,其第一个参数用于指定数据类型,第二个参数是要放到剪贴板上的文本。</p> <pre><code class="lang-javascript">function getClipboardText(event){ var clipboardData = (event.clipboardData || window.clipboardData); return clipboardData.getData("text"); } function setClipboardText (event, value){ if (event.clipboardData){ return event.clipboardData.setData("text/plain", value); } else if (window.clipboardData){ return window.clipboardData.setData("text", value); } } // 粘贴时验证数据,实现过滤 textbox.addEventListener("paste", (event) => { let text = getClipboardText(event); if (!/^\d*$/.test(text)){ event.preventDefault(); } }); </code></pre> <p><a name="f1hZA"></a></p> <h2 id="eocvnc"><a name="eocvnc" class="reference-link"></a><span class="header-link octicon octicon-link"></span>自动切换</h2><p>按tab键自动切换成下一个</p> <pre><code class="lang-html"><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"> <script> function tabForward(event){ let target = event.target; if (target.value.length == target.maxLength){ let form = target.form; for (let 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; } let inputIds = ["txtTel1", "txtTel2", "txtTel3"]; for (let id of inputIds) { let textbox = document.getElementById(id); textbox.addEventListener("keyup", tabForward); } let textbox1 = document.getElementById("txtTel1"); let textbox2 = document.getElementById("txtTel2"); let textbox3 = document.getElementById("txtTel3"); </script> </code></pre> <p>这个 tabForward()函数是实现自动切换的关键。</p> <p>它通过比较用户输入文本的长度与 maxlength 属性的值来检测输入是否达到了最大长度。如果两者相等则换下一个</p>