表单脚本

本章主要介绍:表单、文本框验证与交互、使用其他表单控制。这一章会继续沿用上一章 封装的 EventUtil 对象(具体参考前面的事件)

JavaScript最初的一个应用,就是分担服务器处理表单的责任,打破处处依赖服务器的局面

一、表单的基础知识

JavaScript中,表单对应的是 HTMLFormElement 类型。HTMLFormElement 继承了 HTMLElement。HTMLFormElement 有自己下列独有的属性和方法

  • acceptCharset:服务器能够处理的字符集:等价于HTML中的 accpet-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>元素 引用的方式有好几种:最常见的方式是 使用 getElementById() 方法找到它

var form = document.getElementById('myForm')

其次,通过document.forms 获取页面中所有的表单,再通过 索引 或 name值 来访问

var firstForm = document.forms[0] // 获取页面中的第一个表单
var myForm = document.forms['form2'] // 获取页面中 名称为 “form2” 的表单

在较早的浏览器或者那些支持向后兼容的浏览器中,也会把每个设置了 name 特性的 表单作为属性保存在 document 对象中。通过document.form2 可以访问到名为 "form2" 的表单。

1.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)

  // if () { 
  // 阻止默认事件
  EventUtil.preventDefault(event)
  // }
})

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

var from = document.getElementById('myForm')

// 提交表单
form.submit()

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

提交表单时可能出现的最大问题,就是重复提交表单。为此,可以在在第一次提交表单后就禁用提交按钮,或者利用 onsubmit 事件处理程序取消后续的表单提交操作。

1.2、重置表单

使用 type 特性值为 “reset”的 <input> 或 <button> 都可以创建重置按钮,

<!-- 通用重置按钮 -->
<input type="reset" value="Reset Form">

<!-- 自定义重置按钮 -->
<button type="reset">Reset From</button>

也可以使用 JavaScript 的方式 来重置表单

var form = document.getElementById('myForm')

// 重置表单
from.reset()

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

/* 阻止重置表单操作 */
var form = document.getElementById('myForn')

form.onreset = function(event) {
  event.preventDefault()
}

1.3、表单字段

每个表单都有一个 elements 属性,该属性是表单中所有表单元素(字段)的集合。可以按照位置和 name 特性来访问它们,

var form = document.getElementById('myForm')

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

// 取得表单中name 为 textbox1的字段
var field2 = form.elements['textbox1']

// 取得表单中包含的字段的数量
var fieldCount = from.elements.length

如果使用 name 实现访问元素时,多个表单控件的 name 相同,就会返回一个 以改name 命名的 NodeList,然后可以通过 索引 访问这个集合中的元素
如下

<input type="radio" name="color" value="red"> red
<input type="radio" name="color" value="cyan"> cyan
<input type="radio" name="color" value="violet"> violet

<script>
  var colors = document.forms[0]['color']
  console.log(Object.prototype.toString.call(colors))
  console.log(colors[0]) // 第一个 单选框
</script>
1.3.1、共有的表单字段属性

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

  • 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"

避免多次提交,最常见的解决方案,就是在第一次单机后就禁用提交按钮。

//  避免多次提交表单
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 事件,意味着会在提交发生之间禁用按钮,结果永远都不会提交表单


除了 <fieldset> 之外,所有表单字段都有 type 属性。对于 <input> 元素,这个值等于 HTML 特性 type 的值。对于其他元素,这个 type 属性的值如下表所列:

说明 HTML示例 type 属性的值
单选列表 <select>...</select> "select-one"
多选列表 <select multiple>...</select> "select-multiple"
自定义按钮 <button>...</button> "submit"
自定义非提交按钮 <button type="button">...</button> "button"
自定义重置按钮 <button type="reset">...</button> "reset"
自定义提交按钮 <button type="submit">...</button> "submit

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

1.3.2、共有的表单字段方法

每个表单字段都有两个方法:focus() 和 blur()

focus() 方法用于将浏览器的焦点设置到表单字段,级激活表单字段,使其可以响应键盘事件。为此,可以侦听页面的 load 事件,并在该事件发生时在表单的第一个字段上调用 focus() 方法,如下:

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

需要注意的是:如果 focus() 方法的对象是一个 type="hidden" 的 <input> 元素的话,那么以上代码会导致错误。另外,如果使用 CSS 的 display 和 visibility 属性隐藏了该字段,同样也会导致错误

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

<input type="text" autofocus />

可以通过 autofocus 属性获取 元素上面的 autofocus 的状态,在支持的浏览器中如果设置了为true


blur() 作用是从元素上移走焦点

document.forms[0].elements[0].blur()
1.3.3、共有的表单字段事件

所有的表单字段都支持下列三个事件

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

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, "input", function(event) { // value 值变化时
  event = EventUtil.getEvent(event)
  var target = EventUtil.getTarget(event)
  console.log(target.value)
  // 验证用户是否输入的是数字
  if (/[^\d]/.test(target.value)) {
    console.log(1)
    target.style.backgroundColor = 'red'
  } else {
    target.style.backgroundColor = ''
  }
})

因为 change 事件必须 在value值改变且失去焦点才会触发,所以这里用 input 事件来实时监听

二、文本框脚本

在 HTML 中,有两种方式来表现文本框,<input> 、<textarea> 两种元素

<input>

  • 通过设置 size 特性,可以指定文本框中能够显示的字符数
  • 通过value特性,可以设置文本框的初始值
  • 通过maxlength特性则用于指定文本框 可以接受的最大字符数

<textarea>

  • rows特性指定文本框的字符行数
  • cols 特性指定文本框的字符列数

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

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

值得注意的时:在操作 value 属性时,不建议使用 标准的 DOM 方法(setAttribute()),这样对 value 属性所作的修改,不一定会反映在 DOM 中

2.1、选择文本

上诉两种文本框都支持 select() 方法,这个方法用于选择文本框中的所有文本。在调用 select() 方法时,大多数浏览器都会将焦点设置到 文本框中

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

在文本框获得焦点时选择其所有文本,这是一种非常常见的做法,特别是在 文本框包含默认值的时候。因为这样做可以让用户不必一个一个地删除文本。

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

  target.select()
})
2.1.1、select 事件

与 select() 方法对应的,有一个 select 事件,在选择了文本框的文本是,就会触发select事件,而在IE8及更早版本中,只要用户选择了一个字母(不必释放鼠标),就会触发select 事件。另外,在调用 select() 方法时也会触发 select 事件。

var textbox = document.forms[0].elements['textbox1']
EventUtil.addHandler(textbox, "select", function(event) {
  console.log("select text")
})

当用户选择 textbox 中的文本时,就会触发这个事件 ,输出 select text

2.1.2、取得选择的文本

通过 select 事件我们可以知道用户什么时候选择了文本,但任然不知道用户选择了什么文本。 HTML5 通过了一些 扩展方案解决了这个问题。添加了两个属性:selectionStart 和 selectionEnd。 这两个属性中保存的是基于 0 的数值,表示所选择文本的范围(即文本选区开头和结尾的偏移量)。

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

// 获取选区的文本
var textbox = document.forms[0].elements["textarea"]
EventUtil.addHandler(textbox, "select", function(event) {
  // 调用方法
  console.log("select Text :" +  getSelectedText(textbox))
})

IE8及之前不支持这两个属性而是提供了另一种方案

IE8及更早的版本中有一个 document.selection 对象,其中保存着用户在整个文档范围内选择的文本信息,与 select 事件一起使用的时候,可以假定是用户选择了文本框中的文本。要取得选择的文本,首先必须创建一个范围,然后再将文本从其中提取出来。

function getSelectedText(textbox) {
  if (typeof textbox.selectionstart === 'number') {
    return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd)
  } else if(document.selection) { // 针对 IE
    return document.selection.createRange().text
  }
}
2.1.3、选择部分文本

HTML5 也为选择文本框中的部分文本提供了解决方案,所有文本款都有一个 setSelectionRange() 方法,这个方法接收两个参数:要选择的第一个字符的索引、选择的最后一个字符之后的字符的索引

var textbox = document.forms[0].elements["textarea"]

textbox.value = 'Hello World!'

textbox.select() // 使当前 获取焦点

// 选择所有文本
textbox.setSelectionRange(0, textbox.value.length)

// 选择前3个字符
textbox.setSelectionRange(0, 3)

// 选择第 4-6 个字符
textbox.setSelectionRange(4, 7)

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


IE8及更早版本,要选择文本框中的部分文本,

  1. 首先使用 IE 在所有文本框是 提供的 createTextRange() 方法创建一个范围,
  2. 然后 使用 moveStart() 和 moveEnd() 这两个范围方法将范围移动到位
  3. 在调用这两个方法之前,还必须使用 collapse() 将范围折叠到文本框的开始位置
  4. 使用 范围的 select() 方法选择文本
var textbox = document.forms[0].elements["textarea"]

textbox.value = 'Hello World!'

var range = textbox.createTextRange()

// 选择所有文本
range.collapse(true)
range.moveStart('character', 0)
range.moveEnd('character', textbox.value.length)
range.select()

// 选择前3个字符
range.collapse(true)
range.moveStart('character', 0)
range.moveEnd('character', 3)
range.select()

实现跨浏览器编程,结合上诉两种方案组合

function selectText(textbox, startIndex, endIndex) {
  if (textbox.setSelectionRange) {
    textbox.setSelectionRange(startIndex, endIndex)
  } else if(textbox.createTextRange) { // IE
    var range = textbox.createTextRange() // 创建范围
    range.collapse(true) // 折叠范围
     // 移动范围
    range.moveStart('character', startIndex)
    range.moveEnd('character', endIndex)
    range.select() // 选择文本
  }

  // 获取焦点
  textbox.focus()
}

可以像下面这样使用这个方法


var textbox = document.forms[0].elements['textarea']

textbox.value = 'Hello World'
// 选择所有文本
selectText(textbox, 0, textbox.value.length)

2.2、过滤输入

我们经常会要求用户在文本框中输入特定的数据,或者输入特定格式的数据。综合运用事件和DOM手段,可以将普通的文本框转换成能够理解用户输入数据的功能型控件。

2.2.1、屏蔽字段

响应向文本框中插入字符操作的是 keypress 事件。因此,可以通过阻止这个事件的默认行为来屏蔽此类字符。

EventUtil.addHandler(textbox, 'keypress', function(event) {
  event = EventUtil.getEvent(event)
  EventUtil.preventDefault(event)
})

如果只想屏蔽特定字符,则需要检测 keypress 事件对应的字符编码,然后再决定如何响应。

// 只允许输入数值。
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)
  }
})

仅考虑屏蔽不是数值的字符还不够,还要避免屏蔽一些极为常用和必要的键。所幸的是,要检测这些键并不困难。
在Firefox中,所有由非字符键触发的 keypress 事件对应的字符编码为0
在 Safari 以前的版本中,对应的字符编码全部为8
为了让代码更通用,只要不屏蔽那些字符编码小于10的键即可

// ...
 if (!(/\d/.test(String.fromCharCode(charCode))) && charCode > 9) {
    EventUtil.preventDefault(event)
  }

除此之外还有一个文本需要处理:复制、粘贴及其他操作还有用到 Ctrl 键。在除IE之外的所有浏览器中,前面的代码也会屏蔽 Ctrl + C、Ctrl + V,以及其他使用 Ctrl 的组合键。因此最后还要添加一个检测条件,以确保用户没有按下啊 Ctrl 键。

if (! (/\d/.test(String.fromCharCode(charCode))) && charCode > 9 && !event.ctrlKey) {
    EventUtil.preventDefault(event)
}
2.2.2、操作剪贴板

IE 是第一个支持与剪贴板有关事件,以及通过 JavaScript 访问剪贴板数据的浏览器, HTML5后来也把剪贴板事件纳入了规范

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

由于没有针对剪贴板操作的标准,这些事件及相关对象会因浏览器而异。在Safari、Chrome 和 Firefox中,beforecopy、beforecut、beforepaste 事件只会在显示在针对文本框的上下文菜单(预期发生剪贴板事件)的情况下触发。但是,IE则会在触发 copy、cut和paste事件之前先触发这些事件。至于 copy、cut和paste事件,只要是在上下文菜单中选择了相应选项,或者使用了相应的键盘组合键,所有浏览器都会触发它们。
在实际的事件发生之前通过 beforecopy、beforecut、beforepaste事件可以在像剪贴板发送数据,或者从剪贴板取得数据之前修改数据。不过,取消这些事件并不会取消对剪切板的操作——只有取消 copy、cut、paste 事件,才能阻止响应操作发生。
要访问剪贴板中的数据,可以使用 clipboardData 对象:在IE中,这个对象是 window 对象的 属性而在 Firefox 4+、Safari 和 Chrome 中,这个对象是相应 event 对象的属性。但是,在Firefox、Safari、Chrome 中,只有在处理剪贴板事件期间,clipboardData对象才有效,这是为了防止对剪贴板的未授权访问;在IE中,则可以随时访问 clipboardData 对象。为了确保跨浏览器兼容,最好只在发生剪贴板事件期间使用这个对象。

clipboardData 对象有三个方法

  • getDate() 用于从剪贴板中获取数据,

    • 接受一个参数,即要取得的数据格式,
      在IE中,有两种数据格式:“text”、“URL”
      在Firefox、Safari、Chrome中,这个参数是一种MIME类型,可以使用“text”代表“text/plain”
  • setData() 设置数据

    • 数据类型
      IE支持:text、URL
      而 Safaru 和 Chrome 只支持 MIME 类型,不能代替
    • 放在剪贴板中的文本。
  • clearData():清除数据

在成功将文本放到剪贴板中后,都会返回true;否则返回false

为了弥补这些差异,我们可以项 EventUtil 中再添加下列方法:

var EventUtil = {
  // 获取剪贴板中的 文本
  getClipboardText: function(event) {
    var clipboardData = (event.clipboardData || window.clipboardData)
    return clipboardData.getData('text')
  }, 

  // 设置 剪贴板中的文本
  setClipboardText: function(event, value) {
    if (event.clipboardData) return event.clipboardData.setData('text/plain', value)
    else if(window.clipboardData) return window.clipboardData.setData('text', value)
  }
}

在需要确保粘贴到文本框中的文本中包含某些字符,或者符合某种格式要求时,能够访问剪贴板是非常有用的。在paste事件中,可以确定剪贴板中的事件是否有效

EventUtil.addHandler(textbox, 'paste', function(event) {
  event = EventUtil.getEvent(event)
  var text = EventUtil.getClipboardText(event)
  console.log(1)
  if (!/^\d*$/.test(text)) {
    EventUtil.preventDefault(event)
  }
})

如上代码只会在,粘贴板中文本内容只包含数字的时候,才能粘贴

由于并非所有浏览器都支持访问剪贴板,所以更简单的做法是屏蔽一或多个剪贴板操作

2.3、自动切换焦点

使用 JavaScript 可以从多个方面增强表单字段的易用性。其中,最常用的一种方式就是在用户填写完当前字段时,自动将焦点切换到下一个字段。

例如,美国的电话号码通常分为三个部分:区号、局号、另外4位数字。为取得完整的电话号码,很多网页中都会提供下列3个文本框,如下DOM结构

<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">

为了增强易用性,同时加快数据输入,可以在前一个文本框中的字符达到最大数量后,自动将焦点切换到下一个文本框

function tabForward(event) {
  event = EventUtil.getEvent(event)
  var target = EventUtil.getTarget(event) // 获取当前DOM元素

  if (target.value.length == target.maxLength) { // 如果 输入完毕(最大长度)
    var form = target.form // 获取 当前字段的 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)

不过请记住,这些代码只适用于前面给出的标记,没有考虑隐藏字段

2.4、HTML5约束验证API

为了在将表单提交到服务器之前验证数据,HTML5新增了一些功能。有了这些功能,几遍JavaScript被禁用或者由于种种原因未能加载,也可以确保基本的验证

2.4.1、必填字段

required 属性

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

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

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

另外,使用下面这行代码可以测试浏览器是否支持required属性

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

对于空着的必填字段,不同浏览器有不同的处理方式。Firefox4和Opera11会阻止表单提交并在相应字段下发弹出帮助框,而Safari5-、Chrome9-则什么也不做,而且也不会阻止表单提交。现在的浏览器以便都会阻止提交

2.4.2、其他输入类型

HTML5 为<input> 元素的 type 属性又增加了几个值。“email”、“url”是两个得到支持最多的类型,各浏览器也都给他们增加了定制的验证机制。

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

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


要检查浏览器是否支持这些类型,可以在 JavaScript中创建一个 <input>元素的type设置为其中一个,再检测这个属性的值

var input = document.createElement("input")
input.type = "email"

var isEmailSupported = (input.type == "email")

设置特定的输入类型并不能阻止用户输入无效的值,只是应用某些默认的验证而已。

2.4.3、数值范围

除了上诉两个之外,HTML5 还定义了另外几个输入元素。这几个元素都要求填写某种基于数字的值:number、range、datetime、datetime-local、date、month、week、time

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

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

在不同的浏览器中,可能会也可能不会看到能够自动递增和递减的数值调节按钮(向上和向下按钮)

2.4.4、输入模式

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

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

注意,模式的开头和末尾不用加 ^ 和 $符号(假定已经有了)。这两个符号表示输入的值必须从头到尾与模式匹配。

与其他输入类型相似,指定 pattern 也不能阻止用户输入无效的文本。这个模式应用给值,浏览器来判断值是有效,还是无效。

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

var pattern = document.forms[0].elements['count'].pattern

使用以下代码可以检测浏览器是否支持 pattern 属性

var isPatternSupported = "pattern" in document.createElement("input")
2.4.5、检测有效性

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

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

要检测整个表单是否有效,可以在表单自身调用 checkValidity() 方法。如果所有表单字段都有效,这个方法返回 true;即使有一个字段无效,这个方法也返回false

if (document.form[0].checkValidity()) {
  // 表单有效
} else {
  // 表单无效
}

与 checkValidity() 方法简单地告诉你字段是否有效相比,validity 属性则会告诉你为什么字段有效或无效。这个对象中包含一系列属性,每个属性会返回一个 布尔值。

  • customError:如果设置了 setCustomValidity(),则返回 true,否则返回 false。
  • patternMismatch:如果值与指定的pattern 属性不匹配,返回 true
  • rangeOverflow:如果值比max值大,返回 true
  • rangeUnderflow:如果值比 min 值小,则返回 true
  • stepMisMatch:如果 min 和 max 之间的步长值不合理,返回true
  • tooLong:如果值的长度超过了 maxlength 属性指定的长度,返回 true。有的浏览器(如Firefox4)会自动约束字符数量,因此这个值可能永远返回 false
  • typeMismatch:如果值不是"mail" 或 "url" 要求的格式,返回 true
  • valid:如果这里的其他属性都是false,返回true。cjeckValidity() 也要求相同的值。
  • valueMissing:如果标注为 required 的字段中没有值,则返回 true。

因此,要想得到更具体的信息,就应该使用 validity 属性来检测表单的有效性。

if (input.validity.valueMissing) {
  alert('please specify a value')
} else if (inout.validity.typeMismatch) {
  alert('please enter an email address.')
} else {
  alert('value is invalid')
}
2.4.6、禁用验证

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

<form method="post" action="signup.php" novalidate>

</form>

在 JavaScript中使用 noValidate 属性可以去的或设置这个值,如果这个属性存在,值为 true
如果不存在,值为 false。

document.forms[0].noValidate = true // 禁用表单

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

<form method="post" action="signup.php">
  <input type="submit" value="submit" />
  <input type="submit" value="Non-validating Submit" formnovalidate />
</form>

三、选择框脚本

选择框是通过<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-mutiple",这取决于 HTML中有没有 multiple 特性。选择框的 value 属性由当前选中项决定,相应规则如下:

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

如上DOM结构:

  • 如果用户选中了第一项那么值就是 Sunnyvale, CA
  • 如果用户选中了第二项,则选择框的值是 空字符串
  • 如果选中第三个,则选择框的值是 Austraila

在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

选择框的 change 事件 与其他表单字段的 change 事件触发的条件不一样。其他表单字段的 change 事件是在值被修改且焦点离开当前字段时触发,而选择宽的 change 事件只要选中了选项就会触发。

3.1、选择选项

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

var selectedOption = selectbox.options[selectbox.selectedIndex]

获取后可以像下面这样显示该选项的信息

var selectbox = document.forms[0].elements[0]

var selectedIndex = selectbox.selectedIndex
var selectedOption = selectbox.options[selectedIndex]
var selectedValue = selectedOption.value

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

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

selectbox.options[0].selected = true

设置选项的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) {
      return.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 += 'selectedIndex:' + selectedOptions[i].index + '\nSelected value:' + selectedOptions[i].value
}
console.log(message)

3.2、添加选项

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

第一种方式就是使用如下所示的DOM方法

var newOption = document.createElement('option')
newOption.appendChild(document.createTextNode('option tex'))
newOption.setAttribute('value', 'option value')

selectbox.appendChild(newOption)

第二种方式是使用 Option 构造函数来创建新选项,构造函数接受两个参数:文本(text)、值(value)

var newOption = new Option('Option text', 'Option value')
selectbox.appendChild(newOption) // 在 IE8 及指甲钳版本中有问题

第三种方式是使用 选择框的 add() 方法,接受两个参数:要添加的新选项、将位于新选项之后的选项。如果想在最后添加一个选项,第二个参数设置为 null;在IE对 add() 方法的实现中,第二个参数是可选的,如果指定,该参数必须是新选项之后的选项的索引。兼容DOM的浏要求必须指定第二个参数,因此如果要编写跨浏览器代码,需要为第二个参数传入 undefined,即可。

var newOption = new Option('option text', 'option value')
selectbox.add(newOPtion, undefined) // 最佳方案

3.3、移除选项

与添加选项类似,移除选项的方式也有很多种

  • 使用 removeChild() 的方法
selectbox.removeChild(selectbox,options[0]) // 移除第一个选项
  • 使用选择框的 remove() 方法。这个方法接受一个参数,即要移除选项的索引
selectbox.remove(0) // 移除第一个选项
  • 将相应选项设置为 null。(这种方式也是 DOM 之前浏览器的遗留机制)
selectbox.options[0] = null // 移除第一个选项

要移除选择框中所有的项,可以迭代所有选项并移除它们

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

3.4、移动和重排选项

在DOM标准出现之前,将一个选择框中的选项移动到另一个选择框中是非常麻烦的。使用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]

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

selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index+2])

四、序列化表单

随着 Ajax 的出现,表单序列化已经成为一种常见需求。在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) { // 如果有 name 属性 并且 有值
          for (j = 0, optLen = field.options.length; j < optLen; j++) { // 遍历 所有 option
            option = field.options[j] 
            if (option.selected) { // 如果当前选项被 选择
              optValue = ''
              if (option.hasAttribute) { // 如果支持 hasAttribute() 方法
                optValue = (option.hasAttribute('value') ? option.value : option.text) // 查找是否存在 value 属性
              } else { // 不支持 hasAttribute()
                optValue = (option.attributes['value'].specified ? option.value : option.text) // 查明是否已规定 value 属性
              }

              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) { // 不包含没有 name 的表单字段
          parts.push(encodeURIComponent(field.name) + '=' + encodeURIComponent(field.value))
        }
    }
  }

  return parts.join('&')
}

以下是这个 方法的简单使用

<form action="www.xxx.xxx" id="myForm">
  地区:<select name="locaation" id="selLocation">
    <option value="Sunnyvale, CA">Sunnyvale</option>
    <option value="Chine">Chine</option>
    <option value="Ireland">Ireland</option>
    <option>Asutralia</option>
  </select>
  <p>用户名:<input type="text" name="username"></p>
  <p>邮箱:<input type="email" name="email"></p>
  <p><input type="submit" value="submit"></p>
</form>
<script>
var form = document.forms[0]
form.onsubmit = function(event) {
  event.preventDefault()
  var fieldsStr = serialize(form)

  console.log(fieldsStr)
}

</script>

五、富文本编辑

富文本编辑,又称为 WYSIWYG(What You See Is What You Get,所见即所得)。在网页中编辑富文本内容,是人本对web应用程序最大的期待之一。这一技术的本质,就是在页面中嵌入一个包含空HTML的页面 iframe。通过设置 designMode 属性,这个空白的 HTML 页面可以被编辑,而编辑对象则是该页面 <body> 元素的 HTML 代码。designMode 属性有两个可能的值:"off"(默认值)和 "on"。在设置为 "on" 时,整个文档都会变得可以编辑

可以给 iframe 指定一个 非常简单的HTML 页面作为其内容来源。

<!DOCTYPE>
<html>
  <head>
    <title> Black Page for Rich Text Editing</title>
  </head>
  <body></body>
</html>

在包含页面中,需要使用 onload 事件处理程序来在恰当的时刻设置 designMode, 如下:

<iframe name="richedit" style="width: 100px; height: 100px;" src="./blank.html"></iframe>

<script>
  window.onload = function() {
    frames['richedit'].document.designMode = 'on'
  }
</script> 

需要注意的是,不能以文件方式在本地直接用浏览器打开的,地址栏是file:///。可以试着在本地架设服务器来调试

5.1、使用 contenteditable 属性

另一种编辑富文本内容的方式是使用名为 contenteditable 的特殊属性,这个属性也是由 IE 最早实现的。可以吧 contenteditable 属性应用给页面中的任何元素,然后用户立即就可以编辑该元素。这种方法之所以受到欢迎,是因为它不需要 iframe、空白页 和 JavaScript ,只要为元素设置 contenteditable属性即可

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

如上,元素中包含的任何文本内容就都可以编辑了,就好像这个元素变成了 <textarea> 元素一样。通过在这个元素上设置 contenteditable 元素,也能开打或关闭编辑模式

var div = document.getElementById('richedit')
div.contentEditable = true 
div.contentEditable = false

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

5.2、操作富文本

与富文本编辑器交互的主要方式,就是使用 document.execCommand()。这个方法可以对文档指向预定义的命令,而且可以应用大多格式。这个方法接受三个参数:

  • 要执行的命令名称
  • 表示浏览器是否应该为当前命令提供用户界面的一个布尔值
  • 指向命令必须的一个值(如果不需要值,则传递 null)

为了确保跨浏览器的兼容性,第二个参数应该始终设置为 false,因为 Firefox 会在改参数为 true时 抛出错误

不同浏览器支持的预定义命令也不一样。下表列出了那些被支持最多的命令

命令 值(第三个参数) 说明
backcolor 颜色字符串 设置文档的背景颜色
bold null 将选择的文本转换为粗体
copy null 将选择的文本复制到剪贴板
createlink URL字符串 将选择的文本转换成一个链接,指向指定的URL
cut null 将选择的文本剪切到剪贴板
delete null 删除选择的文本
fontname 字体名称 将选择的文本修改为指定字体
fontsize 1~7 将选择的文本修改为指定字体大小
forecolor 颜色字符串 将选择的文本修改为指定的颜色
formatblock 要包围当前文本的HTML标签;如<h1> 使用指定的HTML标签来格式化选择的文本快
indent null 缩进文本
inserthorizontalrule null 在插入字符处插入一个<hr>元素
insertimage 图像的URL 在插入字符处插入一个图像
insertorderedlist null 在插入字符处插入一个<ol>元素
insertunorderedlist null 在擦汗如字符处插入一个<ul>元素
insertparagraph null 在插入字符处插入一个<p>元素
italic null 将选择的文本转换成斜体
justifycenter null 将插入光标所在文本块居中对齐
justifyleft null 将插入光标所在文本快左对齐
outden null 凸排文本(减少缩进)
paste null 将剪贴板中的文本粘贴到选择的文本
removeformat null 移除插入光标所在文本块的块级格式。这是撤销 formatblock 命令的操作
selectall null 选择文档中的所有文本
underline null 为选择的文本添加下划线
unlink null 移除文本的链接。这是册小 createlink的命令的操作

其中,与剪贴板有关的命令在不同浏览器中的差异极大。Opera 根本没有实现任何剪贴板命令,即使不能通过 document.execCommand() 来执行这些命令,但却可以通过相应的快捷键来实现同样的操作。

使用上诉属性,来简单实现一个富文本

  <button id="boldBtn">bold </button>
  <button id="italicBtn">italic</button>
  <button id="linkBtn">a</button>
  <button id="h1Btn">H1</button>
  <iframe name="richedit" style="width: 1000px; height: 300px;display: block" src="blank.html"></iframe>

<script>
window.onload = function() {
    frames['richedit'].document.designMode = 'on'
   
    document.getElementById('boldBtn').onclick = function() {
      frames['richedit'].document.execCommand('bold', false, null)
    }
    document.getElementById('italicBtn').onclick = function() {
      frames['richedit'].document.execCommand('italic', false, null)
    }
    document.getElementById('linkBtn').onclick = function() {
      frames['richedit'].document.execCommand('createlink', false, 'http://www.baidu.com') // 默认地址,简单模拟
    }
    document.getElementById('h1Btn').onclick = function() {
      frames['richedit'].document.execCommand('formatblock', false, '<h1>')
    }
  }
  
</script>
效果图

选区文本后,点击不同的快捷键,实现修改外观


同样的方法也适用于页面中 contenteditable 属性为 "true" 的区块,只要把对框架的引用替换成当前窗口的 document 对象即可。

<div style="width: 1000px; height: 300px;display: block;border: 1px solid violet" id="div" contenteditable>
</div>

<script>
window.onload = function() {
  document.getElementById('boldBtn').onclick = function() {
    document.execCommand('bold', false, null)
  }
  document.getElementById('italicBtn').onclick = function() {
   document.execCommand('italic', false, null)
  }
  document.getElementById('linkBtn').onclick = function() {
   document.execCommand('createlink', false, 'http://www.baidu.com') // 默认地址,简单模拟
  }
  document.getElementById('h1Btn').onclick = function() {
   document.execCommand('formatblock', false, '<h1>')
  }
    
}

需要注意的是,虽然所有浏览器都支持这些命令,但这些命令所产生的 HTML 仍然有很大不同。由于各个浏览器实现命令的方式不同,加上它们通过 innerHTML 实现转换的方式也不一样,因此不能指望富文本编辑器会产生一致的 HTML。


除了命令之外,还有一些于命令相关的方法

  • queryCommandEnabled()
    用来检测是否可以争对当前选择的文本,或者当前插入字符所在位置执行某个命令。接受一个参数,即要检测的命令。如果当前编辑区域允许执行传入的命令,这个方法返回 true,否则返回 false。
var result = frames['richedit'].document.queryCommandEnabled('bold')

如果能够对当前选择的文本执行"bold"命令,以上代码就会返回 ture

  • queryCommandState()
    方法用于确定是否已将指定命令应用到了选择的文本。
var isBold = frames['richedit'].document.queryCommandState('bold')

如果以前已经对选择的文本执行了"bold"命令,那么上面的代码会返回 ture。

  • queryCommandValue()
    用于取得执行命令时传入的值(即前面例子中传给document.execCommand() 第三个参数
var fontSize = frames['richedit'].document.queryCommandValue('fontsize')

通过这个方法可以确定某个命令是怎样应用到选择的文本的,可以据以确定在对其应用后续命令是否合适

5.3、富文本选区

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

  • anchorNode:选区起点所在的节点。
  • anchorOffset:在到达选区起点之前跳过的 anchorNode 中的字符数量
  • focusNode:选区终点所在的节点
  • focusOffset:focusNode中包含在选区之内的字符数量。
  • isCollapsed:布尔值,表示选区的起点和终点是否重合
  • rangeCount:选区中包含的DOM范围的数量

Selection 对象的这些这些属性并没有包含多少有用的信息。下列方法提供了更多信息,并且支持对选区的操作

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

Selection 对象的这些方法都极为使用,它们利用了 前面讲到的 DOM范围来管理选区。由于可以直接操作选择文本的DOM表现,因此访问DOM范围与 使用 execCommand() 相比,能够对富文本编辑器进行更加细化的控制。

    var selection = frames['richedit'].getSelection()
    
    // 取得选择的文本
    var selectedText = selection.toString()

    // 取得代表选区的范围
    var range = selection.getRangeAt(0)

    // 突出显示选择的文本
    var span = frames['richedit'].document.createElement('span')
    span.style.backgroundColor = 'yellow'
    range.surroundContents(span)

Firefox 3.6+ 中调用 document.getSelection() 会返回一个字符串。为此,可以在 Forefox 3.6+ 中该作调用 window.getSelection(), 从而范围 selection 对象。Firefox 8修复了这个问题

IE8 及更早的版本不支持DOM范围,但我们可以通过它支持的 selection 对象操作选择的文本。要取得富文本编辑器中选择的文本,首先必须创建一个文本范围,然后再像下面这样访问其 text 属性。

var range = frames['richedit'].document.selection.createRange()
var selectedText = range.text

虽然使用 IE 的文本范围来啊执行 HTML 操作并不像使用 DOM 范围那么可靠,但也不失为一种有效的途径。要像前面使用 DOM 范围那样实现相同的文本高亮效果,可以组合使用 **htmlText **属性和 pasteHTML() 方法

var range = frames['richedit'].document.selection.createRange()
range.pasteHTML('<span style="background-color: yellow">'+ range.htmlText + '</span>');

5.4、表单与富文本

富文本编辑器中的HTML不会被自动提交给 服务器,而需要我们手工来提交并提交HTML。为此,通常可以添加一个隐藏的表单字段,让他的值等于 从 iframe 中提取的 HTML。

form.onsubmit = function() {
  this.elements['comments'].value = frames['richedit'].document.body.innerHTML
}

对于 contenteditable 元素,也可以执行类似的操作

form.onsubmit = function() {
  this.elements['comments'].value = document.getElementById('richedit').innerHTML
}

六、小结

使用 JavaScript 可以增强已有的表单字段,从而创造出新的功能,或者提升表单的易用性。

  • 可以使用一些标准 或 非标准的方法选择文本框的全部或部分文本
  • 在文本框的内容变化时,可以通过侦听键盘事件以及检测插入的字符,来允许或禁止用户输入
  • 除了Opera 其他主流浏览器都允许 通过 JavaScript 访问 剪贴板中的数据。
  • IE允许在任何时候访问剪贴板的相关信息,而其他浏览器只能按在发生剪贴板事件时才能访问。

富文本编辑功能是通过一个包含空 HTML 文档的 iframe 元素来实现。通过将空文档的 designMode 属性设置为 'on',就可以将页面转换为 可以编辑状态,此时其表现如同字处理软件。另外,也可以将某个元素设置为 contenteditable。在默认情况下,可以将字体加粗或者将文本转换为斜体,还可以使用剪贴板。
JavaScript通过使用 execCommand() 方法也可以实现相同的一些功能。另外,使用 queryCommandEnabled()、queryCommandState()、queryCommandValue() 方法则可以取得有关文本选区的信息。由于以这种方式构建的富文本编辑器并不是一个表单字段,因此在将其内容提交给服务器之前,必须将 iframe 或 contenteditable 元素中的 HTML 复制到一个表单字段中。

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

推荐阅读更多精彩内容