JavaScript高级程序设计(4)
第19章 表单脚本
### 19.1 表单基础 581 > - 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 属性。 > > - 取得对<form>元素的引用 > > ```javascript > let form = document.getElementById("form1"); > > // 取得页面中的第一个表单 > let firstForm = document.forms[0]; > > // 取得名字为"form2"的表单 > let myForm = document.forms["form2"]; > ``` ##### 19.1.1 提交表单 - > ```javascript > let form = document.getElementById("myForm"); > form.addEventListener("submit", (event) => { > // 阻止表单提交 > event.preventDefault(); > // 取得提交按钮 > let btn = target.elements["submit-btn"]; > // 禁用提交按钮 > btn.disabled = true; > }); > > // 提交表单。通过 submit()提交表单时,submit 事件不会触发。因此在调用这个方法前要先做数据验证 > form.submit(); > ``` > > 表单提交的一个最大的问题是可能会提交两次表单。如果提交表单之后没有什么反应,那么没有耐心的用户可能会多次点击提交按钮。结果是很烦人的(因为服务器要处理重复的请求),甚至可能造成损失(如果用户正在购物,则可能会多次下单)。解决这个问题主要有两种方式:在表单提交后禁用提交按钮,或者通过 onsubmit 事件处理程序取消之后的表单提交。 ##### 19.1.2 重置表单 - > ``` > let form = document.getElementById("myForm"); > // 重置表单 > form.reset(); > ``` > > 表单设计中通常不提倡重置表单,因为重置表单经常会导致用户迷失方向,如果意外触发则会令人感到厌烦。实践中几乎没有重置表单的需求。一般来说,提供一个取消按钮,让用户点击返回前一个页面,而不是恢复表单中所有的值来得更直观。 ##### 19.1.3 表单字段 - > - 有表单元素都是表单elements 属性(元素集合)中包含的一个值。。这个 elements 集合是一个有序列表,包含对表单中所有字段的引用,可以通过索引位置和 name 属性来访问。 > > ```javascript > let form = document.getElementById("form1"); > // 取得表单中的第一个字段 > let field1 = form.elements[0]; > // 取得表单中名为"textbox1"的字段 > let field2 = form.elements["textbox1"]; > // 取得字段的数量 > let fieldCount = form.elements.length; > ``` > > - 表单字段的公共属性 > > - disabled:布尔值,表示表单字段是否禁用。 > - form:指针,指向表单字段所属的表单。这个属性是只读的。 > - name:字符串,这个字段的名字。 > - readOnly:布尔值,表示这个字段是否只读。 > - tabIndex:数值,表示这个字段在按 Tab 键时的切换顺序。 > - type:字符串,表示字段类型,如"checkbox"、"radio"等。 > - value:要提交给服务器的字段值。对文件输入字段来说,这个属性是只读的,仅包含计算机上某个文件的路径。 > > ```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"; > ``` > > - 表单字段的公共方法:focus()和 blur() > > ```javascript > window.addEventListener("load", (event) => { > document.forms[0].elements[0].focus(); > }); > ``` > > - autofocus 属性:HTML5 为表单字段增加的,支持的浏览器会自动为带有该属性的元素设置焦点。 > > ```html > <input type="text" autofocus> > ``` > > - 表单字段的公共事件 > > - blur:在字段失去焦点时触发。 > > - change:在<input>和<textarea>元素的 value 发生变化且失去焦点时触发,或者在<select>元素中选中项发生变化时触发。 > > - focus:在字段获得焦点时触发。 > > ```javascript > let textbox = document.forms[0].elements[0]; > textbox.addEventListener("focus", (event) => { > let target = event.target; > if (target.style.backgroundColor != "red") { > target.style.backgroundColor = "yellow"; > } > }); > textbox.addEventListener("blur", (event) => { > let target = event.target; > target.style.backgroundColor = /[^\d]/.test(target.value) ? "red" : ""; > }); > textbox.addEventListener("change", (event) => { > let target = event.target; > target.style.backgroundColor = /[^\d]/.test(target.value) ? "red" : ""; > }); > ``` ### 19.2 文本框编程 587 > - <input>元素显示为文本框,省略 type 属性会以"text"作为默认值。通过size 属性指定文本框的宽度,以字符数来计量的。value 属性用于指定文本框的初始值,maxLength 属性用于指定文本框允许的最多字符数。 > > - \<textarea\>元素总是会创建多行文本框。可以使用 rows 属性指定这个文本框的高度,以字符数计量;以 cols 属性指定以字符数计量的文本框宽度,类似于<input>元素的 size 属性。 > > ```html > <input type="text" size="25" maxlength="50" value="initial value"> > > <textarea rows="25" cols="5">initial value</textarea> > ``` ##### 19.2.1选择文本 - > - select()方法:法用于全部选中文本框中的文本。不接收参数,可以在任何时候调用。 > > ```javascript > //在文本框获得焦点时选中所有文本是非常常见的,特别是在文本框有默认值的情况下。这样做的出发点是让用户能够一次性删除所有默认内容。可以通过以下代码来实现: > textbox.addEventListener("focus", (event) => { > event.target.select(); > }); > ``` > > - **select** 事件:当选中文本框中的文本时,或调用select()方法时,会触发 select 事件。 > > ```javascript > let textbox = document.forms[0].elements["textbox1"]; > textbox.addEventListener("select", (event) => { > console.log(`Text selected: ${textbox.value}`); > }); > ``` > > - selectionStart 和 selectionEnd:取得选中文本 ,这两个属性包含基于 0 的数值,分别表示文本选区的起点和终点。 > > ```javascript > function getSelectedText(textbox){ > return textbox.value.substring(textbox.selectionStart, > textbox.selectionEnd); > } > ``` > > - setSelectionRange():部分选中文本,这个方法接收两个参数:要选择的第一个字符的索引和停止选择的字符的索引。 > > ```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" > ``` ##### 19.2.2 输入过滤 - > - 屏蔽字符 > > ```javascript > //先用String.fromCharCode()把事件的charCode 转换为字符串, > //再屏蔽 charCode 大于 10 的键 > //再屏蔽快捷键 Ctrl+C、Ctrl+V 及其他使用 Ctrl 的组合键 > //再用正则表达式/\d/来测试。 > textbox.addEventListener("keypress", (event) => { > if (!/\d/.test(String.fromCharCode(event.charCode)) && > event.charCode > 9 && > !event.ctrlKey){ > event.preventDefault(); > } > }); > ``` > > - 处理剪贴板 > > - beforecopy:复制操作发生前触发。 > - copy:复制操作发生时触发。 > - beforecut:剪切操作发生前触发。 > - cut:剪切操作发生时触发。 > - beforepaste:粘贴操作发生前触发。 > - paste:粘贴操作发生时触发。 > > ```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); > } > } > ``` ##### 19,2.3 自动切换 - > JavaScript 可以通过很多方式来增强表单字段的易用性。最常用的是在当前字段完成时自动切换到下一个字段。对于要收集数据的长度已知(比如电话号码)的字段是可以这样处理的。为增加表单的易用性并加速数据输入,可以在每个文本框输入到最大允许字符数时自动把焦点切换到下一个文本框。 > > ```javascript > 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); > } > </script> > ``` ##### 19.2.4 HTML5约束验证API - > - 必填字段 **required** > > ```html > <input type="text" name="username" required> > ``` > > - 更多输入类型 > > ```html > <input type="email" name="email"> > <input type="url" name="homepage"> > ``` > > - 数值范围 > > ```html > //number、range、datetime、date、month、week、time、datetime-local。 > <input type="number" min="0" max="100" step="5" name="count"> > ``` > > - 输入模式 pattern > > ```html > //要限制只能在文本字段中输入数字 > <input type="text" pattern="\d+" name="count"> > ``` > > - 检测有效性 checkValidity() > > > 这个方法在所有表单元素上都可以使用,如果字段值有效就会返回 true,否则返回 false。判断字段是否有效的依据是本节前面提到的约束条件,因此必填字段如果没有值就会被视为无效,而字段值不匹配 pattern 属性也会被视为无效。 > > ```javascript > if (document.forms[0].elements[0].checkValidity()){ > // 字段有效,继续 > } else { > // 字段无效 > } > ``` > > - 禁用验证 novalidate > > ```html > //通过指定 novalidate 属性可以禁止对表单进行任何验证: > <form method="post" action="/signup" novalidate> > <!-- 表单元素 --> > </form> > > //提交按钮添加 formnovalidate 属性 > <input type="submit" formnovalidate name="btnNoValidate" > value="Non-validating Submit"> > ``` ### 19.3 选择框编程 597 ##### 19.3.1 选项处理 - > - 对于只允许选择一项的选择框 > > ```javascript > //获取选中的 > let selectedIndex = selectbox.selectedIndex; > let selectedOption = selectbox.options[selectedIndex]; > > console.log(`Selected index: ${selectedIndex}\n` + > `Selected text: ${selectedOption.text}\n` + > `Selected value: ${selectedOption.value}`); > ``` > > - 对于允许多选的选择框 > > ```javascript > //获取选中的 > function getSelectedOptions(selectbox){ > let result = new Array(); > for (let option of selectbox.options) { > if (option.selected) { > result.push(option); > } > } > return result; > } > ``` ##### 19.3.2 添加选项 - >```javascript >//使用 JavaScript 动态创建选项并将它们添加到选择框 >let newOption = document.createElement("option"); >newOption.appendChild(document.createTextNode("Option text")); >newOption.setAttribute("value", "Option value"); >selectbox.appendChild(newOption); > >//也可以使用 Option 构造函数创建新选项 >let newOption = new Option("Option text", "Option value"); >selectbox.add(newOption, undefined); // 最佳方案 >``` ##### 19.3.3 移除选项 - >```javascript >//第一种方式是使用 DOM 的 removeChild()方法并传入要移除的选项,比如: >selectbox.removeChild(selectbox.options[0]); // 移除第一项 > >//第二种方式是使用选择框的 remove()方法。这个方法接收一个参数,即要移除选项的索引,比如: >selectbox.remove(0); // 移除第一项 > >//最后一种方式是直接将选项设置为等于 null >selectbox.options[0] = null; // 移除第一项 >``` ##### 19.3.4 移动和重排选项 ### 19.4 表单序列化 601 > $('#form').serialize() ### 19.5 富文本编辑 603 ##### 19.5.1 使用 **contenteditable** - > 可以给页面中的任何元素指定 contenteditable 属性,然后该元素会立即被用户编辑。这种方式更受欢迎,因为不需要额外的 iframe、空页面和 JavaScript。元素中包含的任何文本都会自动被编辑,元素本身类似于<textarea>元素。 > > ```html > <div style="width:200px;height:200px;border:1px red solid" id="richedit" contenteditable></div> > > //以把浏览器窗口转换为一个记事本 > <html contenteditable> > ``` ##### 19.5.2 与富文本交互 - > document.execCommand():与富文本编辑器交互的主要方法是使用 document.execCommand()。这个方法在文档上执行既定的命令,可以实现大多数格式化任务。要执行的命令、表示浏览器是否为命令提供用户界面的布尔值和执行命令必需的值(如果不需要则为 null)。为跨浏览器兼容,第二个参数应该始终为 false。 > > ```javascript > //修改内嵌窗格(iframe)中富文本区域的外观,如下面的例子所示: > // 在内嵌窗格中切换粗体文本样式 > frames["richedit"].document.execCommand("bold", false, null); > > // 在内嵌窗格中切换斜体文本样式 > frames["richedit"].document.execCommand("italic", false, null); > > // 在内嵌窗格中创建指向 www.wrox.com 的链接 > frames["richedit"].document.execCommand("createlink", false, > "http://www.wrox.com"); > > // 在内嵌窗格中为内容添加<h1>标签 > frames["richedit"].document.execCommand("formatblock", false, "<h1>"); > ``` ##### 19.5.3 富文件选择 - > 在内嵌窗格中使用 getSelection()方法,可以获得富文本编辑器的选区。 > > ```javascript > 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); > ``` ##### 19.5.4 通过表单提交富文本 - > 要把富文本编辑的结果提交给服务器,必须手工提取 HTML 并自己提交。通常的解决方案是在表单中添加一个隐藏字段,使用内嵌窗格或contenteditable 元素的 HTML 更新它的值。在表单提交之前,从内嵌窗格或 contenteditable 元素中提取出 HTML 并插入隐藏字段中。 > > ```javascript > //代码使用文档主体的 innerHTML 属性取得了内嵌窗格的 HTML,然后将其插入名为"comments"的表单字段中。 > form.addEventListener("submit", (event) => { > let target = event.target; > target.elements["comments"].value = > frames["richedit"].document.body.innerHTML; > }); > > //对于 contenteditable 元素,执行这一操作的代码是类似的: > form.addEventListener("submit", (event) => { > let target = event.target; > target.elements["comments"].value = > document.getElementById("richedit").innerHTML; > }); > ```
顶部
收展
底部
[TOC]
目录
第1章 JavaScript简介
第2章 在 HTML中使用JavaScript
第3章 语言基础(1)语法变量
第3章 语言基础(2)数据类型
第3章 语言基础(3)操作符
第3章 语言基础(4)语句
第4章 变量、作用域与内存
第5章 基本引用类型
第6章 集合引用类型
第7章 迭代器与生成器
第8 章对象、类与面向对象编程
第9章 代理与反射
第10章 函数
第11章 期约与异步函数
第12章 BOM
第13章 客户端检测
第14章 DOM
第15章 DOM 扩展
第16章 DOM2 和 DOM3
第17章 事件
第18章 动画与 Canvas 图形
第19章 表单脚本
第20章 JavaScript API
第21章 错误处理与调试
第22章 处理 XML
第23章 JSON
第24章 网络请求与远程资源
第25章 客户端存储
第26章 模块
第27章 工作者线程
第28章 最佳实践
相关推荐
WebSocket