欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

《JavaScript高级程序设计》笔记:表单脚本(十四)

程序员文章站 2022-08-12 11:11:02
表单的基础知识 在HTML中,表单是由
元素来表示的,而在JS中,表单对应的是HTMLFormElement类型。HTMLFormElement继承了HTMLElement,因而与其它HTML元素具有相同的默认属性。不过HTMLFormElement也有下列独有的属性和方法。 accept ......

表单的基础知识

在html中,表单是由<form>元素来表示的,而在js中,表单对应的是htmlformelement类型。htmlformelement继承了htmlelement,因而与其它html元素具有相同的默认属性。不过htmlformelement也有下列独有的属性和方法。

  • acceptcharset:服务器能够处理的字符集;等价于html中的accept-charset特性。
  • action:接受请求的url;等价于html中的action特性。
  • elements:表单中所有控件的集合。
  • enctype:请求的编码类型;等价于html中的enctype特性。
  • length:表单中控件的数量。
  • method:要发送的http请求类型,通常是"get"或“post”;等价于html中method特性。
  • name:表单的名称;等价于html的name特性。
  • reset():将所有表单域重置为默认值。
  • submit():提交表单。
  • target:用于发送请求和接收响应的窗口名称;等价于html中的target特性。

取得form元素引用的几种方式,方式一:

var form = document.getelementbyid('form1');

方式二:

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

var firstform = document.forms[0]; //取得页面中的第一个表单
var myform = document.forms['form1']; //取得页面中名为"form1"的表单

提交与重置表单

阻止表单提交:

var form = document.getelementbyid('myform');

//使用13章封装的eventutil对象
eventutil.addhandler(form,'submit',function(event){
    
    //取得事件对象
    event = eventutil.getevent(event);
    
    //阻止默认事件(取消表单的提交)
    event.preventdefault(event);
})

提交与重置:

var form = document.getelementbyid('myform');
//提交表单
form.submit();

//重置表单
form.reset();

表单字段

每个表单都有elements属性,该属性是所有表单中所有元素的集合。

var form = document.getelementbyid('myform');

//取得表单中的第一个字段
var field1 = form.elements[0];

//取得名为"textbox1"的字段
var field2 = form.elements['textbox1'];

//取得表单中包含的字段的数量
var fieldcount = form.elements.length;

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

表单字段共有的属性和方法:

  • disabled:布尔值,表示当前字段是否被禁用。
  • form:指向当前字段所属表单的指针;只读。
  • name:当前字段的名称。
  • readonly:布尔值,表示当前字段是否只读。
  • tabindex:表示当前字段的切换(tab)序号。
  • type:当前字段的类型,如“checkbox”、“radio”等。
  • value:当前字段被提交到服务器的值。

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

var form = document.getelementbyid('myform');
var field = form.elements[0];

//修改value属性
field.value = "another value";

//检查form属性的值
console.log(field.form == form);

//把焦点设置到当前字段
field.focus();

//禁用当前字段
field.disabled = true;

//修改type属性(不推荐,但对<input>来说是可行的)
field.type ="checkbox";

避免多次提交表单,在第一次点击提交表单后,设置提交按钮disabled为true,如下代码:

var form = document.getelementbyid('myform');

//避免多次提交表单
eventutil.addhandler(form,"submit",function(event){
    event = eventutil.getevent(event);
    var target = eventutil.gettarget(event);
    
    //取得提交按钮
    var btn = target.elements['submit-btn'];
    
    //禁用它
    btn.disabled = true;
    
    //后面代码省略
})

每个表单字段都有两个方法:focus()blur()。例如,在页面加载完成后,把焦点转移到表单中的第一个字段,如下代码:

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

注意,如果第一个表单字段是<input>元素,且它的type特性的值为“hidden”,那么以上代码会发生错误(高版本浏览器升级修复了该问题)。

html5为表单字段新增加了一个autofocus属性。

<input type="text"  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()change()blur()这三个事件。如下例子:

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.background != 'red'){
        target.style.background = 'yellow';
    }
});
eventutil.addhandler(textbox,"blur",function(event){
    event = eventutil.getevent(event);
    var target = eventutil.gettarget(event);
    if(/[^\d]/.test(target.value)){
        target.style.background = 'red';
    }else{
        target.style.background = '';
    }
});
eventutil.addhandler(textbox,"change",function(event){
    event = eventutil.getevent(event);
    var target = eventutil.gettarget(event);
    console.log(target.value)
    if(/[^\d]/.test(target.value)){
        target.style.background = 'red';
    }else{
        target.style.background = '';
    }
})

文本框脚本

两种方式表示文本框:<input><textarea>

<input>文本框,通过设置size属性,可以指定文本框中显示的字符数。通过设置value特性,可以设置文本框默认的初始值。而maxlength用于指定文本框可以接受的最大字符数。

<input type="text" size="20" value="init value" maxlength="50"/>

对于<textarea>多行文本框而言,要指定文本框的大小,通过设置rows(指定文本框的字符行数)和cols(指定文本框的字符列数)。<textarea>的初始值必须放在<textarea>与</textarea>之间。

<textarea rows="25" cols="5"> init vaule</textarea>

选择文本

上述两种文本框都支持select()方法,这个方法用于选择文本框中的所有文本。

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

文本框获得焦点,选择其中所有文本,代码如下:

var textbox = document.forms[0].elements["textbox"];
eventutil.addhandler(textbox,"focus",function(event){
    event = eventutil.getevent(event);
    var target = eventutil.gettarget(event);
    target.select();
})

1.选择(select)事件

与select()方法对应的是一个select事件。在选择了文本框的文本时,就会触发select事件。不过到底什么时候触发select事件,还会因浏览器而异。在ie9以及其它高版本浏览器中,当用户选择了文本(而且要释放鼠标),才会触发select事件。而在ie8以及更早的版本中,只要用户选择了一个字母(不必释放鼠标),就会触发select事件。另外,在调用select()方法时也会触发select事件。如下代码:

var textbox = document.forms[0].elements["textbox"];
eventutil.addhandler(textbox,"select",function(event){
    console.log("text selected:" + textbox.value);    
})

2.取得选择的文本

虽然select事件知道用户什么时候选择了文本,但是不知道用户选择了什么文本。html5规范为此添加了两个属性:selectionstartselectionend。这两个属性保存的是基于0的数值,表示所选择文本的范围(即文本选区开头和结尾的偏移量)。

function getselectedtext(textbox){
    return textbox.value.substring(textbox.selectionstart,textbox.selectionend);
}
var textbox = document.forms[0].elements["textbox"];
eventutil.addhandler(textbox,"select",function(event){
    console.log("text selected:" + getselectedtext(textbox));    
})

ie8及之前的版本不支持这两个属性,有一个document.selection对象,其中保存着用户在整个文档范围内选择的文本信息;也就是说,无法确认用户选择的是页面中哪个部位的文本。不过在和select事件一起使用的时候,可以假定是用户选择了文本框中的文本,因而触发了该事件。要取得选中的文本,首先必须创建一个范围,然后将文本从其中提取出来。代码如下:

function getselectedtext(textbox){
    if(typeof textbox.selectionstart == 'number'){
        return textbox.value.substring(textbox.selectionstart,textbox.selectionend);
    }else if(document.selection){
        document.selection.createrange().text;
    }    
}

3.选择部分文本

html5也为选择文本框中的部分文本提供了解决方案,即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

textbox.focus();

要看到选中的文本,必须在调用setselectionrange()之前或之后立即将焦点设置到文本框。ie9以及其它高版本支持这种方案。

ie8以及更早版本支持使用范围选择部分文本。要选择文本框中的部分文本,必须首先使用ie在所有文本框上提供的createtextrange()方法创建一个范围,并将其放到恰当的位置上。然后再使用movestart()moveend()这两个范围方法将范围移动到位。不过,在调用这两个方法之前,还必须使用collapse()将范围折叠到文本框的开始位置。此时,movestart()将范围的起点和终点移动到了相同的位置,只要再给moveend()传入要选择的字符总数即可。最后一步,就是使用范围的select()方法选择文本。代码如下:

textbox.value = "hello world!";

var range = textbox.createtextrange();

//选择所有文本
range.collapse(true);
range.movestart("character",0);
range.moveend("character",textbox.value.length);//hello world!
range.select();

//选择前3个字符
range.collapse(true);
range.movestart("character",0);
range.moveend("character",3);//hel
range.select();

//选择第4到第6个字符
range.collapse(true);
range.movestart("character",4);
range.moveend("character",3);//hel
range.select();

跨浏览器:

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();
}

 过滤输入

1.屏蔽字符

eventutil.addhandler(textbox,"keypress",function(event){
    event = eventutil.getevent(event);
    eventutil.preventdefault(event);
})

注:上面代码能屏蔽英文字符,但是不能屏蔽中文汉字。

只允许用户输入数值:

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);
    }
})

虽然理论上只有在用户按下字符键时才会触发keypress事件,但有些浏览器也会对其它键触发此事件。firefox和safari(3.1版本以前)会对向上键、向下键、退格键和删除键触发keypress事件。这就意味着,仅考虑到屏蔽不是数值的字符还是不够,还要避免屏蔽这些极为常见和必要的键。在firefox中,所有由非字符键触发的keypress事件对应的字符编码为0,而在safari3.1以前的版本中,对应的字符编码全部为8。为了让代码更通用,只要不屏蔽那些字符编码小于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);
    }
})

上面代码可以屏蔽非数值字符,但不屏蔽那些也会触发keypress事件的基本按键。

还有一个问题需要处理:复制、粘贴以及其它操作还要用到ctrl键,最后还有一个检测,以确保用户没有按下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);
    }
})

2.操作剪贴板

html5的6个剪贴板事件。

  • beforecopy:在发生复制操作前触发。
  • copy:在发生复制操作时触发。
  • beforecut:在发生剪切操作前触发。
  • cut:在发生剪切操作时触发。
  • beforepaste:在发生粘贴操作前触发。
  • paste:在发生粘贴操作时触发。

在实际的事件发生前,通过beforecopy、beforecut和beforepaste事件可以在向粘贴板发送数据,或者从剪贴板取得数据之前修改数据。不过,取消这些事件并不会取消对剪贴板的操作,只有取消copy、cut和paste事件,才能阻止相应的操作发生。

要访问剪贴板中的数据,可以使用clipboarddata对象;在ie中,这个对象是window对象的属性;而在firefox、safari和chrome中,这个对象是相应的event对象的属性。但是,在firefox、safari和chrome中,只有在处理剪贴板事件期间clipboarddata对象才有效,这是为了防止对剪贴板的未授权访问;在ie中,则可以随时访问clipboarddata对象。

这个clipboarddata对象有三个方法:getdata()setdata()cleardata()

getdata():从剪贴板中取得数据,接受一个参数,即要取得的数据的格式。在ie中,有两种数据格式,“text”和“url”。在firefox、safari和chrome中,这个参数是一个mime类型;不过,可以用“text”代表“text/plain”。

setdata():第一个参数也是数据类型,第二参数是放到剪贴板中的文本。对于第一个参数ie照样支持“text”和“url”。而在safari和chrome中,这个参数仍然只支持mime类型。但是与getdata()方法不同的是,safari和chrome的setdata()方法不能识别“text”类型。这两个浏览器在成功将文本放到剪贴板后,都会返回true,否则返回false。为了弥合这些差异,可以向eventutil对象中添加下列方法:

var eventutil = {

    //省略的代码
    
    //得到剪贴板数据
    getclipboarddata:function(event){
        var clipboarddata = (event.clipboarddata || window.clipboarddata);
        return clipboarddata.getdata("text");
    },
    
    //设置剪贴板数据
    setclipboarddata:function(event,value){
        if(event.clipboarddata){
            return event.clipboarddata.setdata("text/plain",value);
        }else if(window.clipboarddata){
            return window.clipboarddata.setdata("text",value);
        }
    }
};

在paste事件中,确定剪贴板中的数据是否有效,如果无效,取消默认行为,如下代码,如果不是数字,则取消粘贴:

var textbox = document.forms[0].elements["textbox"];
eventutil.addhandler(textbox,"paste",function(event){
    event = eventutil.getevent(event);
    var text = eventutil.getclipboarddata(event);
    if(!/^\d*$/.test(text)){
        eventutil.preventdefault(event);
    }
})

自动切换焦点

 html:

<form>
    <input type="text" name="tel1" id="txttel1" maxlength="3"/>
    <input type="text" name="tel2" id="txttel2" maxlength="3"/>
    <input type="text" name="tel3" id="txttel3" maxlength="4"/>
</form>

js代码:

(function(){
    function tabforward(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){
                    if(form.elements[i+1]){
                        form.elements[i+1].focus();
                    }
                    return;
                }
            }
        }
    }
    
    var textbox1 = document.getelementbyid('txttel1');
    var textbox2 = document.getelementbyid('txttel2');
    var textbox3 = document.getelementbyid('txttel3');
    
    eventutil.addhandler(textbox1,"keyup",tabforward);
    eventutil.addhandler(textbox2,"keyup",tabforward);
    eventutil.addhandler(textbox3,"keyup",tabforward);
})();

 html5约束验证api

1.必填字段

在表单字段中添加required属性。

<form>
    <input type="text" name="text" id="mytext" required/>
    <input type="submit" value="提交"/>
</form>

js检测某个表单字段是否为必填字段:

var isuernamerequired = document.forms[0].elements['username'].required;

使用下面这段代码可以测试浏览器是否支持required属性:

var isrequiredsupported = "required" in document.createelement("input");

2.其他输入类型

html5为<input>元素的type值新添了几个值。其中“email”和“url”是两个得到支持最多的类型,如下代码:

<form>
    <input type="email" name="email" required/>
    <input type="url" name="url" required/>
    <input type="submit" value="提交"/>
</form>

检测浏览器是否支持这些新类型,不支持它们的旧版本浏览器会自动将未知的值设置为“text”,而支持的浏览器会返回正确的值。例如:

var input = document.createelement("input");
input.type ="email";

var isemailsupported = (input.type == "email");

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="acount"/>

还有两个方法stepup()和stepdown(),还没有任何浏览器支持,使用如下:

input.stepup();//加1
input.stepup(6);//加6
input.stepdown();//减1
input.stepdown(6);//减6

4.输入模式

html5为文本字段新增了pattern属性。这个属性的值是一个正则表达式,用于匹配文本框中的值。如下,只运行文本输入数字,代码如下:

<input type="number" pattern="\d+" name="acount"/>

注意,模式的开头和结尾不用加^和$符号。

检测浏览器是否支持pattern属性:

var ispatternsupported = "pattern" in document.createelement("input");

5.检测有效性

使用checkvalidity()方法可以检测整个表单,也可以检测某个表单字段。

//检测具体的某个表单字段
if(document.forms[0].elements[0].checkvalidity()){
    alert("有效的值");
}else{
    alert("无效的值");
}

//检测整个表单
if(document.forms[0].checkvalidity()){
    alert("表单有效");
}else{
    alert("表单无效");
}

 6.禁用验证

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

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

在js中使用novalidate属性可以取得或设置这个值,如果这个属性存在,值为true,不存在则为false。

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

如果一个表单中有多个提交按钮,可以指定某个提交按钮不必验证表单,可以在相应的按钮上添加formnovalidate属性。

<form method="post" action="foo.php">
    <!--这里插入表单元素-->
    <input type="submit" value="regular submit"/>
    <input type="submit" formnovalidate name="btnnovalidate" value="non-validating submit"/>
</form>

使用js设置这个属性:

document.forms[0].elements['btnnovalidate'].formnovalidate = 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特性。

在dom中,每个<option>元素都有一个htmloptionelement对象。为便于访问数据,htmloptionelement对象添加了下列属性:

  • index:当前选项在options集合中的索引。
  • label:当前选项的标签;等价于html中的label特性。
  • selected:布尔值,表示当前选项是否被选中。将这个属性设置为true可以选中当前选项。
  • text:选项的文本。
  • value:选项的值(等价于html中的value特性)。

如下代码,html:

<form>
    <select name="location">
        <option value="1">北京</option>
        <option value="2">天津</option>
        <option value="3">上海</option>
    </select>
</form>

js代码:

var selectbox = document.forms[0].elements['location'];
var text = selectbox.options[0].text; //选项的文本
var value = selectbox.options[0].value;//选项的值

选择选项

使用选择框的selectedindex属性。如上面代码默认选中了天津。

var selectbox = document.forms[0].elements['location'];
var selectoption = selectbox.options[selectbox.selectedindex];

选中选择框的第一项:

selectbox.options[0].selected = true;

多选下,取得所有选中的项:

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;
}
var selectbox = document.forms[0].elements['location'];
getselectedoptions(selectbox);

添加选项

第一种,dom方式添加:

var selectbox = document.forms[0].elements['location'];
var newoption = document.createelement('option');
newoption.appendchild(document.createtextnode('option text'));
newoption.setattribute('value',"option value");
selectbox.appendchild(newoption);

第二种方式,使用option构造函数,option构造函数接受两个参数:文本(text)和值(value),第二个参数可选。虽然这个构造函数会创建一个option实例,但兼容dom的浏览器会返回一个<option>元素。如下代码:

var selectbox = document.forms[0].elements['location'];
var newoption = new option("option text","option value");
selectbox.appendchild(newoption); //在ie8以及之前版本有问题

第三种方式使用选择框的add()方法。该方法接受两个参数:要添加的新选项和将位于新选项之后的选项。

var selectbox = document.forms[0].elements['location'];
var newoption = new option("option text","option value");
selectbox.add(newoption,undefined); 

移除选项

三种方式如下:

var selectbox = document.forms[0].elements['location'];

//removechild()传入要移除的选项
selectbox.removechild(selectbox.options[0]); //移除第一个选项

//remove(index)传入移除项的索引
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);
    }
}

移动和重排选项

将第一个选择框中的第一个选项移动到第二选择框中,代码如下:

var selectbox1 = document.getelementbyid('location1');
var selectbox2 = document.getelementbyid('location2');
selectbox2.appendchild(selectbox1.options[0]);

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

要将选择框中的某一项移动到特定的位置,最适合的dom方法insertbefore()

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]);

表单序列化

在编写代码之前,有必须先搞清楚在表单提交期间,浏览器是怎样将数据发送给服务器的。

  • 对表单字段的名称和值进行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[i];
                        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('&');
}

富文本编辑

富文本编辑,这一技术的本质,就是在页面中嵌入一个包含空html页面的iframe。通过设置designmode属性,这个空白的html页面可以被编辑,而编辑对象则是该页面<body>元素的html代码。designmode属性有两个可能的值:“off”(默认值)和“on”。在设置为“on”时,整个文档都会变得可以编辑(显示插入符号),然后就可以像使用字处理软件一样,通过键盘将文本内容加粗、变成斜线等等。

<iframe name="richedit" style="width:100px;height:100px;" src="index2.html"></iframe>
<script type="text/javascript">
    eventutil.addhandler(window,"load",function(event){
        frames["richedit"].document.designmode = "on";
    })
</script>

使用contenteditable属性

另一种编辑富文本内容的方式是使用名为contenteditable的特殊属性。这个属性最早由ie实现。使用它,不需要使用iframe、空白页和js,只要给元素设置该属性即可,如下:

<div class="editable" id="richedit" contenteditable style="width:100px;height:100px;border:1px solid grey"></div>

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

var div = document.getelementbyid('richedit');
div.contenteditable = "false";

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

操作富文本

document.execcommand(),这个方法可以对文档执行预定义的命令,这个方法接受三个参数:要执行的命令名称、表示浏览器是否应该为当前命令提供用户界面的一个布尔值(跨浏览器兼容性,一般都设置为false)和执行命令必须的一个值。

使用命令来修改富文本区域的外观,如下例子:

//转换粗体文本
frames["richedit"].document.execcommand("bold",false,null);

//转换斜体文本
frames["richedit"].document.execcommand("italic",false,null);

同样的方法适用于页面中contenteditable属性为true的区块:

//转换粗体文本
document.execcommand("bold",false,null);

//转换斜体文本
document.execcommand("italic",false,null);

富文本选区

表单与富文本

eventutil对象方法:

var eventutil = {
    
    //事件处理程序
    addhandler:function(element,type,handler){
        if(element.addeventlistener){
            element.addeventlistener(type,handler,false);
        }else if(element.attachevent){
            element.attachevent("on" + type,handler);
        }else{
            element["on" + type] = handler;
        }
    },
    
    //得到event对象
    getevent:function(event){
        return event ? event : window.event;
    },
    
    //得到事件目标
    gettarget:function(event){
        return event.target || event.srcelement;
    },
    
    //得到相关元素信息
    getrelatedtarget:function(event){
        if(event.relatedtarget){
            return event.relatedtarget;
        }
        else if(event.toelement){
            return event.toelement;
        }
        else if(event.fromelement){
            return event.fromelement;
        }else{
            return null;
        }
    },
    
    //取消默认行为
    preventdefault:function(event){
        if(event.preventdefault){
            event.preventdefault();
        }else{
            event.returnvalue = false;
        }
    },
    
    //得到button属性
    getbutton:function(event){
        if(document.implementation.hasfeature("mouseevents","2.0")){
            return event.button;
        }else{
            switch(event.button){
                case 0:
                case 1:
                case 3:
                case 5:
                case 7:
                    return 0;
                case 2:
                case 6:
                    return 2;
                case 4:
                    return 1;
            }
        }
    },
    
    //取得鼠标滚轮增量值(delta)
    getwheeldelta:function(event){
        if(event.wheeldelta){
            return event.wheeldelta;
        }else{
            return -event.detail * 40;
        }
    },
    
    //字符编码
    getcharcode:function(event){
        if(typeof event.charcode == 'number'){
            return event.charcode;
        }else{
            return event.keycode;
        }
    },
    
    //移除事件处理程序
    removehandler:function(element,type,handler){
        if(element.removeeventlistener){
            element.removeeventlistener(type,handler,false);
        }else if(element.detachevent){
            element.detachevent("on" + type,handler);
        }else{
            element["on" + type] = null;
        }
    },
    
    //阻止事件捕获或冒泡
    stoppropagation:function(event){
        if(event.stoppropagation){
            event.stoppropagation();
        }else{
            event.cancelbubble = true;
        }
    },
    
    //得到剪贴板数据
    getclipboarddata:function(event){
        var clipboarddata = (event.clipboarddata || window.clipboarddata);
        return clipboarddata.getdata("text");
    },
    
    //设置剪贴板数据
    setclipboarddata:function(event,value){
        if(event.clipboarddata){
            return event.clipboarddata.setdata("text/plain",value);
        }else if(window.clipboarddata){
            return window.clipboarddata.setdata("text",value);
        }
    }
};