JS之表单脚本

一、表单基础知识

在 JavaScript 中,表单对应的是 HTMLFormElement 类型。 HTMLFormElement 继承了 HTMLElement ,因而与其他 HTML 元素具有相同的默认属性。

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> 元素引用的方式有好几种。
其中最常见的方式就是将它看成与其他元素一样,并为其添加 id 特性,然后再像下面这样使用 getElementById() 方法找到它。

var form = document.getElementById("form1");

其次,通过 document.forms 可以取得页面中所有的表单。在这个集合中,可以通过数值索引或name 值来取得特定的表单。

var firstForm = document.forms[0]; //取得页面中的第一个表单
var myForm = document.forms["form2"]; //取得页面中名称为"form2"的表单

1、提交表单

用户单击提交按钮或图像按钮时,就会提交表单。使用 <input> 或 <button> 都可以定义提交按钮,只要将其 type 特性的值设置为 "submit" 即可,而图像按钮则是通过将 <input> 的 type 特性值设置为"image" 来定义的。因此,只要我们单击以下代码生成的按钮,就可以提交表单。

<!-- 通用提交按钮 -->
<input type="submit" value="Submit Form">
<!-- 自定义提交按钮 -->
<button type="submit">Submit Form</button>
<!-- 图像按钮 -->
<input type="image" src="graphic.gif">

以这种方式提交表单时,浏览器会在将请求发送给服务器之前触发 submit 事件。这样,我们就有机会验证表单数据,并据以决定是否允许表单提交。阻止这个事件的默认行为就可以取消表单提交。

var form = document.getElementById("myForm");
EventUtil.addHandler(form, "submit", function(event){
    //取得事件对象
    event = EventUtil.getEvent(event);
    //阻止默认事件
    EventUtil.preventDefault(event);
});

在 JavaScript 中,以编程方式调用 submit() 方法也可以提交表单。而且,这种方式无需表单包含提交按钮,任何时候都可以正常提交表单。

var form = document.getElementById("myForm");
// 提交表单
form.submit();

以调用 submit() 方法的形式提交表单时,不会触发 submit 事件,因此要记得在调用此方法之前先验证表单数据。

解决重复提交表单的办法有两个:在第一次提交表单后就禁用提交按钮,或者利用 onsubmit 事件处理程序取消后续的表单提交操作。

2、重置表单

在用户单击重置按钮时,表单会被重置。使用 type 特性值为 "reset" 的 <input> 或 <button> 都可以创建重置按钮:

<!-- 通用重置按钮 -->
<input type="reset" value="Reset Form">
<!-- 自定义重置按钮 -->
<button type="reset">Reset Form</button>

在重置表单时,所有表单字段都会恢复到页面刚加载完毕时的初始值。如果某个字段的初始值为空,就会恢复为空;而带有默认值的字段,也会恢复为默认值。

用户单击重置按钮重置表单时,会触发 reset 事件。以在必要时取消重置
操作。

var form = document.getElementById("myForm");
EventUtil.addHandler(form, "reset", function(event){
    //取得事件对象
    event = EventUtil.getEvent(event);
    //阻止表单重置
    EventUtil.preventDefault(event);
});

也可以通过 JavaScript 来重置表单:

var form = document.getElementById("myForm");
// 重置表单
form.reset();

调用 reset() 方法会像单击重置按钮一样触发 reset 事件。

提示:事实上,重置表单的需求是很少见的。更常见的做法是提供一个取消按钮,让用户能够回到前一个页面,而不是不分青红皂白地重置表单中的所有值。

3、表单字段

每个表单都有elements 属性,该属性是表单中所有表单元素(字段)的集合。这个 elements 集合是一个有序列表,其中包含着表单中的所有字段,例如 <input> 、 <textarea> 、 <button> 和 <fieldset> 。每个表单字段在 elements 集合中的顺序,与它们出现在标记中的顺序相同,可以按照位置和 name 特性来访问它们。

var form = document.getElementById("form1");
//取得表单中的第一个字段
var field1 = form.elements[0];
//取得名为"textbox1"的字段
var field2 = form.elements["textbox1"];
//取得表单中包含的字段的数量
var fieldCount = form.elements.length;

如果有多个表单控件都在使用一个 name (如单选按钮),那么就会返回以该 name 命名的一个NodeList 。

<form method="post" id="myForm">
        <ul>
            <li>
                <input type="radio" name="color" value="red">Red
            </li>
            <li>
                <input type="radio" name="color" value="green">Green
            </li>
            <li>
                <input type="radio" name="color" value="blue">Blue
            </li>
        </ul>
</form>

var form = document.getElementById("myForm");
var colorFields = form.elements["color"];
alert(colorFields.length); //3

var firstColorField = colorFields[0];
var firstFormField = form.elements[0];
alert(firstColorField === firstFormField); //true

如果访问elements[0] ,则只会返回第一个元素。应尽可能使用 elements 。

(1)共有的表单字段属性

除了 <fieldset> 元素之外,所有表单字段都拥有相同的一组属性。由于 <input> 类型可以表示多种表单字段,因此有些属性只适用于某些字段,但还有一些属性是所有字段所共有的。

共有属性:

  • disabled :布尔值,表示当前字段是否被禁用。
  • form :指向当前字段所属表单的指针;只读。
  • name :当前字段的名称。
  • readOnly :布尔值,表示当前字段是否只读。
  • tabIndex :表示当前字段的切换(tab)序号。
  • type :当前字段的类型,如 "checkbox" 、 "radio" ,等等。
  • value :当前字段将被提交给服务器的值。对文件字段来说,这个属性是只读的,包含着文件在计算机中的路径。

除了 form 属性之外,可以通过 JavaScript 动态修改其他任何属性。

var form = document.getElementById("myForm");
var field = form.elements[0];
//修改 value 属性
field.value = "Another value";
//检查 form 属性的值
alert(field.form === form); //true
//把焦点设置到当前字段
field.focus();
//禁用当前字段
field.disabled = true;
//修改 type 属性(不推荐,但对<input>来说是可行的)
field.type = "checkbox";

侦听 submit 事件,并在该事件发生时禁用提交按钮。

//避免多次提交表单
EventUtil.addHandler(form, "submit", function(event) {
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    //取得提交按钮
    var btn = target.elements["submit-btn"];
    //禁用它
    btn.disabled = true;
});

注意,不能通过 onclick 事件处理程序来实现这个功能,原
因是不同浏览器之间存在“时差”:有的浏览器会在触发表单的 submit 事件之前触发 click 事件,而有的浏览器则相反。对于先触发 click 事件的浏览器,意味着会在提交发生之前禁用按钮,结果永远都不会提交表单。因此,最好是通过 submit 事件来禁用提交按钮。不过,这种方式不适合表单中不包含提交按钮的情况;如前所述,只有在包含提交按钮的情况下,才有可能触发表单的 submit事件。

(2)共有的表单字段方法

每个表单字段都有两个方法: focus() 和 blur() 。 focus() 方法用于将浏览器的焦点设置到表单字段,即激活表单字段,使其可以响应键盘事件。

EventUtil.addHandler(window, "load", function(event){
    document.forms[0].elements[0].focus();
});

HTML5 为表单字段新增了一个 autofocus 属性。在支持这个属性的浏览器中,只要设置这个属性,不用 JavaScript 就能自动把焦点移动到相应字段。

<input type="text" autofocus>

为了保证前面的代码在设置 autofocus 的浏览器中正常运行,必须先检测是否设置了该属性:

EventUtil.addHandler(window, "load", function(event) {
    var element = document.forms[0].elements[0];
    if (element.autofocus !== true) {
        element.focus();
        console.log("JS focus");
    }
});

与 focus() 方法相对的是 blur() 方法,它的作用是从元素中移走焦点。在调用 blur() 方法时,并不会把焦点转移到某个特定的元素上;仅仅是将焦点从调用这个方法的元素上面移走而已。

document.forms[0].elements[0].blur();

(3)共有的表单字段事件

除了支持鼠标、键盘、更改和 HTML 事件之外,所有表单字段都支持下列 3 个事件。

  • blur :当前字段失去焦点时触发。
  • change :对于 <input> 和 <textarea> 元素,在它们失去焦点且 value 值改变时触发;对于<select> 元素,在其选项改变时触发。
  • focus :当前字段获得焦点时触发。

对于 <input> 和 <textarea> 元素,当它们从获得焦点到失去焦点且 value 值改变时,才会触发 change 事件。对于 <select> 元素,只要用户选择了不同的选项,就会触发 change 事件; change 事件经常用于验证用户在字段中输入的数据。

假设有一个文本框,我们只允许用户输入数值。此时,可以利用focus 事件修改文本框的背景颜色,以便更清楚地表明这个字段获得了焦点。可以利用 blur 事件恢复文本框的背景颜色,利用 change 事件在用户输入了非数值字符时再次修改背景颜色。

var textbox = document.forms[0].elements[0];
EventUtil.addHandler(textbox, "focus", function(event) {
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    if (target.style.backgroundColor != "red") {
        target.style.backgroundColor = "yellow";
    }
});
EventUtil.addHandler(textbox, "blur", function(event) {
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    if (/[^\d]/.test(target.value)) {
        target.style.backgroundColor = "red";
    } else {
        target.style.backgroundColor = "";
    }
});
EventUtil.addHandler(textbox, "change", function(event) {
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    if (/[^\d]/.test(target.value)) {
        target.style.backgroundColor = "red";
    } else {
        target.style.backgroundColor = "";
    }
});

二、文本框脚本

在 HTML 中,有两种方式来表现文本框:一种是使用 <input> 元素的单行文本框,另一种是使用<textarea> 的多行文本框。

要表现文本框,必须将 <input> 元素的 type 特性设置为 "text" 。而通过设置 size 特性,可以指定文本框中能够显示的字符数。通过 value 特性,可以设置文本框的初始值,而 maxlength 特性则用于指定文本框可以接受的最大字符数。

能够显示 25 个字符,但输入不能超过 50 个字符的文本框。

<input type="text" size="25" maxlength="50" value="initial value">

<textarea> 元素始终会呈现为一个多行文本框。要指定文本框的大小,可以使用 rows和 cols 特性。其中, rows 特性指定的是文本框的字符行数,而 cols 特性指定的是文本框的字符列数。

与 <input> 元素不同, <textarea> 的初始值必须要放在<textarea> 和 </textarea> 之间:

<textarea rows="25" cols="5">initial value</textarea>

另一个与 <input> 的区别在于,不能在 HTML 中给 <textarea> 指定最大字符数。

无论这两种文本框在标记中有什么区别,但它们都会将用户输入的内容保存在 value 属性中。可以通过这个属性读取和设置文本框的值:

var textbox = document.forms[0].elements["textbox1"];
alert(textbox.value);
textbox.value = "Some new value";

1、选择文本

select() 方法用于选择文本框中的所有文本。在调用 select()方法时,大多数浏览器(Opera 除外)都会将焦点设置到文本框中。这个方法不接受参数,可以在任何时候被调用。

var textbox = document.forms[0].elements["textbox1"];
textbox.select();

只要文本框获得焦点,就会选择其中所有的文本。

EventUtil.addHandler(textbox, "focus", function(event) {
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    target.select();
});

(1)选择( select )事件

与 select() 方法对应的,是一个 select 事件。在选择了文本框中的文本时,就会触发 select事件。

var textbox = document.forms[0].elements["textbox1"];
EventUtil.addHandler(textbox, "select", function(event){
    var alert("Text selected" + textbox.value);
});

(2)取得选择的文本

HTML5添加了两个属性: selectionStart 和 selectionEnd 。这两个属性中保存的是基于 0 的数值,表示所选择文本的范围(即文本选区开头和结尾的偏移量)。

要取得用户在文本框中选择的文本:

function getSelectedText(textbox){
    return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd);
}

因 为 substring() 方 法 基 于 字 符 串 的 偏 移 量 执 行 操 作 , 所 以 将 selectionStart 和selectionEnd 直接传给它就可以取得选中的文本。

(3)选择部分文本

所有文本框都有一个 setSelectionRange()方法。这个方法接收两个参数:要选择的第一个字符的索引和要选择的最后一个字符之后的字符的索引(类似于 substring() 方法的两个参数)。

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"

要看到选择的文本,必须在调用 setSelectionRange() 之前或之后立即将焦点设置到文本框。

跨浏览器解决方案:

function selectText(textbox, startIndex, stopIndex) {
    if (textbox.setSelectionRange) {
        textbox.setSelectionRange(startIndex, stopIndex);
    } else if (textbox.createTextRange) {
        var range = textbox.createTextRange();
        range.collapse(true);
        range.moveStart("character", startIndex);
        range.moveEnd("character", stopIndex - startIndex);
        range.select();
    }
     //必须让文本框获得焦点
    textbox.focus();
}

selectText() 函数接收三个参数:要操作的文本框、要选择文本中第一个字符的索引和要选择文本中最后一个字符之后的索引。

使用 selectText() 方法。

textbox.value = "Hello world!"
//选择所有文本
selectText(textbox, 0, textbox.value.length); //"Hello world!"
//选择前 3 个字符
selectText(textbox, 0, 3); //"Hel"
//选择第 4 到第 6 个字符
selectText(textbox, 4, 7); //"o w"

选择部分文本的技术在实现高级文本输入框时很有用,例如提供自动完成建议的文本框就可以使用这种技术。

2、过滤输入

我们经常会要求用户在文本框中输入特定的数据,或者输入特定格式的数据。

(1)屏蔽字符

有时候,我们需要用户输入的文本中包含或不包含某些字符。例如,电话号码中不能包含非数值字符。

下列代码只允许用户输入数值。

EventUtil.addHandler(textbox, "keypress", function(event) {
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    var charCode = EventUtil.getCharCode(event);
    if (!/\d/.test(String.fromCharCode(charCode))) {
        EventUtil.preventDefault(event);
    }
});

使用 EventUtil.getCharCode() 实现了跨浏览器取得字符编码。然后,使
用 String.fromCharCode() 将字符编码转换成字符串,再使用正则表达式 /\d/ 来测试该字符串,从而确定用户输入的是不是数值。如果测试失败,那么就使用 EventUtil.preventDefault() 屏蔽按键事件。结果,文本框就会忽略所有输入的非数值。

为了让代码更通用,只要不屏蔽那些字符编码小于 10 的键即可。

EventUtil.addHandler(textbox, "keypress", function(event) {
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    var charCode = EventUtil.getCharCode(event);
    if (!/\d/.test(String.fromCharCode(charCode)) && charCode > 9) {
        EventUtil.preventDefault(event);
    }
});

还要添加一个检测条件,以确保用户没有按下 Ctrl 键。

EventUtil.addHandler(textbox, "keypress", function(event) {
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    var charCode = EventUtil.getCharCode(event);
    if (!/\d/.test(String.fromCharCode(charCode)) && charCode > 9 &&
        !event.ctrlKey) {
        EventUtil.preventDefault(event);
    }
});

3、自动切换焦点

在用户填写完当前字段时,自动将焦点切换到下一个字段。在自动切换焦点之前,必须知道用户已经输入了既定长度的数据。

4、HTML5约束验证API

只有在某些情况下表单字段才能进行自动验证。具体来说,就是要在 HTML 标记中为特定的字段指定一些约束,然后浏览器才会自动执行表单验证。

(1)必填字段

在表单字段中指定了 required 属性:

<input type="text" name="username" required>

任何标注有 required 的字段,在提交表单时都不能空着。这个属性适用于 <input> 、 <textarea>和 <select> 字段(Opera 11 及之前版本还不支持 <select> 的 required 属性)。

在 JavaScript 中,通过对应的 required 属性,可以检查某个表单字段是否为必填字段。

var isUsernameRequired = document.forms[0].elements["username"].required;

测试浏览器是否支持 required 属性

var isRequiredSupported = "required" in document.createElement("input");

(2)其他输入类型

"email" 和 "url" 是两个得到支持最多的类型,各浏览器也都为它们增加了定制的验证机制。

<input type="email" name ="email">
<input type="url" name="homepage">

"email" 类型要求输入的文本必须符合电子邮件地址的模式, "url" 类型要求输入的文本必须符合 URL 的模式。

(3)数值范围

基于数字的值: "number" 、 "range" 、 "datetime" 、 "datetime-local" 、 "date" 、 "month" 、 "week" ,还有 "time" 。浏览器对这几个类型的支持情况并不好,因此如果真想选用的话,要特别小心。

对所有这些数值类型的输入元素,可以指定 min 属性(最小的可能值)、 max 属性(最大的可能值)和 step 属性(从 min 到 max 的两个刻度间的差值)。例如,想让用户只能输入 0 到 100的值,而且这个值必须是 5 的倍数:

<input type="number" min="0" max="100" step="5" name="count">

(4)输入模式

HTML5 为文本字段新增了 pattern 属性。这个属性的值是一个正则表达式,用于匹配文本框中的值。例如,如果只想允许在文本字段中输入数值

<input type="text" pattern="\d+" name="count">

在 JavaScript 中可以通过 pattern 属性访问模式。

var pattern = document.forms[0].elements["count"].pattern;

测浏览器是否支持 pattern 属性

var isPatternSupported = "pattern" in document.createElement("input");

(5)检测有效性

使用 checkValidity() 方法可以检测表单中的某个字段是否有效。所有表单字段都有个方法,如果字段的值有效,这个方法返回 true ,否则返回 false 。字段的值是否有效的判断依据是前面介绍过的那些约束。

if (document.forms[0].elements[0].checkValidity()){
    //字段有效,继续
} else {
    //字段无效
}

(6)禁用验证

通过设置 novalidate 属性,可以告诉表单不进行验证。

<form method="post" action="signup.php" novalidate>
<!--这里插入表单元素-->
</form>

在 JavaScript 中使用 noValidate 属性可以取得或设置这个值

document.forms[0].noValidate = true; //禁用验证

三、选择框脚本

选择框是通过 <select> 和 <option> 元素创建的。为了方便与这个控件交互,除了所有表单字段共有的属性和方法外, HTMLSelectElement 类型还提供了下列属性和方法。

  • add(newOption, relOption) :向控件中插入新 <option> 元素,其位置在相关项( relOption )之前。
  • multiple :布尔值,表示是否允许多项选择;等价于 HTML 中的 multiple 特性。
  • options :控件中所有 <option> 元素的 HTMLCollection 。
  • remove(index) :移除给定位置的选项。
  • selectedIndex :基于 0 的选中项的索引,如果没有选中项,则值为 -1 。对于支持多选的控件,只保存选中项中第一项的索引。
  • size :选择框中可见的行数;等价于 HTML 中的 size 特性。

选择框的 type 属性不是 "select-one" ,就是 "select-multiple" ,这取决于 HTML 代码中有没有 multiple 特性。选择框的 value 属性由当前选中项决定,相应规则如下。

  • 如果没有选中的项,则选择框的 value 属性保存空字符串。
  • 如果有一个选中项,而且该项的 value 特性已经在 HTML 中指定,则选择框的 value 属性等于选中项的 value 特性。即使 value 特性的值是空字符串,也同样遵循此条规则。
  • 如果有一个选中项,但该项的 value 特性在 HTML 中未指定,则选择框的 value 属性等于该项的文本。
  • 如果有多个选中项,则选择框的 value 属性将依据前两条规则取得第一个选中项的值。

在 DOM 中,每个 <option> 元素都有一个 HTMLOptionElement 对象表示。
HTMLOptionElement 对象添加了下列属性:

  • index :当前选项在 options 集合中的索引。
  • label :当前选项的标签;等价于 HTML 中的 label 特性。
  • selected :布尔值,表示当前选项是否被选中。将这个属性设置为 true 可以选中当前选项。
  • text :选项的文本。
  • value :选项的值(等价于 HTML 中的 value 特性)。
var selectbox = document.forms[0]. elements["location"];
var text = selectbox.options[0].text; // 选项的文本
var value = selectbox.options[0].value; //选项的值

1、选择选项

对于只允许选择一项的选择框,访问选中项的最简单方式,就是使用选择框的 selectedIndex 属性

var selectedOption = selectbox.options[selectbox.selectedIndex];

对于可以选择多项的选择框, selectedfIndex 属性就好像只允许选择一项一样。设置selectedIndex 会导致取消以前的所有选项并选择指定的那一项,而读取 selectedIndex 只会返回选中项中第一项的索引值。

另一种选择选项的方式,就是取得对某一项的引用,然后将其 selected 属性设置为 true 。

selectbox.options[0].selected = true;

与 selectedIndex 不同,在允许多选的选择框中设置选项的 selected 属性,不会取消对其他选中项的选择,因而可以动态选中任意多个项。但是,如果是在单选选择框中,修改某个选项的 selected 属性则会取消对其他选项的选择。需要注意的是,将 selected 属性设置为 false 对单选选择框没有影响。

selected 属性的作用主要是确定用户选择了选择框中的哪一项。要取得所有选中的项,可以循环遍历选项集合,然后测试每个选项的 selected 属性。

function getSelectedOptions(selectbox) {
    var result = new Array();
    var option = null;
    for (var i = 0, len = selectbox.options.length; i < len; i++) {
        option = selectbox.options[i];
        if (option.selected) {
            result.push(option);
        }
    }
    return result;
}

使用 getSelectedOptions() 函数取得选中项的示例

var selectbox = document.getElementById("selLocation");
var selectedOptions = getSelectedOptions(selectbox);
var message = "";
for (var i = 0, len = selectedOptions.length; i < len; i++) {
    message += "Selected index: " + selectedOptions[i].index +
        "\nSelected text: " + selectedOptions[i].text +
        "\nSelected value: " + selectedOptions[i].value + "\n\n";
}
alert(message);

2、添加选项

可以使用 JavaScript 动态创建选项,并将它们添加到选择框中。

使用DOM方法添加选项:

var newOption = document.createElement("option");
newOption.appendChild(document.createTextNode("Option text"));
newOption.setAttribute("value", "Option value");
selectbox.appendChild(newOption);

使用 Option 构造函数来创建新选项:

var newOption = new Option("Option text", "Option value");
selectbox.appendChild(newOption); //在 IE8 及之前版本中有问题

除 IE 之外的浏览器中都可以使用。由于存在 bug,IE 在这种方式下不能正确设置新选项的文本。

使用选择框的 add() 方法:

var newOption = new Option("Option text", "Option value");
selectbox.add(newOption, undefined); //最佳方案

DOM 规定这个方法接受两个参数:要添加的新选项和将位于新选项之后的选项。如果想在列表的最后添加一个选项,应该将第二个参数设置为null 。在 IE对 add() 方法的实现中,第二个参数是可选的,而且如果指定,该参数必须是新选项之后选项的索引。兼容 DOM 的浏览器要求必须指定第二个参数,因此要想编写跨浏览器的代码,就不能只传入一个参数。这时候,为第二个参数传入 undefined ,就可以在所有浏览器中都将新选项插入到列表最后了。

3、移除选项

使用 DOM 的 removeChild() 方法,为其传入要移除的选项:

selectbox.removeChild(selectbox.options[0]); //移除第一个选项

使用选择框的 remove() 方法,这个方法接受一个参数,即要移除选项的索引

selectbox.remove(0); //移除第一个选项

将相应选项设置为 null:

selectbox.options[0] = null; //移除第一个选项

要清除选择框中所有的项,需要迭代所有选项并逐个移除它们:

function clearSelectbox(selectbox) {
    for (var i = 0, len = selectbox.options.length; i < len; i++) {
        selectbox.remove(i);
    }
}

这个函数每次只移除选择框中的第一个选项。由于移除第一个选项后,所有后续选项都会自动向上移动一个位置,因此重复移除第一个选项就可以移除所有选项了。

4、移动和重排选项

使用 DOM 的 appendChild() 方法,就可以将第一个选择框中的选项直接移动到第二个选择框中。如果为 appendChild() 方法传入一个文档中已有的元素,那么就会先从该元素的父节点中移除它,再把它添加到指定的位置。

将第一个选择框中的第一个选项移动到第二个选择框中的过程:

var selectbox1 = document.getElementById("selLocations1");
var selectbox2 = document.getElementById("selLocations2");
selectbox2.appendChild(selectbox1.options[0]);

移动选项与移除选项有一个共同之处,即会重置每一个选项的 index 属性。

要将选择框中的某一项移动到特定位置,最合适的 DOM 方法就是 insertBefore() ; appendChild() 方法只适用于将选项添加到选择框的最后。
在选择框中向前移动一个选项的位置:

var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index-1]);

将选择框中的选项向后移动一个位置:

var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index+2]);

四、表单序列化

在 JavaScript 中,可以利用表单字段的 type 属性,连同 name 和 value 属性一起实现对表单的序列化。

在表单提交期间,浏览器是怎样将数据发送给服务器的:

  • 对表单字段的名称和值进行 URL 编码,使用和号(&)分隔。
  • 不发送禁用的表单字段。
  • 只发送勾选的复选框和单选按钮。
  • 不发送 type 为 "reset" 和 "button" 的按钮。
  • 多选选择框中的每个选中的值单独一个条目。
  • 在单击提交按钮提交表单的情况下,也会发送提交按钮;否则,不发送提交按钮。也包括 type为 "image" 的 <input> 元素。
  • <select> 元素的值,就是选中的 <option> 元素的 value 特性的值。如果 <option> 元素没有value 特性,则是 <option> 元素的文本值。

在表单序列化过程中,一般不包含任何按钮字段,因为结果字符串很可能是通过其他方式提交的。除此之外的其他上述规则都应该遵循。

function serialize(form) {
    var parts = [],
        field = null,
        i,
        len,
        j,
        optLen,
        option,
        optValue;
    for (i = 0, len = form.elements.length; i < len; i++) {
        field = form.elements[i];
        switch (field.type) {
            case "select-one":
            case "select-multiple":
                if (field.name.length) {
                    for (j = 0, optLen = field.options.length; j < optLen; j++) {
                        option = field.options[j];
                        if (option.selected) {
                            optValue = "";
                            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("&");
}

serialize() 函数会以查询字符串的格式输出序列化之后的字符串。

五、富文本编辑

这一技术的本质,就是在页面中嵌入一个包含空 HTML 页面的 iframe 。通过设置 designMode 属性,这个空白的 HTML 页面可以被编辑,而编辑对象则是该页面 <body> 元素的 HTML 代码。 designMode 属性有两个可能的值: "off" (默认值)和 "on" 。在设置为 "on" 时,整个文档都会变得可以编辑。

<iframe name="richedit" style="height:100px;width:100px;" src="blank.htm"></iframe>
<script type="text/javascript">
EventUtil.addHandler(window, "load", function(){
    frames["richedit"].document.designMode = "on";
});
</script>

1、使用contenteditable属性

另一种编辑富文本内容的方式是使用名为 contenteditable 的特殊属性,这个属性也是由 IE 最早实现的。可以把 contenteditable 属性应用给页面中的任何元素,然后用户立即就可以编辑该元素。

这种方法之所以受到欢迎,是因为它不需要 iframe 、空白页和 JavaScript,只要为元素设置contenteditable 属性即可。

<div class="editable" id="richedit" contenteditable></div>

通过在这个元素上设置 contenteditable 属性,也能打开或关闭编辑模式。

var div = document.getElementById("richedit");
div.contentEditable = "true";

contenteditable 属性有三个可能的值: "true" 表示打开、 "false" 表示关闭, "inherit" 表示从父元素那里继承。

2、操作富文本

与富文本编辑器交互的主要方式,就是使用 document.execCommand() 。这个方法可以对文档执行预定义的命令,而且可以应用大多数格式。可以为 document.execCommand() 方法传递 3 个参数:要执行的命令名称、表示浏览器是否应该为当前命令提供用户界面的一个布尔值和执行命令必须的一个值(如果不需要值,则传递 null )。为了确保跨浏览器的兼容性,第二个参数应该始终设置为 false ,因为 Firefox 会在该参数为 true 时抛出错误。

3、富文本选区

在富文本编辑器中,使用框架( iframe )的 getSelection() 方法,可以确定实际选择的文本。这个方法是 window 对象和 document 对象的属性,调用它会返回一个表示当前选择文本的 Selection对象。

4、表单与富文本

由于富文本编辑是使用 iframe 而非表单控件实现的,因此从技术上说,富文本编辑器并不属于表单。换句话说,富文本编辑器中的 HTML 不会被自动提交给服务器,而需要我们手工来提取并提交HTML。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  •   JavaScript 最初的一个应用,就是分担服务器处理表单的责任,打破处处依赖服务器的局面。   尽管目前的...
    霜天晓阅读 656评论 0 3
  • 表单基础知识 在HTML中,表单是由 元素来表示的,而在JS中,表单对应的则是HTMLFormElement类型。...
    oWSQo阅读 902评论 0 1
  • 第14章 表单脚本 1. 表单的基础指示 在 JavaScript 中,表单对应的则是 HTMLFormEleme...
    yinxmm阅读 296评论 0 1
  • HTML 5 HTML5概述 因特网上的信息是以网页的形式展示给用户的,因此网页是网络信息传递的载体。网页文件是用...
    阿啊阿吖丁阅读 3,828评论 0 0
  • 今天是你的第45个生日了吧,开始都没有认真算,只记得在外面游荡许久后某次归家才惊觉到我印象中那个有点讲究有点傲娇有...
    能与太阳肩并肩的妮玲阅读 279评论 0 0