1. 表单


1.1 获得表单

在HTML中,表单是由<form>元素来表示的,而在JavaScript中,表单对应的则是HTMLFormElement类型。HTMLFormElement继承了HTMLElement,因而与其他HTML元素具有相同的默认属性,此外,HTMLFormElement也有它自己独有的属性和方法:

1) acceptCharset: 服务器能够处理的字符集。

2) action: 接受请求的URL。

3) elements: 表单中所有控制的集合。

4) enctype: 请求的编码类型。

5) length: 表单中控件的数量。

6) method: 要发送的HTTP请求类型。

7) name: 表单的名称。

8) reset(): 将所有表单域重置为默认值。

9) submit(): 提交表单。

10) target: 用于发送请求和接收响应的窗口名称。

要取得<form>元素的引用,最常见的方式就是为其添加id属性,然后再用getElementById()方法找到它,例如:

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

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

var firstForm = document.forms[0];
var myform = document.form["formname"];


1.2 提交表单

用户单击提交按钮或图像按钮时,就会提交表单。使用<input>或<button>都可以定义提交按钮,只要将其type属性设置为"submit",例如:

<input type="submit" value="Submit"/>
<button type="submit">Submit</button>
<input type="image" src="sub.jpg"/>

提交表单时,浏览器会在将请求发送给服务器之前触发submit事件,阻止这个事件的默认行为就可以取消表单提交,例如:

var form = document.getElementById("myform");
EventUtil.addHandle(form, "submit", function(event) {
  event = EventUtil.getEvent(event);
  EventUtil.preventDefault(event);
});

以编程方式调用submit()方法也可以提交表单,例如:

var form = document.getElementById("myform");
form.submit();


1.3 重置表单

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

<input type="reset" value="Reset"/>
<button type="reset">Reset</button>

在重置表单时,所有表单字段都会恢复到页面刚加载完毕时的初始值。用户单击重置按钮时,会触发reset事件,可以在必要时取消重置,例如:

var form = document.getElementById("myform");
EventUtil.addHandler(form, "reset", function(event) {
  event = EventUtil.getEvent(event);
  EventUtil.preventDefault(event);
});

与调用submit()一样,也可以通过JavaScript来重置表单,例如:

var form = document.getElementById("myform");
form.reset();


1.4 表单字段

可以使用原生DOM方法访问表单元素,每个表单都有elements属性,该属性是表单中所有元素的集合,例如:

var form = document.getElementById("myform");
var field1 = form.elements[0];
var field2 = form.elements["textbox1"];
var fieldCount = form.elements.length;

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

除了<filedset>元素外,所有表单字段都拥有相同的一组属性和方法:

1) disabled: 表示当前字段是否被禁用。

2) form: 指向当前字段所属表单的指针。

3) name: 当前字段的名称。

4) readOnly: 表示当前字段是否只读。

5) tabIndex: 表示当前字段的切换序号。

6) type: 当前字段的类型。

7) value: 当前字段将被提交给服务器的值。

每个表单字段都有两个方法:focus()和blur()。其中focus()方法用于将浏览器的焦点设置到表单字段,blur()方法的作用是从元素中移走焦点。

所有表单字段还支持3个事件:blur、change和focus。分别在当前字段失去焦点时触发,在内容改变时触发,在当前字段获得焦点时触发。


2. 文本框脚本


2.1 选择文本

<input>和<textarea>都支持select()方法,这个方法用于选择文本框中的所有文本,例如:

var textbox = docuemnt.forms[0].elements["mytextbox"];
textbox.select();

在文本框获得焦点时选择其所有文本是常见做法,例如:

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

与select()方法对应的是一个select事件,在选择了文本框中的文本时,就会触发select事件。虽然可以通过select事件我们可以知道用户什么时候选择了文本,但仍然不知道用户选择了什么文本。没有标准对此作出规定,因此就存在一些事实标准,其中,Firefox的方案最受认可。Firefox为文本框添加了两个属性:selectionStart和selectionEnd。这两个属性中保存的是基于0的数值,表示所选择文本的范围,因此可以使用如下代码:

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

Firefox、Safari、Chrome和Opera都支持这两个属性,IE不支持,而是有一个document.selection对象,其中保存着用户在整个文档范围内选择的文本信息,例如:

function getSelectedText(textbox) {
  if (document.selection) {
    return document.selection.createRange().text;
  }
  else {
    return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd);
  }
}

虽然选择文本框中的部分文本是一种很正常的操作,但却没有相关标准。同样Firefox的解决方案也是这种情况下的事实标准,即为所有文本框都添加了setSelectionRange()方法。这个方法接受两个参数:要选择的第一个字符索引和最后一个字符之后的字符索引,例如:

textbox.setSelectionRange(0, textbox.value.length);

Firefox、Safari、Chrome和Opera都支持这种方案。IE支持使用范围选择部分文本,IE为文本框提供了createTextRange()方法,要选择文本框中的部分文本,必须创建一个范围,并将其放到恰当的位置上。然后再使用moveStart()和moveEnd()将范围移动到位,之前还必须使用collapse()将范围折叠到文本框的开始位置,例如:

var range = textbox.createTextRange();
range.collapse(true);
range.moveStart("character", 0);
range.moveEnd("character", textbox.value.length);
range.select();


2.2 过滤输入

有时候我们需要控制用户输入,比如屏蔽所有按键操作,例如:

EventUtil.addHandle(textbox, "keypress", function(event) {
  event = EventUtil.getEvent(event);
  EventUitl.preventDefault(event);
});

如果只想屏蔽特定的字符,则需要检测keypress事件,例如:

EventUtil.addHandle(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) {
    EventUitl.preventDefault(event);
  }
});

IE是第一个支持剪贴板相关的事件,以及通过JavaScript访问剪贴板数据的浏览器,IE实现成为事实标准,Safari 2、Chrome和Firefox 3也支持类似的事件。下列是6个剪贴板事件:

1) beforecopy: 在发生复制操作前触发。

2) copy: 在发生复制操作时触发。

3) beforecut: 在发生剪切操作前触发。

4) cut: 在发生剪切操作时触发。

5) beforepaste: 在发生粘贴操作前触发。

6) paste: 在发生粘贴操作时触发。

要访问剪贴板中的数据,可以使用clipboardData对象。在IE中,这个对象是window对象的属性,而在Safari和Chrome中,这个对象是相应event对象的属性。但是Firefox不支持clipboardData对象,而且Safari和Chrome中,只有在处理剪贴板事件期间clipboardData对象才有效。这个对象有三个方法:getData()、setData()和clearData()。其中getData()用于从剪贴板中取得数据,setData()用于放入数据,而clearData()用于清除数据。


2.3 切换焦点

在用户填完当前字段时,自动将焦点切换到下一个字段可以增强表单的易用性。这会使用到焦点切换的功能,例如:

(function() {
  function tagForward(event) {
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    if (target.value.length == target.maxLength) {
      var form = target.form;
      for (var i=0, len=form.elements.length; i<len; i++) {
        if (form.elements[i] == target) {
          form.elements[i+1].focus();
          return;
        }
      }
    }
  }
})


3. 选择框脚本


3.1 选择选项

除了表单字段共有的属性外,HTMLSelectElement类型还提供了下列属性和方法:

1) add(): 向控件中添加新<option>元素。

2) multiple: 是否允许多项选择。

3) options: 控件中所有<option>元素的HTMLCollection。

4) remove(): 移除给定位置的选项。

5) selectedIndex: 基于0的选中项的索引,如果没有,则为-1,对于多选,只保存第一项的索引。

6) size: 选择框中可见的行数。

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

1) index: 当前选项在options集合中的索引。

2) label: 当前选项的标签。

3) selected: 表示当前选项是否被选中。

4) text: 选项的文本。

5) value: 选项的值。

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

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

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

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

selectbox.options[0].selected = true;

在允许多选的选择框中设置选项的selected属性,不会取消对其他选中项的选择,因而可以动态选中任意多个项。


3.2 添加选项

可以使用JavaScript动态创建选项,并将它们添加到选择框中,添加选项的方式有很多,第一种是使用DOM方法,例如:

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

第二种方式是使用Option构造函数接受两个参数:文本和值,第二个参数可选,例如:

var newOption = new Option("Text", "Value");
selectbox.appendChild(newOption); //IE不兼容

第三种方式是新选项的方式是使用选择框的add()方法,这个方法接受两个参数:要添加的新选项和将位于新选项之后的选项,如果想在列表最后一项添加,应该将第二个选项设为null,在IE中对add()方法的实现中,第二个参数是可选的,而且必须是新选项之后选项的索引,因此兼容代码不能只传一个参数,可以为第二个参数传入undefined,例如:

var newOption = new Option("Text", "Value");
selectbox.add(newOption, undefined);


3.3 移除选项

移除选项也有很多种,第一种可以用DOM的removeChild()方法,例如:

selectbox.removeChild(selectbox.options[0]);

第二种可以使用选择框的remove()主应运,这个方法接受一个参数,即要移除选项的索引,例如:

selctbox.remove[0];

第三种是将相应选项设置为null,例如:

selctbox.options[0] = null;


3.4 移动选项

使用DOM的appendChild()方法,可以将第一个选择框中的选项直接移动到第二个选择框中,例如:

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

重排选项次序的过程也类似,例如:

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