表单控件
2025年1月10日大约 6 分钟
tabindex
- 任何具有
tabindex
特性的元素,都会变成可聚焦的 - 该特性的
value
是当使用 Tab(或类似的东西)在元素之间进行切换时,元素的顺序号 - 切换顺序为:从
1
开始的具有tabindex
的元素排在前面(按tabindex
顺序),然后是不具有tabindex
的元素(例如常规的<input>
) - 不具有
tabindex
的元素按文档源顺序(默认顺序)切换 tabindex="0"
会使该元素被与那些不具有tabindex
的元素放在一起。也就是说,当我们切换元素时,具有tabindex="0"
的元素将排在那些具有tabindex ≥ 1
的元素的后面tabindex="-1"
只允许以编程的方式聚焦于元素。Tab 键会忽略这样的元素,但是elem.focus()
有效- 可以使用
elem.tabIndex
通过 JavaScript 来添加tabindex
,效果是一样的
获取表单
document.forms.my; // name="my" 的表单
document.forms[0]; // 文档中的第一个表单
element.form; // 反向获取表单
获取表单元素
- 返回元素节点或元素节点列表
form.elements.name
可以简写成form.name
<form name="my">
<input name="one" value="1">
<input name="two" value="2">
<fieldset name="userFields">
<legend>info</legend>
<input name="login" type="text">
</fieldset>
</form>
<script>
// 获取表单
let form = document.forms.my; // <form name="my"> 元素
// 获取表单中的元素
let elem = form.elements.one; // <input name="one"> 元素
console.log(elem.value); // 1
let fieldset = form.elements.userFields;
console.log(fieldset); // HTMLFieldSetElement
// 可以通过名字从表单和 fieldset 中获取 input
console.log(fieldset.elements.login == form.elements.login); // true
</script>
表单元素
input
input.value
:获取值
radio
radio.checked
:是否选中
checkbox
checkbox.checked
:是否选中
textarea
textarea.value
:获取值
select
select.options
:获取<option>
子元素集合select.value
:当前选择<option>
的value
select.selectedIndex
:当前选择<option>
的索引option.selected
:<option>
是否被选择option.index
:<option>
在所属<select>
中的索引option.text
:<option>
的文本内容option.value
:<option>
的value
新增
<option>
标签的方式
/**
* text:标签内的文本内容
* value:标签 value 属性的值
* defaultSelected:如果为 true,则会在添加标签属性 selected,可以使用 getAttribute 获取
* selected:选项是否被选中
*/
option = new Option(text, value, defaultSelected, selected);
表单事件
submit
提交表单时触发,具体条件如下
- 点击
<input type="submit">
或<input type="image">
时触发 - 在
input
字段中按下Enter
键时触发- 会在
<input type="submit">
(如果有的话)上触发一次click
事件
- 会在
<form onsubmit="return false">
<input type="text" size="30" value="Focus here and press enter">
<input type="submit" value="Submit" onclick="alert('click')">
</form>
// 主动触发,直接提交表单
form.submit()
focus
聚焦元素时触发,当用户点击某个元素或使用键盘上的 Tab 键选中时,该元素将会获得聚焦
可以通过
document.activeElement
来获取当前所聚焦的元素
// 监听事件
elem.onfocus = function(){}
// 主动触发
elem.focus()
blur
元素失去焦点时触发,可能发生在用户点击页面的其它地方,或者按下 Tab 键跳转到下一个表单字段,亦或是其它途径的时候
// 监听事件
elem.onblur = function(){}
// 主动触发
elem.onblur()
change
当元素更改完成时,将触发
change
事件
- 对于文本输入框,当其失去焦点时,就会触发
change
事件,但是键入内容时不会触发change
事件 - 对于其它元素:
select
,input type=checkbox/radio
,会在选项更改后立即触发change
事件
input
用户对输入值进行修改后,(只要值改变了)就会触发
input
事件
- 当输入值更改后,就会触发
input
事件,无法使用event.preventDefault()
cut/copy/paste
事件发生于剪切/拷贝/粘贴一个值的时候
- 属于
ClipboardEvent
类,并提供了对剪切/拷贝/粘贴的数据的访问方法 - 在剪切/复制事件处理程序中调用
event.clipboardData.getData(...)
只会得到一个空字符串,因为此时数据还未存入剪切板- 可以使用
event.preventDefault()
来中止行为,什么都不会被复制/粘贴
- 可以使用
<input type="text" id="input">
<script>
input.onpaste = function(event) {
alert("paste: " + event.clipboardData.getData('text/plain'));
event.preventDefault();
};
input.oncut = input.oncopy = function(event) {
alert(event.type + '-' + document.getSelection());
event.preventDefault();
};
</script>
注意
focus/blur事件委托
方法一:两个事件均不会向上冒泡,但会在捕获阶段向下传播
<form id="form">
<input type="text" name="name" value="Name">
<input type="text" name="surname" value="Surname">
</form>
<style> .focused { outline: 1px solid red; } </style>
<script>
// 将处理程序置于捕获阶段(最后一个参数为 true)
form.addEventListener("focus", () => form.classList.add('focused'), true);
form.addEventListener("blur", () => form.classList.remove('focused'), true);
</script>
方法二:使用
focusin
和focusout
事件,与focus/blur
事件完全一样,只是它们会冒泡
<form id="form">
<input type="text" name="name" value="Name">
<input type="text" name="surname" value="Surname">
</form>
<style> .focused { outline: 1px solid red; } </style>
<script>
form.addEventListener("focusin", () => form.classList.add('focused'));
form.addEventListener("focusout", () => form.classList.remove('focused'));
</script>
例子
可编辑的 div
点击 div 变成文本框来进行编辑
按 Enter 键或者通过 blur 来保存结果变回 div
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style>
.view,
.edit {
height: 150px;
width: 400px;
font-family: sans-serif;
font-size: 14px;
display: block;
}
.view {
/* padding + border = 3px */
padding: 2px;
border: 1px solid black;
}
.edit {
/* replace padding with border (still 3px not to shift the contents) */
border: 3px solid blue;
padding: 0px;
}
.edit:focus {
/* remove focus border in Safari */
outline: none;
}
</style>
</head>
<body>
<div id="view" class="view">Text</div>
<script>
let area = null;
let view = document.getElementById('view');
view.onclick = function() {
editStart();
};
function editStart() {
area = document.createElement('textarea');
area.className = 'edit';
area.value = view.innerHTML;
area.onkeydown = function(event) {
if (event.key == 'Enter') {
this.blur();
}
};
area.onblur = function() {
editEnd();
};
view.replaceWith(area);
area.focus();
}
function editEnd() {
view.innerHTML = area.value;
area.replaceWith(view);
}
</script>
</body>
</html>
模态框
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#prompt-form {
display: inline-block;
padding: 5px 5px 5px 70px;
width: 200px;
border: 1px solid black;
background: white url(https://en.js.cx/clipart/prompt.png) no-repeat left 5px;
vertical-align: middle;
}
#prompt-form-container {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
display: none;
width: 100%;
height: 100%;
text-align: center;
}
#prompt-form-container:before {
display: inline-block;
height: 100%;
content: '';
vertical-align: middle;
}
#cover-div {
position: fixed;
top: 0;
left: 0;
z-index: 9000;
width: 100%;
height: 100%;
background-color: gray;
opacity: 0.3;
}
#prompt-form input[name="text"] {
display: block;
margin: 5px;
width: 180px;
}
</style>
</head>
<body style="height:3000px">
<h2>Click the button below</h2>
<input type="button" value="Click to show the form" id="show-button">
<div id="prompt-form-container">
<form id="prompt-form">
<div id="prompt-message"></div>
<input name="text" type="text">
<input type="submit" value="Ok">
<input type="button" name="cancel" value="Cancel">
</form>
</div>
<script>
// Show a half-transparent DIV to "shadow" the page
// (the form is not inside, but near it, because it shouldn't be half-transparent)
function showCover() {
let coverDiv = document.createElement('div');
coverDiv.id = 'cover-div';
// make the page unscrollable while the modal form is open
document.body.style.overflowY = 'hidden';
document.body.append(coverDiv);
}
function hideCover() {
document.getElementById('cover-div').remove();
document.body.style.overflowY = '';
}
function showPrompt(text, callback) {
showCover();
let form = document.getElementById('prompt-form');
let container = document.getElementById('prompt-form-container');
document.getElementById('prompt-message').innerHTML = text;
form.text.value = '';
function complete(value) {
hideCover();
container.style.display = 'none';
document.onkeydown = null;
callback(value);
}
form.onsubmit = function() {
let value = form.text.value;
if (value == '') return false; // ignore empty submit
complete(value);
return false;
};
form.cancel.onclick = function() {
complete(null);
};
document.onkeydown = function(e) {
if (e.key == 'Escape') {
complete(null);
}
};
let lastElem = form.elements[form.elements.length - 1];
let firstElem = form.elements[0];
lastElem.onkeydown = function(e) {
if (e.key == 'Tab' && !e.shiftKey) {
firstElem.focus();
return false;
}
};
firstElem.onkeydown = function(e) {
if (e.key == 'Tab' && e.shiftKey) {
lastElem.focus();
return false;
}
};
container.style.display = 'block';
form.elements.text.focus();
}
document.getElementById('show-button').onclick = function() {
showPrompt("Enter something<br>...smart :)", function(value) {
alert("You entered: " + value);
});
};
</script>
</body>
</html>