4.1 Web表单核心
4.1.1 表单概述
4.1.2 第一个表单
4.1.2.1 表单定义
- HTML Form 是用户和web站点交互的主要内容之一。
- 表单由一个或多个小部件组成,类似其他语言的可视化控件。
4.1.2.2 设计表单
构建一个简单的联系人表单。
4.1.2.3 实现表单
为了实现上述表单,需要使用以下HTML element
4.1.2.4 基本表单样式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Your first HTML form</title>
<style>
form {
/* 居中表单 */
margin: 0 auto;
width: 400px;
/* 显示表单的轮廓 */
padding: 1em;
border: 1px solid #CCC;
border-radius: 1em;
}
ul {
list-style: none;
padding: 0;
margin: 0;
}
form li+li {
margin-top: 1em;
}
label {
/* 确保所有label大小相同并正确对齐 */
display: inline-block;
width: 90px;
text-align: right;
}
input,
textarea {
/* 确保所有文本输入框字体相同
textarea默认是等宽字体 */
font: 1em sans-serif;
/* 使所有文本输入框大小相同 */
width: 300px;
box-sizing: border-box;
/* 调整文本输入框的边框样式 */
border: 1px solid #999;
}
input:focus,
textarea:focus {
/* 给激活的元素一点高亮效果 */
border-color: #000;
}
textarea {
/* 使多行文本输入框和它们的label正确对齐 */
vertical-align: top;
/* 给文本留下足够的空间 */
height: 5em;
}
.button {
/* 把按钮放到和文本输入框一样的位置 */
padding-left: 90px;
/* 和label的大小一样 */
}
button {
/* 这个外边距的大小与label和文本输入框之间的间距差不多 */
margin-left: .5em;
}
</style>
</head>
<body>
<form action="/my-handling-form-page" method="post">
<ul>
<li>
<label for="name">Name:</label>
<input type="text" id="name" name="user_name" />
</li>
<li>
<label for="mail">E-mail:</label>
<input type="email" id="mail" name="user_mail" />
</li>
<li>
<label for="msg">Message:</label>
<textarea id="msg" name="user_message"></textarea>
</li>
<li class="button">
<button type="submit">Send your message</button>
</li>
</ul>
</form>
</body>
</html>
|
4.1.2.5 发送数据
4.1.3 构造表单
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Payment form example</title>
<style>
h1 {
margin-top: 0;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
form {
margin: 0 auto;
width: 400px;
padding: 1em;
border: 1px solid #CCC;
border-radius: 1em;
}
div+div {
margin-top: 1em;
}
label span {
display: inline-block;
width: 120px;
text-align: right;
}
input,
textarea {
font: 1em sans-serif;
width: 250px;
box-sizing: border-box;
border: 1px solid #999;
}
input[type=checkbox],
input[type=radio] {
width: auto;
border: none;
}
input:focus,
textarea:focus {
border-color: #000;
}
textarea {
vertical-align: top;
height: 5em;
resize: vertical;
}
fieldset {
width: 250px;
box-sizing: border-box;
margin-left: 136px;
border: 1px solid #999;
}
button {
margin: 20px 0 0 124px;
}
label {
position: relative;
}
label em {
position: absolute;
right: 5px;
top: 20px;
}
</style>
</head>
<body>
<form method="post">
<h1>Payment form</h1>
<p>Required fields are followed by <strong><abbr title="required">*</abbr></strong>.</p>
<section>
<h2>Contact information</h2>
<fieldset>
<legend>Title</legend>
<ul>
<li>
<label for="title_1">
<input type="radio" id="title_1" name="title" value="A">
Ace
</label>
</li>
<li>
<label for="title_2">
<input type="radio" id="title_2" name="title" value="K">
King
</label>
</li>
<li>
<label for="title_3">
<input type="radio" id="title_3" name="title" value="Q">
Queen
</label>
</li>
</ul>
</fieldset>
<p>
<label for="name">
<span>Name: </span>
<strong><abbr title="required">*</abbr></strong>
</label>
<input type="text" id="name" name="username">
</p>
<p>
<label for="mail">
<span>E-mail: </span>
<strong><abbr title="required">*</abbr></strong>
</label>
<input type="email" id="mail" name="usermail">
</p>
<p>
<label for="pwd">
<span>Password: </span>
<strong><abbr title="required">*</abbr></strong>
</label>
<input type="password" id="pwd" name="password">
</p>
</section>
<section>
<h2>Payment information</h2>
<p>
<label for="card">
<span>Card type:</span>
</label>
<select id="card" name="usercard">
<option value="visa">Visa</option>
<option value="mc">Mastercard</option>
<option value="amex">American Express</option>
</select>
</p>
<p>
<label for="number">
<span>Card number:</span>
<strong><abbr title="required">*</abbr></strong>
</label>
<input type="tel" id="number" name="cardnumber">
</p>
<p>
<label for="date">
<span>Expiration date:</span>
<strong><abbr title="required">*</abbr></strong>
<em>formatted as mm/dd/yyyy</em>
</label>
<input type="date" id="date" name="expiration">
</p>
</section>
<section>
<p> <button type="submit">Validate the payment</button> </p>
</section>
</form>
</body>
</html>
|
4.1.4 表单控件
4.1.4.1 通用属性
- autofocus(false) 文档中只有一个与表单相关的元素可以指定具有输入焦点。
- disabled(false) 用户不能与元素交互。
- form
- name
- value
4.1.4.2 文本输入
https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/Input
- 通用属性
- readonly
- placeholder
- size
- 单行文本框
<input type="text" id="comment" name="comment" value="I'm a text field">
- Email地址框
<input type="email" id="email" name="email" multiple>
- 密码框
<input type="password" id="pswd" name="pswd">
- 搜索框
<input type="search" id="search" name="search">
- 电话号码
<input type="tel" id="tel" name="tel">
- URL
<input type="url" id="url" name="url">
- 多行文本框
<textarea cols="30" rows="10"></textarea>
4.1.4.3 下拉内容
https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/select
1
2
3
4
5
6
7
8
9
10
11
12
|
<select id="groups" name="groups">
<optgroup label="fruits">
<option>Banana</option>
<option selected>Cherry</option>
<option>Lemon</option>
</optgroup>
<optgroup label= "vagetables">
<option>Carrot</option>
<option>Eggplant</option>
<option>Potato</option>
</optgroup>
</select>
|
1
2
3
4
5
|
<select multiple id="multi" name="multi">
<option>Banana</option>
<option>Cherry</option>
<option>Lemon</option>
</select>
|
1
2
3
4
5
6
7
8
9
10
11
12
|
<label for="myFruit">What's your favorite fruit?</label>
<input type="text" name="myFruit" id="myFruit" list="mySuggestion">
<datalist id="mySuggestion">
<option>Apple</option>
<option>Banana</option>
<option>Blackberry</option>
<option>Blueberry</option>
<option>Lemon</option>
<option>Lychee</option>
<option>Peach</option>
<option>Pear</option>
</datalist>
|
4.1.4.4 可选中项
4.1.4.5 按钮
4.1.4.6 高级表单部件
- 数字
<input type="number" name="age" id="age" min="1" max="10" step="2">
-滑块
<input type="range" name="beans" id="beans" min="0" max="500" step="10">
4.1.4.7 其他小部件
- 文件选择器
<input type="file" name="file" id="file" accept="image/*" multiple>
- 隐藏内容
<input type="hidden" id="timestamp" name="timestamp" value="1286705410">
- 图像按钮
<input type="image" alt="Click me!" src="my-img.png" width="80" height="30" />
- 仪表和进度条
- 进度条
<progress max="100" value="75">75/100</progress>
- 仪表
<meter min="0" max="100" value="75" low="33" high="66" optimum="50">75</meter>
4.1.5 HTML5的表单
4.1.6 其他表单
4.1.7 样式化表单
4.1.7.1 基本样式美化
1
2
3
4
5
|
input[type=search]{
border: 1px dotted #999;
border-radius: 0;
-webkit-appearance: none;
}
|
1
2
3
|
<form>
<input type="search">
</form>
|
1
2
3
4
|
button, input, select, textarea{
font-family: inherit;
font-size: 100%;
}
|
1
2
3
4
5
6
7
8
|
button, input, select, textarea{
width: 150px;
margin: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
<style>
legend {
width: 1px;
height: 1px;
overflow: hidden;
}
</style>
<fieldset>
<legend>hi</legend>
<h1>hello</h1>
</fieldset>
|
1
2
3
|
textarea {
vertical-align: top;
}
|
4.1.7.2 实际案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Postcard example</title>
<style>
@font-face {
font-family: 'handwriting';
src: url('fonts/journal-webfont.woff2') format('woff2'),
url('fonts/journal-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'typewriter';
src: url('fonts/veteran_typewriter-webfont.woff2') format('woff2'),
url('fonts/veteran_typewriter-webfont.woff') format('woff');
font-weight: normal;
font-style: normal;
}
body {
font: 1.3rem sans-serif;
padding: 0.5em;
margin: 0;
background: #222;
}
form {
position: relative;
width: 740px;
height: 498px;
margin: 0 auto;
padding: 1em;
box-sizing: border-box;
background: #FFF url(background.jpg);
/* we create our grid */
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: 10em 1em 1em 1em;
}
h1 {
font: 1em "typewriter", monospace;
align-self: end;
}
#message {
grid-row: 1 / 5;
}
#from,
#reply {
display: flex;
}
label {
font: .8em "typewriter", sans-serif;
}
input,
textarea {
font: 1.4em/1.5em "handwriting", cursive, sans-serif;
border: none;
padding: 0 10px;
margin: 0;
width: 80%;
background: none;
}
input:focus,
textarea:focus {
background: rgba(0, 0, 0, .1);
border-radius: 5px;
}
textarea {
display: block;
padding: 10px;
margin: 10px 0 0 -10px;
width: 100%;
height: 90%;
border-right: 1px solid;
/* resize : none; */
overflow: auto;
}
button {
padding: 5px;
font: bold .6em sans-serif;
border: 2px solid #333;
border-radius: 5px;
background: none;
cursor: pointer;
transform: rotate(-1.5deg);
}
button:after {
content: " >>>";
}
button:hover,
button:focus {
outline: none;
background: #000;
color: #FFF;
}
</style>
</head>
<body>
<form>
<h1>to: Mozilla</h1>
<div id="from">
<label for="name">from:</label>
<input type="text" id="name" name="user_name">
</div>
<div id="reply">
<label for="mail">reply:</label>
<input type="email" id="mail" name="user_email">
</div>
<div id="message">
<label for="msg">Your message:</label>
<textarea id="msg" name="user_message"></textarea>
</div>
<div class="button">
<button type="submit">Send your message</button>
</div>
</form>
</body>
</html>
|
4.1.8 高级样式表单
4.1.8.1 CSS表现力
-
CSS 2.1
-
CSS Selector Level 3
- :enabled
- :disabled
- :checked
- :indeterminate
-
CSS Basic UI Level 3
- :default
- :valid
- :invalid
- :in-range
- :out-of-range
- :required
- :optional
- :read-only
- :read-write
-
CSS Selector Level 4
-
Mozilla CSS
- :-moz-placeholder
- :-moz-submit-invalid
- :-moz-ui-invalid
- :-moz-ui-valid
-
WebKit CSS
- ::-webkit-input-placeholder
- others
-
Microsoft CSS
4.1.8.2 案例
4.1.9 UI伪类
4.1.10 客户端表单验证
4.1.10.1 什么是表单数据校验
4.1.10.2 HTML5内置表单校验
- Input元素的校校验
- Input元素required属性
- 正则表达式校验
- 限制输入长度maxlength/minlength
- 自定义错误信息(javascript)
4.1.10.3 JavaScript校验表单
- 支持约束校验API的表单元素
- 约束校验API的属性
- validationMessage
- validity
- validity.customError
- validity.patternMismatch
- validity.rageOverflow
- validity.rageUnderflow
- validity.stepMismatch
- validity.tooLong
- validity.typeMismatch
- validity.valid
- validity.valueMissing
- willValidate
- 约束校验API的方法
- checkValidity()
- HTMLFormElement.reportValidity()
- setCustomValidity(message)
- 使用约束校验API的例子
4.1.11 发送表单数据
https://developer.mozilla.org/zh-CN/docs/Learn/Forms/Sending_and_retrieving_form_data
4.1.11.1 数据都去那儿了
- 客户端/服务器体系结构
- 客户端定义如何发送数据
- 服务端如何检索数据
4.1.11.2 发送文件
- method get
- enctype multipart/form-data
4.1.11.3 安全问题
-
XSS CSRF
-
SQL 注入
-
HTPP数据头注入
-
电子邮件注入
4.2 Web表单进阶
4.2.1 构造自定义表单控件
4.2.1.1 设计、结构、和语义
4.2.1.2 通过JavaScript让您的小部件动起来
- 为什么不生效
- 浏览器关掉了JavaScript
- 脚本没有加载
- 脚本出现问题
- 脚本与浏览器的扩展冲突
- 浏览器老旧不支持新功能
- 让工作更简单
- classList
- addEventListener
- forEach
- querySelector
- querySelectorAll
- 构造事件回调
- 处理组件的值
4.2.1.3 可访问性
4.2.2 使用Javascript发送表单
4.2.2.1 表单不总是表单
4.2.2.2 发送表单数据
- 构建XMLHttpRequest
- FormDATA Object
- 使用FormData对象
- 使用绑定到表单元素上的FormData
- 在隐藏的iframe中构建DOM
4.2.2.3 处理二进制
4.2.3 表单组件兼容性列表
4.2.3.1 如何阅读表格
4.2.3.2 兼容性表格