跳到主要内容

表单脚本

表单

表单基础

HTMLFormElement 类型
  • acceptCharset:字符集;
  • action:url;
  • elements:表单 HTMLCollection;
  • enctype:编码类型;
  • length:控件数量;
  • method:HTTP 请求;
  • name:表单名称;
  • reset():重置表单;
  • submit():提交;
获取表单
let form = document.getElementById("form1");
// 取得页面中的第一个表单
let firstForm = document.forms[0];
// 取得名字为"form2"的表单
let myForm = document.forms["form2"];

表单字段

访问表单字段
let form = document.getElementById("form1");
// 取得表单中的第一个字段
let field1 = form.elements[0];
// 取得表单中名为"textbox1"的字段
// 若存在多个同名字段, 返回 HTMLCollection
let field2 = form.elements["textbox1"];
// 取得字段的数量
let fieldCount = form.elements.length;
公共属性
  • disabled:布尔值,表单字段是否禁用;
  • form:指向表单字段所属的表单;
  • name:字段名称;
  • readOnly:布尔值,字段是否只读;
  • type:字段类型;
  • value:提交给服务器的值;
  • autofocus:布尔值,自动获得焦点;
公共方法
  • focus():获得焦点;
  • blur():取消焦点;
公共事件
  • blur:失去焦点时触发;
  • change:value 变化时触发;
  • focus:获得焦点时触发;

提交表单

语法格式
// 通用提交按钮
<input type="submit" value="Submit Form" />
// 自定义提交按钮
<button type="submit">Submit Form</button>
// 图片按钮
<input type="image" src="graphic.gif" />

// 提交表单
// 该方式不会触发 submit 事件
let form = document.getElementById("myForm");
form.submit();
submit 事件
// 表单提交前触发 submit 事件
let form = document.getElementById("myForm");
form.addEventListener("submit", (event) => {
// 阻止表单提交
event.preventDefault();
});

重置表单

语法格式
// 通用重置按钮
<input type="reset" value="Reset Form">
// 自定义重置按钮
<button type="reset">Reset Form</button>

// 重置表单
// 依旧触发 reset 事件
let form = document.getElementById("myForm");
form.reset();
reset 事件
// 表单重置前触发 reset 事件
let form = document.getElementById("myForm");
form.addEventListener("reset", (event) => {
event.preventDefault();
});

文本框编程

文本框编程基础

单行文本框
// 一次最多显示 25 个字符, 最大长度为 50 个字符
<input type="text" size="25" maxlength="50" value="initial value">
多行文本框
// 一行最多 25 个字符, 一次最多显示 5 行
<textarea rows="25" cols="5">
initial value
</textarea>

选择文本

select()
// 自动选中文本框所有文字
let textbox = document.forms[0].elements["textbox1"];
textbox.select();
select 事件
// 选中文本后触发
let textbox = document.forms[0].elements["textbox1"];
textbox.addEventListener("select", (event) => {
console.log(`Text selected: ${textbox.value}`);
});
文本偏移量
// selectionStart 属性为文本起始偏移量
// selectionEnd 属性为文本终止偏移量
function getSelectedText(textbox) {
return textbox.value.slice(textbox.selectionStart, textbox.selectionEnd);
}
选中部分文本
// HTML5 的 setSelectionRange()
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"

输入过滤

屏蔽字符
// 屏蔽数字
textbox.addEventListener("keypress", (event) => {
// 不屏蔽一些控制按键
// 若匹配则阻止这次事件
if (
!/\d/.test(String.fromCharCode(event.charCode)) &&
event.charCode > 9 &&
!event.ctrlKey
) {
event.preventDefault();
}
});
剪切板事件
  • beforecopy:复制前触发;
  • copy:复制时触发;
  • beforecut:剪切前触发;
  • cut:剪切时触发;
  • beforepaste:粘贴前触发;
  • paste:粘贴时重复啊;
操作剪切板
// 通过 window 对象 (IE) 或 event 对象 (Firefox, Safari 和 Chrome) 上的 clipboardData 对象获取剪切板
const clipboardData = event.clipboardData || window.clipboardData;
// 使用 MIME 类型
// 获得剪切板内容
const data = clipboardData.getData("text/plain");
// 设置剪切板内容
const data = clipboardData.setData("text/plain");
// 清理剪切板内容
const data = clipboardData.clearData("text/plain");

HTML5 约束验证 API

必填字段
// 设置 require 属性
let isUsernameRequired = document.forms[0].elements["username"].required;
设置类型
let input = document.createElement("input");
input.type = "email";
数值范围
input.stepUp(); // 加 1 步长
input.stepUp(5); // 加 5 步长
input.stepDown(); // 减 1 步长
input.stepDown(10); // 减 10 步长
输入模式
// 获取 pattern 属性
let pattern = document.forms[0].elements["count"].pattern;
// 设置 pattern 属性
document.forms[0].elements["count"].pattern = !/\d/;
检测有效性
// 检测单个字段是否有效
if (document.forms[0].elements[0].checkValidity()) {
// 字段有效, 继续
} else {
// 字段无效
}
// 检测表单 (所有字段) 是否有效
if (document.forms[0].checkValidity()) {
// 表单有效, 继续
} else {
// 表单无效
}

// validity 属性表示字段为什么有效/无效
const why = input.validity;
禁用验证
const noValidate = document.forms[0].noValidate; // 默认为 false
document.forms[0].noValidate = true; // 关闭验证

选择框编程

基础

HTMLSelectElement 属性和方法
  • add(new,rel):在 rel 之前添加新 option;
  • multiple:布尔值,对应 multiple 属性;
  • options:所有元素的 HTMLCollection;
  • remove(index):移除对应选项;
  • selectedIndex:第一个选中项的索引值;;
  • size:对应 size 属性;
  • type:对应 type 属性;
HTMLOptionElement 属性和方法
  • index:选项在 HTMLCollection 中的索引值;
  • label:对应 label 属性;
  • selected:布尔值,表示是否选中当前选项;
  • text:选项文本;
  • value:对应 value 属性;
change 事件
  • 选择框会在选中时立刻触发 change 事件;

选项处理

获取单选框选项
let selectedIndex = selectbox.selectedIndex;
let selectedOption = selectbox.options[selectedIndex];
console.log(
`Selected index: ${selectedIndex}\n` +
`Selected text: ${selectedOption.text}\n` +
`Selected value: ${selectedOption.value}`
);
获取多选框选项
function getSelectedOptions(selectbox) {
let result = new Array();
for (let option of selectbox.options) {
if (option.selected) {
result.push(option);
}
}
return result;
}

添加选项

DOM 方法
let newOption = document.createElement("option");
newOption.appendChild(document.createTextNode("Option text"));
newOption.setAttribute("value", "Option value");
selectbox.appendChild(newOption);
构造函数
// 创建 text 为 Option text, value 为 Option value 的 <option>
let newOption = new Option("Option text", "Option value");
selectbox.appendChild(newOption);
// 插入 newOption 至第二个参数对应标签之前, undefined 表示插入到末尾
selectbox.add(newOption, undefined);

移除选项

移除
selectbox.removeChild(selectbox.options[0]); // 移除第一项
selectbox.remove(0); // 移除索引为 0 的 <option>
selectbox.options[0] = null;
移除全部
// selectbox.options 为 HTMLCollection, 实时更新, 故移除第一项即可
function clearSelectbox(selectbox) {
for (let option of selectbox.options) {
selectbox.remove(0);
}
}

移动和重排选项

移动选项
// index 重置
let selectbox1 = document.getElementById("selLocations1");
let selectbox2 = document.getElementById("selLocations2");
selectbox2.appendChild(selectbox1.options[0]);
重排选项
let optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index - 1]);

表单序列化

表单提交格式
  • 字段名和值 & 分隔,使用 URL 编码;
  • 禁用字段不会发送;
  • reset/button 按钮不会发送;
  • submit 按钮点击才会发送;
  • 选择框选中后才会发送,每个选中项都有一个值;
function serialize(form) {
let parts = [];
let optValue;
for (let field of form.elements) {
switch (field.type) {
case "select-one":
case "select-multiple":
if (field.name.length) {
for (let option of field.options) {
if (option.selected) {
if (option.hasAttribute) {
optValue = option.hasAttribute("value")
? option.value
: option.text;
} else {
optValue = option.attributes["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("&");
}
}

富文本编辑

使用 iframe

基本技术
  • iframe 标签嵌入一个空白 HTML;
  • 通过 designMode 属性定义;
    • off:默认值,不可编辑;
    • on:可编辑;
空白 HTML 模板
<!DOCTYPE html>
<html>
<head>
<title>Blank Page for Rich Text Editing</title>
</head>
<body></body>
</html>

使用 contenteditable 属性

// 布尔属性
<div class="editable" id="richedit" contenteditable></div>;
// 切换编辑状态
// true: 开启, false: 关闭, inherit: 继承父元素
let div = document.getElementById("richedit");
richedit.contentEditable = "true";

富文本交互

execCommand()
// 执行对应命令
// 三个参数分别为执行命令, 是否提供为命令提供用户界面, 执行命令的必须值
frames["richedit"].document.execCommand("bold", false, null); // iframe
document.execCommand("createlink", false, "http://www.wrox.com"); // contenteditable 属性
queryCommandEnabled()
// 当前选中文本或光标所在位置能否执行对应命令
let result = frames["richedit"].document.queryCommandEnabled("bold");
queryCommandState()
// 对应命令是否应用至当前选中文本或光标所在位置
let isBold = frames["richedit"].document.queryCommandState("bold");
queryCommandValue()
// 返回执行命令的值
let fontSize = frames["richedit"].document.queryCommandValue("fontsize");

富文本选择

getSelection()
// 暴露于 document 和 window 对象
// 返回当前选中文本的 Selection 对象
let selection = frames["richedit"].getSelection();
Selection 对象
  • 一堆属性和方法,此处略;
  • 通过 DOM 范围控制选中文本;

提交富文本

方法
// 通过表单提交, 设置一个隐藏字段, 使用 iframe 或 contenteditable 元素的 HTML 更新它的值
// iframe
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;
});