js 表单脚本

目录

前言

一、表单基础知识

1、HTMLFormElement 独有的属性和方法

2、获取 form 元素引用(获取表单)

(1)、像获取普通 DOM 元素一样获取 form

(2)、通过 document.forms 获取 form

(3)、直接通过 document."表单名字" 获取 form

二、提交表单

1、提交表单的方式有两类

(1)、按钮提交

(2)、JavaScript 的 submit() 方法提交

2、如何避免重复提交表单?(★★★★★)

三、重置表单

1、重置表单的方式有两类

(1)、按钮重置

(2)、JavaScript 的 reset() 方法重置

四、表单字段

1、使用 elements 属性访问表单元素

2、共有的表单字段属性

3、共有的表单字段方法

(1)、focus() 方法

(2)、blur() 方法

(3)、change() 方法(★★★★★)

五、文本脚本

1、单行文本框 \\>

2、多行文本框 \\>

3、选择文本 \\>

(1)、在文本框获得焦点时自动选择其所有文本(★★★★★)

(2)选择部分文本

4、过滤输入

(1)、屏蔽字符(★★★★★)

(2)、操作剪切板

(3)、 如何确保粘贴到文本框中的文本包含某些字符,或者符合某种格式要求呢?(★★★★★)

(4)、自动切换焦点(★★★★★)

(5)、HTML5 约束验证 API

六、选择框脚本

1、\ 元素\>

2、\ 元素\>

七、表单序列化

八、富文本编辑

1、富文本编辑的本质

2、使用 contenteditable 属性使页面中的元素变成富文本编辑

3、操作富文本

(1)、使用 document.execCommand() 方法操作富文本

(2)、使用 DOM 的一系列方法操作富文本

4、表单与富文本


前言

本文多处用到“跨浏览器事件处理程序  EventUtil”,详细代码请戳:https://blog.csdn.net/mChales_Liu/article/details/106541683

一、表单基础知识

在 HTML 中,表单是由 <form> 元素表示的,而在 JavaScript 中,表单对应的则是 HTMLFormElement 类型。HTMLFormElement 继承了 HTMLElement,因此与其他 HTML 元素一样具有相同的默认属性。

1、HTMLFormElement 独有的属性和方法

(1)、HTMLFormElement 独有的属性

  • acceptCharset:服务器能够处理的字符集,等价于 HTML 中的 accept-charset 特性。
  • action:接受请求的 URL,等价于 HTML 中的 action 特性。
  • elements:表单中所有控件的集合(HTMLCollection)。
  • enctype:请求的编码类型,等价于 HTML 中的 enctype 特性。
  • length:变淡中控件的数量。
  • method:要发送的 HTTP 请求类型,通常是“get”或“post”,等价于 HTML 中的 method 特性。
  • name:表单的名称,等价于 HTML 中的 name 特性。
  • target:用于发送请求和接受响应的窗口名称,等价于 HTML 中的 target 特性。

(2)、HTMLFormElement 独有的方法

  • reset():将所有表单域重置为默认值。
  • submit():提交表单。

2、获取 form 元素引用(获取表单)

(1)、像获取普通 DOM 元素一样获取 form

比如:通过添加 id 特性,用 getElementById() 获取。

<form action="#" id="form1">
    <input type="text" name="textName1" />
</form>
<script>
    // 获取页面上 id 为“form1”的表单
    var form = document.getElementById("form1");
    console.log(form);           // <form action="#" id="form1">...</form>
</script>

(2)、通过 document.forms 获取 form

<form action="#" id="form1">
    <input type="text" name="textName1" />
</form>
<form action="#" id="form2">
    <input type="text" name="textName1" />
</form>
<script>
    // 获取页面上 id 为“form2”的表单
    var myForm = document.forms["form2"];        
    console.log(form);           // <form action="#" id="form2">...</form>

    // 获取页面中的第一个表单
    var firstForm = document.forms[0];           
    console.log(form);           // <form action="#" id="form1">...</form>
</script>

(3)、直接通过 document."表单名字" 获取 form

不建议采用这种方式,因为有些浏览器版本不兼容此方法。

<form action="#" id="form1" name="aform">
    <input type="text" name="textName1" />
</form>
<script>
    var form = document.aform;
    console.log(form);         // <form action="#" id="form1" name="aform">...</form>
</script>

 

二、提交表单

1、提交表单的方式有两类

(1)、按钮提交

<!-- 提交按钮 -->
<input type="submit" value="提 交">
<!-- 自定义提交按钮 -->
<button type="submit">提 交</button>
<!-- 图像按钮 -->
<input type="image" src="abc.png">

注意:只要表单中存在上述任一按钮,那么在相应的表单控件获取到焦点的情况下,按回车键就可以提交表单。 

以这种方式提交表单时,浏览器会在将请求发送之前触发 submit 事件,在 submit 事件中做表单验证,以校验结果决定是否提交表单。

--> 阻止 submit 事件的默认行为

在表单数据无效时,只要阻止 submit 事件的默认行为,就可以取消表单提交:

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

(2)、JavaScript 的 submit() 方法提交

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

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

2、如何避免重复提交表单?(★★★★★)

思路:在第一次提交表单后就要禁用提交按钮,或者利用 onsubmit 事件处理程序取消后续的表单提交操作。

var form = document.getElementById("myForm");
EventUtil.addHandler(form, "submit", function(event){
    evnet = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    // 获取提交按钮
    var btn = target.elements["submit-btn"];
    // 禁用提交按钮
    btn.disabled = true;
})

 

三、重置表单

1、重置表单的方式有两类

(1)、按钮重置

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

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

-->阻止 reset 事件的默认行为

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

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

(2)、JavaScript 的 reset() 方法重置

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

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

 

四、表单字段

1、使用 elements 属性访问表单元素

(注意与“获取 form 元素引用”的差异)

elements 属性是表单中所有元素的集合,这个集合石一个有序列表,可以按照位置和 name 特性来访问其中的元素,当多个字段的name名相同时,使用name访问字段,会返回一个NodeList。

<form id="userForm">
    <span>姓名</span><input type="text" name="userName"/><br>
    <span>密码</span><input type="password" name="userPsd"/><br>
    <span>性别</span>
        <input type="radio" name="userGender" checked/><b>男</b>
        <input type="radio" name="userGender"/><b>女</b><br>
</form>
<script>
    
</script>
<script>
    var personInfo = document.getElementById("userForm");
    
    // 取得表单中包含字段的数量
    var fieldCount = personInfo.elements.length;
    console.log(fieldCount);            // 4
    
    // 取得第一个字段
    var myForm1 = personInfo.elements[0];
    console.log(myForm1);               // <input type="text" name="userName"/>
    
    // 取得name为textName1的字段
    var textName2 = personInfo.elements["userPsd"];
    console.log(textName2);             // <input type="text" name="userPsd"/>
    
    // 取得name名相同的字段
    var radioNameList = personInfo.elements["radioName"]
    console.log(radioNameList);        // [RadioNodeList(2) [input, input, value: "on"]
</script>

2、共有的表单字段属性

除了 <fieldset> 元素外,所有的表单字段都有一组相同的属性。详情如下:

  • disabled:布尔值,表示当前字段是否被禁用。
  • form:指向当前字段所属表单的指针,只读。
  • name:单签字段的名称。
  • readOnly:布尔值,表示当前字段是否只读。
  • tabIndex:表示当前字段的切换(tab)序号。
  • type:当前字段的类型。
  • value:当前字段的值。

注意:<input> 和 <button> 元素的 type 属性是可以修改的,而 <select> 元素的 type 属性则是只读的。

3、共有的表单字段方法

(1)、focus() 方法

当前字段获取焦点时触发。

EventUtil.addHandler(window, "load", function(event){
    document.forms[0].elements[0].focus();// 将第一个表单的第一个表单字段设置为获取焦点
});

注意:以上代码,如果第一个表单字段是一个 <input> 元素,并且其 type 值为 “hidden”,那么以上代码会报错;如果使用了 CSS 的 display 和 visibility 属性隐藏了该字段,也会报错。

为了解决这个问题,HTML5 新增了一个 autofocus 属性。

--> autofocus 属性

  • IE9 及之前的版本不支持 <input> 标签的 autofocus 属性。
  • 使用 autofocus 属性,不用 JavaScript 就能使该字段自动获得焦点。
<input type="text" autofocus>

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

EventUtil.addHandler(window, "load", function(event){
    // 将第一个表单的第一个表单字段设置为获取焦点
    var element = document.forms[0].elements[0];
    if(!element.autofocus){
        element.focus();
    }
});

(2)、blur() 方法

当前字段失去焦点时触发。

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

(3)、change() 方法(★★★★★)

  • 对于 <input> 和 <textarea> 元素,在他们失去焦点 value 值改变时触发;
  • 对于 <select> 元素,在其选项发生改变时触发。

change() 方法经常用于验证用于在字段中输入的数据。

例如:校验账号输入的是否是手机号

<form>
    <span>账号</span><input type="text" name="account" placeholder="请输入手机号码" id="user_account"/><br>
    <span>密码</span><input type="password" name="password"/><br>
</form>
<script src="./methods/EventUtil.js"></script>
<script>
    // var userAccount = document.getElementById("user_account");
    var userAccount = document.forms[0].elements[0];
    
    EventUtil.addHandler(userAccount, "change", function(event){
        event = EventUtil.getEvent(event);
        var target = EventUtil.getTarget(event);
        var re = /^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$/;
        if(re.test(target.value)){
            target.style.border = "1px solid #0f0";
        }else{
            target.style.border = "1px solid #f00";
        }
    });
</script>

 

五、文本脚本

在 HTML 中,有两种方式来表现文本框:单行文本框 <input> 和 多行文本框 <textarea>。

尽量不要借助 DOM 来操作表单文本脚本,建议用直接操作 form 的方式来读写文本脚本:

var textbox = document.form[0].elements["textbox"];
alert(textbox.value);

textbox.value = "666";

// 这里不妨回忆一下,DOM 如何设置其元素的值的?
// 答案是:通过 setAttrbute() 方法。

1、单行文本框 \<input\>

  • type: 必须设置为“text”;
  • value:储存文本框的值,可读可写;
  • size:指定文本框中能够显示的字符数;
  • maxlength:指定文本框可以接受的最大的字符数。

maxlength 的作用顾名思义,size 的作用不甚明了,所以一起来探索一下:

<input type="text" size="0" maxlength="10" value="0"/>
<input type="text" size="1" maxlength="10" value="0"/>
<input type="text" size="5" maxlength="10" value="0"/>
<input type="text" size="10" maxlength="10" value="0"/>
<input type="text" size="11" maxlength="10" value="0"/>

 上述代码,都只能最多输入10个字符,由于 size 的大小不同,加载出来的效果如下:

执行结果: 

可见,size 只影响可展示内容的范围(面积)。

2、多行文本框 \<textarea\>

  • rows:指定文本框的字符行数;
  • cols:指定文本框的字符列数(类似于 <input> 元素的 size 特性);
  • value:储存文本框的值,可读可写。
<textarea cols="3" rows="3">0</textarea>
<textarea cols="6" rows="6">0</textarea>

 上述代码,执行效果如下:

<textarea> 与 <input> 的不同之处在于:

  • <textarea> 的初始值必须要放在 <textarea> 和 </textarea> 之间;
  • 不能在 HTML 中给 <textarea>指定最大的字符数。

3、选择文本 \<select\>

单行文本框 <input> 和 多行文本框 <textarea> 都支持 select 事件。

(1)、在文本框获得焦点时自动选择其所有文本(★★★★★)

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

(2)选择部分文本

所有的文本框都包含一个 setSelectionRange() 方法,

setSelectionRange() 方法接受两个参数:要选择的第一个字符的索引 和 要选择的最后一个字符之后的字符的索引(类似于 substring() 方法的两个参数)。

4、过滤输入

(1)、屏蔽字符(★★★★★)

有时候,我们需要用户输入的文本中包含或者不包含某些字符,怎么办?

因为响应文本框中输入字符操作的是 keypress 事件,所以我们可以通过阻止 keypress 事件的默认行为来屏蔽一些字符。

①、屏蔽所有字符——文本框变为只读

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);
    var re = /\d/;
    if(!re.test(String.fromCharCode(charCode))){
        EventUtil.preventDefault(event);
    }
});

上述代码中,EventUtil.getCharCode(event) 实现了跨浏览器获取字符编码。然后,使用 String.formCharCode() 方法将字符编码转为字符串,最后使用正则表达式检测该字符串,从而确定用户输入的值是符合标准的。②③、(兼容版)屏蔽特定字符

③、(兼容版 + 防Ctrl版)屏蔽特殊字符

// 当前文本框只允许输入数值
EventUtil.addHandler(textbox, "keypress", function(event){
    event = EventUtil.getEvent(event);
    var target = EventUtil.getTarget(event);
    var charCode = EventUtil.getCharCode(event);
    var re = /\d/;
    if(!re.test(String.fromCharCode(charCode)) && charCode > 9 && !event.ctrlKey){
        EventUtil.preventDefault(event);
    }
});

(2)、操作剪切板

①、剪贴板事件

  • beforecopy:在复制前触发;
  • copy:在剪切前触发;
  • cut:剪切时触发;
  • beforepaste:在粘贴前触发;
  • paste:粘贴时触发。

②、访问剪切板的数据

在 IE 中,clipboardData 对象是 window 对象的属性,在 Firefox 4+、Safari 和 Chrom 中,clipboardData 对象是相应 event 的属性。

clipboardData 对象包含三个方法:

  • getData() 方法:从剪切板中获取数据。它接受一个参数:获取数据的格式。
  • setData() 方法:将指定内容放在剪切板中。它接受两个参数:数据类型 和 要放在剪切板中的文本。
  • clearData() 方法:清除剪切板中的数据。

使用 clipboardData 对象访问剪切板的数据的跨浏览器版实现,请参阅:https://blog.csdn.net/mChales_Liu/article/details/106541683

(3)、 如何确保粘贴到文本框中的文本包含某些字符,或者符合某种格式要求呢?(★★★★★)

通过访问剪切板的 paste 事件即可。

例如:将剪切板中的内容粘贴到一个只接受数值的文本框中

EventUtil.addHandler(textbox, "paste", function(event){
    event = EventUtil.getEvent(event);
    var text = EventUtil.getClipboardText(event);
    var re = /^\d*$/;
    if(!re.test(text)){
        EventUtil.preventDefault(event);
    }
});

由于并非所有的浏览器都支持访问剪贴板,所以更简单的做法是屏蔽一或多个剪贴板操作。在 IE、Safari、Chrom 和 Firefox 3+ 中,可以通过阻止剪贴板的 copy、cut 和 paste 事件来阻止对剪贴板的默认行为,在 Opera 中,则需要阻止那些会触发这些事件的按键操作,同时还要阻止在文本框中显示上下文菜单。

(4)、自动切换焦点(★★★★★

什么是自动切换焦点呢?就是:在用户填写完当前字段后,自动将焦点切换到下一个字段。通常,在自动切换焦点之前,必须知道用户已经输入了即定长度的数据(例如电话号码)。

举个栗子:美国的电话号码通常分为区号、局号和另外 4 位数字三部分,为取得完全的电话号码,很多网页中都会提供三个文本框,采用自动切换焦点的技术实现,增强了表单的易用性。代码实现如下:

<form>
    <h3>美国电话:</h3>
    <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>
<script src="./methods/EventUtil.js"></script>
<script>
    // 自动切换焦点的封装
    (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);
    })();
</script>

(5)、HTML5 约束验证 API

以下功能在支持 H5 的浏览器(Firefox 4+、Safari 5+、Chrom 和 Opera 10+)中有效。

①、必填字段——required

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

②、其他输入类型

<input type="类型">

新增的输入类型如下:

email、url、number、range、datetime、datetime-local、date、month、week、time等。

③、数值范围

对于所有的数值类型的输入元素,都可以指定 min(最小值)、max(最大值)和 step(倍数)属性的值,而且在 JavaScript 中都可以直接通过元素访问或修改这些属性的值。

例如:想让用户只能输入 0 到 100 的值,而且这个值只能是 5 的倍数:

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

④、输入模式——pattern

pattern 属性的值是一个正则表达式,用于匹配文本框中的值。

例如:只允许输入数值

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

⑤、检测表单中的某个字段是否有效

表单中的某个字段满足两个条件时,才算是有效的:

  • 必填字段中必须有值
  • 字段中的值必须与 pattern 属性的要求匹配

使用 checkValidity() 方法可以检测表单中的某个字段是否有效。所有表单字段都有这个方法,有效返回 true,无效返回 false。

// 检测整个表单是否有效
if(document.forms[0].checkValidity()){
    // 表单有效,继续
} else {
    // 表单无效
}

⑥、禁用验证——novalidate 和 formnovalidate

--> 设置整个表单不必进行表单验证——novalidate

<form method="post" action="userInfo.php" novalidate>
    // ...
</form>

 使用 JavaScript 这样设置这个值:

document.forms[0].noValidate = true;

--> 设置某个提交按钮不必进行表单验证——formnovalidate

<form method="post" action="userInfo.php">
    // ...
    <input type="submit" value="提 交1">
    <input type="submit" value="提 交2" name="btnNoValidate" formnovalidate>
</form>

使用 JavaScript 这样设置这个值:

document.forms[0].elements["btnNoValidate"].formNoValidate = true;

 

六、选择框脚本

选择框是通过<select> 和 <option> 元素创建的控件。

1、\<select\> 元素

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

  • multiple:布尔值,表示是否允许多项选择,等价于 HTML 中的multiple 特性。
  • options:控件中所有 <option> 元素的 HTMLColletion。
  • selectedIndex:基于 0 的选中项的索引,如果没有选中项,则值为 -1。
  • size:选择框中可见的行数,等价于 HTML 中的 size 特性。
  • value:
    • 如果没有选中项,则选择框的 value 值为空字符串。
    • 如果有一个选中项,而且该项的 value 特性已经在 HTML 中指定,则选择框的 value 值等于选中项的 value 值。
    • 如果有一个选中项,但是该项的 value 特性在 HTML 中未指定,则选择框的 value 值等于该项的文本。
    • 如果有多个选项,则选择框的 value 属性将依据前两条规则取得第一个选中项的值。
  • add(newOption, relOption):向控件中插入新的 <option > 元素,其位置在相关项(relOption)之前。
  • remove(index):一处给定位置的选项。

2、\<option\> 元素

每个 <option> 元素都有一个 HTMLOptionElement 对象,HTMLOptionElement 对象有以下属性:

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

在操作选项时,建议最好使用特定于选项的属性,而不是使用标准的 DOM 技术。因为所有的浏览器都支持这些特定于选项的属性,但是用 DOM 操作时,实际的交互方式会因浏览器而异。比如:

var selectbox = document.forms[0].elements["location"];
// 不推荐
var text = selectbox.options[0].firstChild.nodeValue;
var value = selectbox.options[0].getAttribute("value");
// 推荐
var text = selectbox.options[0].text;
var value = selectbox.options[0].value;

 

七、表单序列化

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

首先,我们来了解下在表单提交期间,浏览器是怎样将数据发送给服务器的。

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

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

表单序列化的代码实现:

Object.prototype.serialize = function(){
    var res = [],	//存放结果的数组
        current = null,	//当前循环内的表单控件
        i,	//表单NodeList的索引
        len, //表单NodeList的长度
        k,	//select遍历索引
        optionLen,	//select遍历索引
        option, //select循环体内option
        optionValue,	//select的value
        form = this;	//用form变量拿到当前的表单,易于辨识
    
    for(i=0, len=form.elements.length; i<len; i++){
        current = form.elements[i];

        //disabled表示字段禁用,需要区分与readonly的区别
        if(current.disabled) continue;
        
        switch(current.type){
            //select控件
            case "select-one":
            case "select-multiple":
                if(current.name && current.name.length){
                    console.log(current);
                    for(k=0, optionLen=current.options.length; k<optionLen; k++){
                        option = current.options[k];
                        if(option.selected){
                            optionValue = "";
                            if(option.hasAttribute){
                                optionValue = option.hasAttribute('value') ? option.value : option.text
                            }else{
                                // 兼容 IE,使用 specified 属性检测是否已规定某个属性
                                optionValue = option.attributes('value').specified ? option.value : option.text;	
                            }
                            res.push(encodeURIComponent(current.name) + "=" + encodeURIComponent(optionValue));
                        }
                    }
                }
                break;

            //可忽略控件处理
            case "file":	//文件输入类型
            case "submit":	//提交按钮
            case "button":	//一般按钮
            case "image":	//图像形式的提交按钮
            case "reset":	//重置按钮
            case undefined:	//未定义
                break;
            
            case "radio":// 单选框
            case "checkbox":// 复选框
                if(!current.checked) break;
                /* 执行默认操作 */

            default:
                // 不包含没有名字的表单控件
                if(current.name && current.name.length){
                    res.push(encodeURIComponent(current.name) + "=" + encodeURIComponent(current.value));
                }
        }
    }
    return res.join("&");
}

 

八、富文本编辑

富文本编辑又称为WYSIWYG(What you see is what you get)),所见即所得。

1、富文本编辑的本质

富文本编辑的本质是:在页面中嵌入一个包含空 HTML 页面的 iframe。通过设置 designMode 属性,这个空白的 HTML 页面可以被编辑,而编辑对象则是该页面 <body> 元素的 HTML 代码。

designMode 属性有两个值,off(默认值)和 on。在设置为 on 时,整个文档会变成富文本编辑。

<iframe name="richedit" style="width: 100px;height: 100px;" src="./iframe.html"></iframe>
<script src="./methods/EventUtil.js"></script>
<script>
    EventUtil.addHandler(window, "load", function(){
        frames["richedit"].designMode = "on";
    });
</script>

代码执行后,报错:form02.html:92 Uncaught DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame. (尚未解决,请大佬留言。

2、使用 contenteditable 属性使页面中的元素变成富文本编辑

contenteditable 属性有三个可选值:

  • true:打开
  • false:关闭
  • inherit:从父元素那里继承。

给页面中的任何元素添加 contenteditable 属性后,用户立即就可以编辑该元素(富文本编辑)了。

<div contenteditable></div>

 可以通过 JavaScript 来控制元素的 contenteditable 属性:

<div id="richedit" contenteditable>666</div>
<script>
    var myDiv = document.getElementById("richedit");
    myDiv.contentEditable = false;
</script>

3、操作富文本

(1)、使用 document.execCommand() 方法操作富文本

document.execCommand() 方法接收 3 个参数:要执行的命令名称、表示浏览器是否应该为当前命令提供用户界面的一个布尔值(为了兼容 Firefox,该参数始终设置为 false) 和 执行命令必须的一个值(如果不需要值则传递 null)。

不同浏览器支持的富文本的预定义命令不一样,下面列出了那些被广泛支持的富文本的预定义命令:

预定义命令值(第三个参数)说明
backcolor颜色字符串设置文档的背景颜色
boldnull将选择的文本转换为粗体
copynull将选择的文本复制到剪贴板
createlinkURL 字符串将选择的文本转换成一个链接,指向指定的 URL
cutnull将选择的文本剪切到剪贴板
deletenull删除选择的文本
fontname字体名称将选择的文本修改为指定的字体
fontsize1 ~ 7将选择的文本修改为指定的字体大小
forecolor颜色字符串将选择的文本修改为指定的颜色
formatblock要包围当前文本块的 HTML 标签(比如:<h1>)使用指定的 HTML 标签来格式化选择的文本块
indentnull缩进文本
inserthorizontalrulenull在插入字符处插入一个 <hr> 元素
insertimage图像的 URL在插入字符处插入一个图像
insertorderedlistnull在插入字符处插入一个 <ol> 元素
insertunorderedlistnull在插入字符处插入一个 <ul> 元素
insertparagraghnull在插入字符处插入一个 <p> 元素
italicnull将选择的文本转换为斜体
justifycenternull将插入光标所在的文本块居中对齐
justifyleftnull将插入光标所在的文本块左对齐
outdentnull凸排文本(减少缩进)
pastenull将剪贴板中的文本粘贴到选择的文本
removeformatnull移除插入光标所在文本块的块级格式(这是撤销 formatblock 的操作)
selectallnull选择文档中所有的文本
underlinenull为选择的文本添加下划线
unlinknull移除文本的链接(这是撤销 createlink 的操作)

 注意:

与剪贴板有关的富文本预定义命令在不同的浏览器中差异极大,Opera 没有实现,Firefox 默认禁用了他们,Safari 和 Chrome 仅仅实现了 cut 和 copy,没有实现 paste。

对于非剪贴板的富文本预定义命令,虽然所有浏览器都支持,但是这些命令产生的 HTML 效果仍有很大的不同。

既然各大浏览器对 execCommand() 方法这么不友好,不妨用下面的 DOM 系列方法代替它来操作富文本。

(2)、使用 DOM 的一系列方法操作富文本

在富文本编辑其中,使用框架 iframe 的 getSelection() 方法,可以确定时机选择的文本。

调用 getSelection() 方法,会返回一个 Selection 对象,这个对象的属性没有多少有用的信息,所以这里只学习它的方法:

  • addRange(range):将指定的 DOM 范围添加到选区中。
  • collapse(node, offset):将选区折叠到指定节点中的相应的文本偏移位置。
  • collapaseToEnd():将选区折叠到终点位置。
  • collapaseToStart():将选区折叠到起点位置。
  • containsNode(node):确定指定的节点是否包含在选区中。
  • deleteFromDocument():从文档中删除选区中的文本,与 document.execCommand("delete", false, null) 命令的结果相同。
  • extend(node, offset):通过将 focusNode 和 focusOffset 移动到指定的值,来扩展选区。
  • getRangeAt(index):返回索引对应的选区中的 DOM 范围。
  • removeAllRanges():从选区中移除所有 DOM 范围。实际上,这样会移除选区,因为选区中至少要有一个范围。
  • removeRange(range):从选区中移除指定的 DOM 范围。
  • selectAllChildren(node):清除选区,并选择指定节点的所有子节点。
  • toString():返回选区所包含的文本内容。

使用案例:

<iframe name="richedit" style="width: 100px;height: 100px;" src="./iframe.html"></iframe>
<script>
    var selection = frames["richedit"].getSelection();
    var selsctedText = selection.toString();
</script>

4、表单与富文本

富文本不是表单,富文本使用的是 iframe 而非表单控件,所以富文本编辑器中的 HTML 不会被自动提交给服务器,需要我们手动获取提交。

如何手动获取并提交 iframe 中的数据呢?

通常,可以添加一个隐藏的表单字段,让它得值等于从 iframe 中提取出来的 innerHTML 的值。

 

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值