在DOM 之前,从一个选择框向另一个选择框移动选项是非常麻烦的,要先从第一个选择框移除选
项,然后以相同文本和值创建新选项,再将新选项添加到第二个选择框。DOM 方法则可以直接将某个
选项从第一个选择框移动到第二个选择框,只要对相应选项使用appendChild()方法即可。如果给这
个方法传入文档中已有的元素,则该元素会先从其父元素中移除,然后再插入指定位置。例如,下面的
代码会从选择框中移除第一项并插入另一个选择框:
let selectbox1 = document.getElementById(“selLocations1”);
let selectbox2 = document.getElementById(“selLocations2”);
selectbox2.appendChild(selectbox1.options[0]);
移动选项和移除选项都会导致每个选项的index 属性重置。
重排选项非常类似,DOM 方法同样是最佳途径。要将选项移动到选择框中的特定位置,
insertBefore()方法是最合适的。不过,要把选项移动到最后,还是appendChild()方法比较方便。
下面的代码演示了将一个选项在选择框中前移一个位置:
let optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove,
selectbox.options[optionToMove.index-1]);
这个例子首先获得要移动选项的索引,然后将其插入之前位于它前面的选项之前,其中第二行代码
适用于除第一个选项之外的所有选项。下面的代码则可以将选项向下移动一个位置:
let optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove,
selectbox.options[optionToMove.index+2]);
以上代码适用于选择框中的所有选项,包括最后一个。
表单序列化
随着Ajax(第21 章会进一步讨论)的崭露头角,表单序列化(form serialization)已经成为一个常
见需求。表单在JavaScript 中可以使用表单字段的type 属性连同其name 属性和value 属性来进行序
列化。在写代码之前,我们需要理解浏览器如何确定在提交表单时要把什么发送到服务器。
字段名和值是URL 编码的并以和号(&)分隔。
禁用字段不会发送。
复选框或单选按钮只在被选中时才发送。
类型为"reset"或"button"的按钮不会发送。
多选字段的每个选中项都有一个值。
通过点击提交按钮提交表单时,会发送该提交按钮;否则,不会发送提交按钮。类型为"image"
的元素视同提交按钮。
元素的值是被选中元素的value 属性。如果元素没有value 属
性,则该值是它的文本。
表单序列化通常不包含任何按钮,因为序列化得到的字符串很可能以其他方式提交。除此之外其他
规则都应该遵循。最终完成表单序列化的代码如下:
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(‘
e
n
c
o
d
e
U
R
I
C
o
m
p
o
n
e
n
t
(
f
i
e
l
d
.
n
a
m
e
)
=
′
+
′
{encodeURIComponent(field.name)}=' + '
encodeURIComponent(field.name)=′+′{encodeURIComponent(field.value)}’);
}
}
return parts.join(“&”);
}
这个serialize()函数一开始定义了一个名为parts 的数组,用于保存要创建字符串的各个部分。
接下来通过for 循环迭代每个表单字段,将字段保存在field 变量中。获得一个字段的引用后,再通
过switch 语句检测其type 属性。最麻烦的是序列化元素,包括单选和多选两种模式。在
遍历选择框的每个选项时,只要有选项被选中,就将其添加到结果字符串。单选控件只会有一个选项被
选中,多选控件则可能有零或多个选项被选中。同样的代码适用于两种选择类型,因为浏览器会限制可
选项的数量。找到选中项时,需要确定使用哪个值。如果不存在value 属性,则应该以选项文本代替,
不过value 属性为空字符串是完全有效的。为此需要使用DOM 合规的浏览器支持的hasAttribute()方法,而在IE8 及更早版本中要使用值的specified 属性。
表单中如果有元素,它就会出现在元素集合中,但应该没有type 属性。因此,如果
type 属性是undefined,则不必纳入序列化。各种类型的按钮以及文件输入字段也是如此。(文件输
入字段在提交表单时包含文件的内容,但这些字段通常无法转换,因而也要排除在序列化之外。)对于
单选按钮和复选框,会检测其checked 属性。如果值为false 就退出switch 语句;如果值为true,
则继续执行default 分支,将字段的名和值编码后添加到parts 数组。注意,所有没有名字的表单字
段都不会包含在序列化结果中以模拟浏览器的表单提交行为。这个函数的最后一步是使用join()通过
和号把所有字段的名值对拼接起来。
serialize()函数返回的结果是查询字符串格式。如果想要返回其他格式,修改起来也很简单。
javascript基础从小白到高手系列一千七百六十六:移动和重排选项
最新推荐文章于 2024-09-04 11:57:55 发布