要素过多建议收藏
- 富文本编辑
 
 基本的技术就是在空白  HTML  文件中嵌入一个  
 
 iframe 。通过  designMode  属性,可以将这个空白文档变成可以编辑的,实际编辑的则是 <body> 元素  
 
 的  HTML 。 designMode  属性有两个可能的值: "off" (默认值)和 "on" 。设置为 "on" 时,整个文档  
 
 都会变成可以编辑的(显示插入光标),从而可以像使用文字处理程序一样编辑文本,通过键盘将文本  
 
 标记为粗体、斜体,等等。 
 
 作为  iframe  源的是一个非常简单的空白  HTML  页面。下面是一个例子:  
 <!DOCTYPE html>
<html><head><title>Blank Page for Rich Text Editing</title></head><body></body>
</html>  这个页面会像其他任何页面一样加载到  iframe  里。为了可以编辑,必须将文档的  designMode  属  
  性设置为 "on" 。不过,只有在文档完全加载之后才可以设置。在这个包含页面内,需要使用  onload  
  事件处理程序在适当时机设置  designMode ,如下面的例子所示: 
 <iframe name="richedit" style="height: 100px; width: 100px"></iframe> 
<script> window.addEventListener("load", () => { frames["richedit"].document.designMode = "on"; }); 
</script>  以上代码加载之后,可以在页面上看到一个类似文本框的区域。这个框的样式具有网页默认样式,  
  不过可以通过  CSS  调整。 
 - 使用 contenteditable
 还有一种处理富文本的方式,也是  IE  最早实现的,即指定  contenteditable 属性。可以给页面 
  中的任何元素指定  contenteditable  属性,然后该元素会立即被用户编辑。这种方式更受欢迎,因为  
  不需要额外的  iframe 、空页面和  JavaScript ,只给元素添加一个  contenteditable  属性即可,比如: 
 <div class="editable" id="richedit" contenteditable ></div>
 元素中包含的任何文本都会自动被编辑,元素本身类似于 <textarea> 元素。通过设置  
  contentEditable  属性,也可以随时切换元素的可编辑状态: 
 let div = document.getElementById("richedit");richedit.contentEditable = "true";
 contentEditable  属性有  3  个可能的值: "true" 表示开启, "false" 表示关闭, "inherit" 表示  
  继承父元素的设置(因为在  contenteditable  元素内部会创建和删除元素)。 IE 、 Firefox 、 Chrome 、  
  Safari  和  Opera  及所有主流移动浏览器都支持  contentEditable  属性。 
 - 与富文本交互
 与富文本编辑器交互的主要方法是使用  document.execCommand() 。这个方法在文档上执行既定  
  的命令,可以实现大多数格式化任务。 document.execCommand() 可以接收  3  个参数:要执行的命令、  
  表示浏览器是否为命令提供用户界面的布尔值和执行命令必需的值(如果不需要则为  null )。为跨浏览  
  器兼容,第二个参数应该始终为  false ,因为  Firefox  会在其为  true  时抛出错误。  
  不同浏览器支持的命令也不一样。下表列出了最常用的命令。 
  
 剪贴板相关的命令与浏览器关系密切。虽然这些命令并不都可以通过  document.execCommand()  
 
 使用,但相应的键盘快捷键都是可以用的。  
 
 这些命令可以用于修改内嵌窗格( iframe )中富文本区域的外观,如下面的例子所示: 
 
// 在内嵌窗格中切换粗体文本样式frames["richedit"].document.execCommand("bold", false, null);// 在内嵌窗格中切换斜体文本样式frames["richedit"].document.execCommand("italic", false, null);// 在内嵌窗格中创建指向 www.wrox.com 的链接frames["richedit"].document.execCommand("createlink", false,"http://www.wrox.com");// 在内嵌窗格中为内容添加 <h1> 标签frames["richedit"].document.execCommand("formatblock", false, "<h1>");
 同样的方法也可以用于页面中添加了  contenteditable  属性的元素,只不过要使用当前窗口而不  
 
 是内嵌窗格中的  document  对象: 
 
// 切换粗体文本样式document.execCommand("bold", false, null);// 切换斜体文本样式document.execCommand("italic", false, null);// 创建指向 www.wrox.com 的链接document.execCommand("createlink", false, "http://www.wrox.com");// 为内容添加 <h1> 标签document.execCommand("formatblock", false, "<h1>");
 注意,即使命令是所有浏览器都支持的,命令生成的  HTML  通常差别也很大。例如,为选中文本  
 
 应用  bold  命令在  IE  和  Opera  中会使用 <strong> 标签,在  Safari  和  Chrome  中会使用 <b>标签,而在Firefox  中会使用 <span> 标签。在富文本编辑中,不能依赖浏览器生成的  HTML,因为命令实现和格式 转换都是通过  innerHTML  完成的。 
 
 还有与命令相关的其他一些方法。第一个方法是  queryCommandEnabled() ,此方法用于确定对当  
  前选中文本或光标所在位置是否可以执行相关命令。它只接收一个参数,即要检查的命令名。如果可编 辑区可以执行该命令就返回  true ,否则返回  false 。来看下面的例子:  
 let result = frames["richedit"].document.queryCommandEnabled("bold");
 以上代码在当前选区可以执行 "bold" 命令时返回  true 。不过要注意, queryCommandEnabled()  
  返回  true  并不代表允许执行相关命令,只代表当前选区适合执行相关命令。在  Firefox  中,  
  queryCommandEnabled("cut") 即使默认不允许剪切也会返回  true 。  
   另一个方法  queryCommandState() 用于确定相关命令是否应用到了当前文本选区。例如,要确定  
  当前选区的文本是否为粗体,可以这样:  
  let isBold = frames["richedit"].document.queryCommandState("bold");
 如果之前给文本选区应用过 "bold" 命令,则以上代码返回  true 。全功能富文本编辑器可以利用这  
  个方法更新粗体、斜体等按钮。  
   最后一个方法是  queryCommandValue() ,此方法可以返回执行命令时使用的值(即前面示例的  
  execCommand() 中的第三个参数)。如果对一段选中文本应用了值为  7  的 "fontsize"命令,则如下代 码会返回  7 : 
 let fontSize = frames["richedit"].document.queryCommandValue("fontsize");
 这个方法可用于确定如何将命令应用于文本选区,从而进一步决定是否需要执行下一个命令。 
 
 
- 富文件选择
 在内嵌窗格中使用  getSelection() 方法,可以获得富文本编辑器的选区。这个方法暴露在  
 
 document  和  window  对象上,返回表示当前选中文本的  Selection  对象。每个  Selection  对象都拥  
 
 有以下属性。  
 
   anchorNode :选区开始的节点。  
 
 
   anchorOffset :在  anchorNode  中,从开头到选区开始跳过的字符数。  
 
 
   focusNode :选区结束的节点。  
 
 
   focusOffset : focusNode  中包含在选区内的字符数。  
 
 
   isCollapsed :布尔值,表示选区起点和终点是否在同一个地方。  
 
 
   rangeCount :选区中包含的  DOM  范围数量。  
 
 
 Selection  的属性并没有包含很多有用的信息。好在它的以下方法提供了更多信息,并允许操作  
 
 选区。  
 
 
   addRange( range ) :把给定的  DOM  范围添加到选区。  
 
 
   collapse( node, offset ) :将选区折叠到给定节点中给定的文本偏移处。  
 
 
   collapseToEnd() :将选区折叠到终点。  
 
 
   collapseToStart() :将选区折叠到起点。  
 
 
   containsNode( node ) :确定给定节点是否包含在选区中。  
 
 
   deleteFromDocument() :从文档中删除选区文本。与执行  execCommand("delete", false,  
 
 null) 命令结果相同。  
 
 
   extend( node, offset ) :通过将  focusNode  和  focusOffset  移动到指定值来扩展选区。 
 
 
   getRangeAt( index ) :返回选区中指定索引处的  DOM  范围。  
     removeAllRanges() :从选区中移除所有  DOM  范围。这实际上会移除选区,因为选区中至少  
  要包含一个范围。  
     removeRange( range ) :从选区中移除指定的  DOM  范围。  
     selectAllChildren( node ) :清除选区并选择给定节点的所有子节点。  
     toString() :返回选区中的文本内容。  
   Selection  对象的这个方法极其强大,充分利用了  DOM  范围来管理选区。操纵  DOM  范围可以实  
  现比  execCommand() 更细粒度的控制,因为可以直接对选中文本的  DOM 内容进行操作。来看下面的 例子: 
 let selection = frames["richedit"].getSelection(); 
// 取得选中的文本
let selectedText = selection.toString(); 
// 取得表示选区的范围
let range = selection.getRangeAt(0); 
// 高亮选中的文本
let span = frames["richedit"].document.createElement("span"); 
span.style.backgroundColor = "yellow"; 
range.surroundContents(span);  以上代码会在富文本编辑器中给选中文本添加黄色高亮背景。实现方式是在默认选区使用  DOM  范  
  围,用  surroundContents() 方法给选中文本添加背景为黄色的 <span> 标签。  
  getSelection() 方法在  HTML5  中进行了标准化, IE9  以及  Firefox 、 Safari 、 Chrome  和  Opera  的所  
  有现代版本中都实现了这个方法。  
   IE8  及更早版本不支持  DOM  范围,不过它们允许通过专有的  selection  对象操作选中的文本。如  
  本章前面所讨论的,这个  selection  对象是  document 的属性。要取得富文本编辑器中选中的文本, 必须先创建一个文本范围,然后再访问其  text  属性: 
 let range = frames["richedit"].document.selection.createRange(); 
let selectedText = range.text;  使用  IE  文本范围执行  HTML  操作不像使用  DOM  范围那么可靠,不过也是可以做到的。要实现与  
  使用  DOM  范围一样的高亮效果,可以组合使用  htmlText  属性和  pasteHTML() 方法: 
  let range = frames["richedit"].document.selection.createRange(); 
range.pasteHTML( '<span style="background-color:yellow">${range.htmlText}</span>');  以上代码使用  htmlText  取得了当前选区的  HTML ,然后用一个 <span> 标签将其包围起来并通过  
  pasteHTML() 再把它插入选区中。