js基础-富文本编辑器

2024-05-19 19:13:28

富文本编辑器

1、富文本编辑器简介

富文本编辑(WYSIWYG(What You See Is What You GET,所见即所得))。

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

designMode属性有两个可能的值:“off”和“on”,默认为“off”。

给iframe指定一个非常简单的HTML页面作为编辑框:

<!DOCTYPE html> 
<html> <head> <title>Edit</title> </head> <body></body> 
</html> 

要将其设置成可编辑,不是在iframe页面内,而是它嵌入的那个页面,而且必须等待页面完全加载后才能设置designMode属性:

<iframe name="richedit" style="width:100px;height:100px" src="blank.html" ></iframe>window.onload = function(){ window.frames['richedit'].document.designMode = 'on'; 
} 

等到上面的代码执行完,就可以使用可编辑区了。

1.1 使用contenteditable属性

可以给页面中的任何元素添加contenteditable属性,使其成为可编辑区:

<div id="richedit" contenteditable="true"></div> 

当然,也可以通过JavaScript设置:

var richedit = document.getElementById('richedit'); 
richedit.contentEditable = 'true'; 

1.2 获取编辑区里的HTML内容

// iframe frames['richedit'].document.body.innerHTML// 设置contenteditable的元素 richedit.innerHTML 

2 富文本选区

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

每个Selection对象可能包含一个或多个Range对象。

Range对象表示文档的连续范围区域,简单的说就是高亮选区。一个Range的开始点和结束点位置任意,开始点和结束点也可以是一样的(空Range)。最常见的就是用户在浏览器窗口中用鼠标拖动选中的区域。

不过,不同的浏览器,Range对象是不一样的,在Chrome、Mozilla、Safari等主流浏览器上,Range属于selection对象(表示range范围),而在IE下,Range属于TextRange对象(表示文本范围)。

在下面的所有列子中,皆以selection对象为主,同时会加上textRange对象的兼容代码。

2.1 拖动选择获取

每一个浏览器窗口都有一个selection(或text Range)对象,我们可以通过window.getSelection()方法来获取:

var selectedRange; 
function saveSelection(){ if(window.getSelection){ /主流的浏览器,包括chrome、Mozilla、Safari/ return window.getSelection(); }else if(document.selection){ /IE下的处理/ return document.selection.createRange(); } return null; 
}; 

注意:标准dom是从window中获取selection对象,而ie是从document对象中获取。

实例(可以试试在不同浏览器下的执行,点击里面的按钮btn1):Demo

2.2 优化获取代码

一个selection对象有可能不是只有一个Range对象,有可能有多个,每一个Range对象代表用户鼠标所选取范围内的一段连续区域。(在Firefox中,可以通过 ctrl键可以选取多个连续的区域,因此在Firefox中一个selection对象有多个range对象,在其他浏览器中,用户只能选取一段连续的区 域,因此只有一个range对象。)

如何获取某个Range对象呢?我们可以通过selection对象的getRangeAt方法来获取:

range = window.getSelection().getRangeAt(index) 

getRangeAt()方法接受一个参数,代表该Range对象的序列号,也可以说你拖动选择的顺序号,它的值有如下几种情况:

  • 当用户没有按下鼠标时候,该参数的值为0.
  • 当用户按下鼠标的时候,该参数值为1.
  • 当用户使用鼠标同时按住ctrl键时选取了一个或者多个区域时候,该参数值代表用户选取区域的数量。
  • 当用户取消区域的选取时,该属性值为1,代表页面上存在一个空的Range对象;

要获取Range对象,一般我们会判断是否有Range对象,我们可以通过selection对象的rangeCount属性(类似数组的length,返回Range对象的数量)来判断是否有多个Range对象,然后再去调用getRangeAt()方法。

对于富文本编辑器来说,一般情况下,我们只需要一个选择区域(Range对象),优化后的代码如下:

function saveSelection(){ if(window.getSelection){ /主流的浏览器,包括chrome、Mozilla、Safari/ var sel = window.getSelection(); if(sel.rangeCount > 0){ return sel.getRangeAt(0); } }else if(document.selection){ /IE下的处理/ return document.selection.createRange(); } return null; 
}; 

实例(可以试试在不同浏览器下的执行,点击里面的按钮btn2):Demo

2、Range对象的属性和方法

2.1 创建Range对象(范围)

document.createRange():用于创建一个Range对象(范围)

在IE下

document.body.createTextRange():用于创建一个textRange对象

2.2 Range对象的属性

endContainer:返回范围的结束点的Document节点,通常是文本节点。endOffset:返回endContainer中的结束点位置。startContainer: 返回范围的开始点中的Document节点,通常是文本节点。   startOffset:返回startContainer中的开始点位置。collapsed:用于判断范围的开始点与结束点是否处于相同的位置,如果相同,该属性值返回true,即范围是空的或折叠的。commonAncestorContainer:范围的开始点和结束点的(即它们的祖先节点)、嵌套最深的 Document 节点。 

注意:所有属性都是只读的。如果范围中存在空格,也会计算在偏移量内。

实例(点击里面的按钮btn3):Demo

2.3 Range对象的方法

2.3.1 范围选择

selectNode(node):设置该范围的边界点,使它包含指定节点和指定节点的所有子孙节点。selectNodeContents(node):设置该范围的边界点,使它包含指定节点的子孙节点,但不包含指定节点本身。

2.3.2 操作范围

deleteContents():将Range对象中所包含的内容从页面中删除setStart(node,index):将指定节点中的某处位置指定为Range对象所代表区域的起点位置setEnd(node,index):将指定节点中的某处位置指定Range对象所代表区域的结束位置setStartBefore(node):将指定节点的起点位置指定为Range对象所代表区域的起点位置。setStartAfter():将指定节点的终点位置指定为Range对象所代表区域的起点位置。setEndBefore():将指定节点的起点位置指定为Range对象所代表区域的终点位置。setEndAfter(): 将指定节点的终点位置指定为Range对象所代表区域的终点位置。cloneRange():对当前的Range对象进行复制,该方法返回一个复制的Range对象cloneContents():复制当前Range对象所代表区域中的HTML代码并返回新的DocumentFragment对象。extractContents():将Range对象所代表区域中的html代码克隆到一个DocumentFragment对象中,然后从页面中删除这段HTML代码detach():释放Range对象。insertNode(node):将指定的节点插入到某个Range对象所代表的区域中,插入位置为Range对象所代表区域的起点位置,如果该节点已经存在于页面中,该节点将被移动到Range对象代表的区域的起点处。 

实例(关于setStart和setEnd,点击里面的按钮btn6):Demo

实例(关于deleteContents,点击里面的按钮btn7):Demo

实例(关于extractContents,点击里面的按钮btn8):Demo

2.3.3 其他方法

collpase(boolean)  用于使范围的边界点重合。当为true时,将范围的结束点设为与开始点相同的值;当为false时,将范围的开始点设为与结束点相同的值。compareBoundaryPoints(how,sourceRange):用来比较两个Range对象,返回1,0,-10表示相等,等于1时,当前范围在sourceRange之后,等于-1时,当前范围在sourceRange之前)toString():返回该范围表示的文档区域的纯文本内容。 

(1)compareBoundaryPoints()

how的常量:

START_TO_START  用指定范围的开始点与当前范围的开始点进行比较。 
START_TO_END    用指定范围的开始点与当前范围的结束点进行比较。 
END_TO_END  用指定范围的结束点与当前范围的结束点进行比较。 
END_TO_START    用指定范围的结束点与当前范围的开始点进行比较。 

4、selection对象

selection对象可看作是Range对象的集合,包含一个或多个Range对象。

4.1 属性

anchorNode:返回范围的开始点的Document节点,和range对象的endContainer作用一样。anchorOffset:返回startContainer中的开始点位置,和range对象的startOffset作用一样。focusNode:返回范围的结束点的Document节点,和range对象的endContainer作用一样。focusOffset:返回endContainer中的结束点位置,和range对象的endOffset作用一样。isCollapsed:范围的开始点与结束点是否重叠 
这是新标准中selection的属性,通过这些属性,我们省却了先获取range对象再获取偏移量和节点的繁琐。 

实例(点击里面的按钮btn4):Demo

4.2 方法

removeAllRanges():删除selection中原有的所有rangeaddRange(range):将新的range添加到selection中 

5、HTMLInputElement的属性方法

5.1 在IE下Range对象

**(1)属性

htmlText:返回字符串,为textRange的HTML内容,与innerHTML作用一样,只读  
text:返回字符串,为textRange的文本内容,相当于innerText,可读写。 

(2)方法

moveStart("character",index):选定范围的开始点向后移动index个字符moveEnd("character",index):选定范围的结束点向后移动index个字符pasterHTML():黏贴HTML到一个文本节点时,该文本节点自动分隔。 

5.2 在其他主流浏览器上

(1)属性

selectionStart:获取范围的开始点,可读写 
selectionEnd:获取范围的结束点,可读写 
selectionDiraction

(2) 方法

select():在焦点状态下,移动光标至第一个字符后面setSelectionRange(start,end):设置范围的开始点和结束点。 
注意:selectionStart和selectionEnd会记录元素最后一次selection的相关属性,意思就是当元素失去焦点后,使用selectionStart和selectionEnd仍能够获取到元素失去焦点时的值。setSelectionRange(start,end): 
如果textbox没有selection时,selectionStart和selectionEnd相等,都是焦点的位置。 
在使用setSelectionRange()时 
如果end小于start,会讲selectionStart和selectionEnd都设置为end; 
如果startend参数大于textbox内容的长度(textbox.value.length),startend都会设置为value属性的长度。 

3 操作富文本

使用document.execCommand()方法是与富文本编辑器交互的重要方式,它可以对文档执行预定义的命令,而且可以应用大多数格式。

语法:

bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument) 

参数说明:

  • aCommandName:String类型,命令名称
  • aShowDefaultUI:Boolean类型,默认为false,是否展示用户界面,一般设为false。Mozilla没有实现。
  • aValueArgument:String类型,一些命令需要额外的参数值(比如insertHTML需要提供HTML内容),默认为null,一般不需要参数时都使用null。

命令介绍:

backColor (用法:document.execCommand('backColor',bfalseb,Color); ) 
改变文档的背景颜色。 在styleWithCss模式,它影响的是包含元素的背景。 这个命令要求提供一个颜色值<color>作为第三个参数 (Internet Explorer 使用这个命令设置文本背景色)  bold (用法: document.execCommand('Bold','false',null); ) 
对选中文本或者插入元素设置、取消粗体显示. (Internet Explorer 使用<strong>标签 而不是<b>标签。)contentReadOnly 
转化文档进入只读或者可编辑模式. 这个命令要求提供给一个boolean值给第3个参数(ie不支持)。  copy   用法:document.execCommand('copy','false',null); 
把当前选中区域复制到系统剪贴板。由于启用这个功能的条件因浏览器不同而不同,所以使用此功能时,请先检查浏览器是否支持。createLink 
当有选中区域的时候,将选中区域创建为一个锚点,需要提供一个URI给第3个参数. 这个URI必须至少包含一个字符,空白字符也可。(Internet Explorer会创建一个URI为空的a标签) 
cut     用法:document.execCommand('cut','false',null); 
剪切选中文本到剪切板. 同copy一样需要开启剪切板功能。  decreaseFontSize 
给选中文本或者插入元素添加一个small标签。(Internet Explorer不支持)  delete  删除当前选中区域enableInlineTableEditing 
开启或禁用表的行和列的插入删除功能 ( Internet Explorer不支持)  enableObjectResizing 
开启或禁用图片或者其他可调整元素大小的(resize)功能 ( Internet Explorer不支持) 
fontName  用法:document.execCommand('fontName','false',sFontName); 
改变选中文本或者插入元素的字体。需要给第3个参数提供一个字体值(例如:"Airal")  fontSize  用法:document.execCommand('fontSize','false',sSize|iSize); 
改变选中文本或者插入元素的字体大小。需要给第3个参数提供一个数字  foreColor 
改变选中文本或者插入元素的字体颜色。需要给第3个参数提供一个颜色值formatBlock 
添加一个HTML块式标签在包含当前选择的行,如果已经存在了,更换包含该行的块元素(在Firefox中的blockquote例外,它将包含任何包含块元素)。需要提供一个标签名称作为参数(比如:H1、P、DL、BLCOKQUOTE等)(IE仅支持标题标签H1-H6,ADDRESS和PRE,使用时还必须包含标签分隔符<>,比如<H1>)forwardDelete 
删除光标所在位置的字符,和按下删除键一样。heading 
添加一个标题标签在光标处或所选文字上。需要提供标签名称字符串作为参数(比如:H1、H6)(IE和Safari不支持)hiliterColor 
更改选择或插入点的背景颜色。需要提供一个颜色值作为参数。(IE不支持)increaseFontSize 
在选择或插入点周围添加一个BIG标签(IE不支持)indent 
取消或缩进选择或插入点所在的行。insertBrOnReturn 
控制当按下Enter键时,是插入br标签还是把当前块元素变成两个(IE不支持)insertHorizontalRule 
在插入点插入一个水平线(删除选中的部分)insertHTML 
在插入点插入一个HTML字符串(删除选中部分)。需要提供一个HTML字符串作为参数(IE不支持)insertImage 
在插入点插入一张图片(删除选中部分)。需要提供一个image src URI作为参数。这个URI至少包含一个字符(空字符也行)。(IE会创建一个值为null的链接)insertOrderedList 
在插入点或选中文字上创建一个有序列表insertUnorderedList 
在插入点或选中文字上创建一个无序列表insertParagraph 
在选择或当前行周围插入一个段落。(IE会在插入点插入一个段落并删除选中部分)insertText 
在光标插入位置插入文本内容或覆盖所选的文本内容italic 
在光标插入点开启或关闭斜体字。(IE使用<em>标签,而不是<i>)justifyCenter 
对光标插入位置或所选内容进行文字居中justifyFull 
对光标插入位置或所选内容进行文本对齐(两端对齐)justifyLeft 
对光标插入位置或所选内容进行文本左对齐justifyRight 
对光标插入位置或所选内容进行文本右对齐outdent 
对光标插入行货所选行内容减少缩进量paste 
在光标位置黏贴剪贴板的内容。(对选中内容替换)redo 
重做被撤销的操作removeFormat 
对所选内容去除所有格式(比如:加粗)。selectAll 
选中编辑区里的全部内容strikeThrough 
在光标插入点开启或关闭删除线subscript 
在光标插入点开启或关闭下角标superscript 
在光标插入点开启或关闭上角标underline 
在光标插入点开启或关闭下划线undo 
撤销最近执行的命令unlink 
去除所选的锚链接的<a>标签useCSS 
切换使用HTML tags还是CSS来生成标记。需要一个布尔值作为参数。该属性已废除,使用styleWithCSS代替。styleWithCSS 
用这个取代useCSS命令。切换使用HTML tags还是CSS来生成标记。需要一个布尔值作为参数。(false使用CSS,true使用HTML) 

这个方法使用于iframe类型的编辑器,也适用于将contenteditable设置为true的元素:

// iframe 
frames['richedit'].document.execCommand('bold', false, null);// 设置contenteditable为true的元素 
document.execCommand('bold', false, null); 

3.1 与命令相关的方法

  • queryCommandEnabled():可以用它来检测是否可以针对当前选择的文本,或者当前插入字符所在位置执行某个命令,它接受一个参数,即要检测的命令,如果单亲编辑区允许执行传入的命令,则返回true,否则返回false
document.queryCommandEnabled('bold') ){} 
  • queryCommandState():用于确定是否已将指定命令应用到了选择的文本。比如:判断当前选择的文本是否已将转换成了粗体:
isBold = document.queryCommandState('bold'); 
  • queryCommandValue():用于取得执行命名时传入的值(即document.execCommand()的第三个参数)

4、常用案例代码

6.1 针对div(contenteditable=”true”)相关操作

(1) 获取用户选择内容

function saveSelection(){ if(window.getSelection){ /主流的浏览器,包括chrome、Mozilla、Safari/ var sel = window.getSelection(); if(sel.rangeCount > 0){ return sel.getRangeAt(0); } }else if(document.selection){ /IE下的处理/ return document.selection.createRange(); } return null; 
};var selectedRange = saveSelection();  // 保存获取到的Range对象 

注意:如果是在IE下需要获取内容,需要使用selection.text来获取。

实例(可以试试在不同浏览器下的执行,点击里面的按钮btn2):Demo

(2) 恢复光标位置

function restoreSelection(){ var selection = window.getSelection(); if (selectedRange) { try { selection.removeAllRanges();  /清空所有Range对象/  } catch (ex) { /IE/ document.body.createTextRange().select(); document.selection.empty(); }; /恢复保存的范围/ selection.addRange(selectedRange); } 
} 

实例(点击里面的按钮btn5):Demo

(3)将光标移至文本最后

function selectAllText(elem){ if(window.getSelection){ elem.focus(); var range = window.getSelection(); range.selectAllChildren(elem); range.collapseToEnd(); }else if(document.selection){ var range = document.selection.createTextRange(); range.moveToElementText(elem); range.collapse(false); range.select(); /避免产生空格/ } 
} 

6.2 表单元素(input、textarea)相关操作

(1) 将光标置于表单元素的最后

function toTextEnd(elem){ if(window.getSelection){ elem.setSelectionRange(elem.value.length,elem.value,length); elem.focus() }else if(document.selection){ /IE下/ var range = elem.createTextRange(); range.moveStart('character',elem.value.length); range.collapse(true); range.select(); } 
} 

实例(点击里面的按钮btn10):Demo

(2) 选中所有文字

function selectAllText(elem){ if(window.getSelection){ elem.setSelectionRange(0,elem.value.length); elem.focus(); }else if(document.selection){ var range = elem.createTextRange(); range.select(); } 
} 

实例(点击里面的按钮btn11):Demo

(3)获取光标位置

function getCursorPosition(elem){ if(window.getSelection){ return elem.selectionStart; }else if(document.selection){ elem.focus(); var range = document.selection.createTextRange(); range.moveStart('character',-elem.value.length); return range.text.length; } return elem.value.length; 
} 

(4)设置光标位置

function setCursorPosition(elem, position){ if(window.getSelection){ elem.focus(); elem.setSelectionRange(position,position); }else if(document.selection){ var range = elem.createTextRange(); range.collapse(true); range.moveEnd('character',position); range.moveStart('character',position); range.select(); } 
} 

一个简单的富文本编辑器:富文本编辑器

js基础-富文本编辑器相关推荐

  1. php去除编辑器html标签,js处理富文本编辑器转义、去除转义、去除HTML标签

    富文本编辑器生成的HTML标签,进行转义,然后写入数据库,防止脚本注入: function htmlEncode(value){ return $(' } 从数据库拿出的转义后的HTML标签内容,先得 ...

  2. HTML JS实现富文本编辑器

    HTML/CSS/JS 目录:https://blog.csdn.net/dkbnull/article/details/87934939 JS实现富文本编辑器主要借助 document.execCo ...

  3. 原生JS实现富文本编辑器

    富文本编辑器是我们常用到的编辑器,也有很多功能完备且强大的编辑器,比如Quill Rich Text Editor.ueditor等,都是很优秀的富文本编辑器.在我们写网页的时候也会用到它,通常省事的 ...

  4. js处理富文本编辑器转义、去除转义、去除HTML标签

    富文本编辑器生成的HTML标签,进行转义,然后写入数据库,防止脚本注入: function htmlEncode(value){return $('<div/>').text(value) ...

  5. 小程序开发笔记(二):微信小程序富文本编辑器editor的使用

      小程序在去年5月的 v2.7.0 版本新增了组件editor富文本编辑器,但对于像我这种开发新手,要熟练使用还是有一定难度.所以记录一下我的学习过程,希望对大家有帮助.   小程序有详细的微信开发 ...

  6. 【推荐】1657- 灵活可扩展,2023年值得尝试的13款富文本编辑器

    作为前端开发人员,我们经常需要为网站和应用程序添加文本内容.与传统的文本编辑器不同,富文本编辑器可让您轻松创建各种类型的文本内容,包括加粗字体.斜体字.框架.列表.图片和视频等. 本文我将向大家推荐 ...

  7. 【JavaWeb】之富文本编辑器

    [JavaWeb]富文本编辑器 前言 一.富文本编辑器介绍 二.富文本编辑器使用 1.引入编辑器(多种引入方式) 2.使用编辑器 三.主流富文本编辑器推荐 1.TinyMCE 2.CKEditor 3 ...

  8. 灵活可扩展,2023年值得尝试的13款富文本编辑器

    作为前端开发人员,我们经常需要为网站和应用程序添加文本内容.与传统的文本编辑器不同,富文本编辑器可让您轻松创建各种类型的文本内容,包括加粗字体.斜体字.框架.列表.图片和视频等. 本文我将向大家推荐 ...

  9. 前端学习(2732):重读vue电商网站42之添加富文本编辑器

    vue-quill-editor 官方文档传送门 通过 vue-ui 界面,可以安装我们所需要的依赖,或者使用下文 npm 或 yarn安装. NPM Js npm install vue-quill ...

最新文章

  1. 2020 年度最佳的23个机器学习项目!(附源代码)
  2. java opencv 图片放大缩小,角点检测和边缘检测(14)
  3. 如何快速实现物联网行业中的实名认证
  4. MySQL性能优化(八)
  5. 设计模式(二)工厂模式
  6. SharpDevelop源码分析 (一、序+基本概念) 收藏
  7. 【Tiny4412】制作最小文件系统脚本
  8. MySQL 19个规则数据库设计总结
  9. 企业私有云部署im,视频服务
  10. JSON数据格式----- JavaScript与JSON、JavaScript的JSON对象、构建JSON格式数据
  11. 写你自己 android 多通道打包工具 可以包libs和.so文件
  12. c# 获取excel单元格公式结果_EXCEL公式解析:单元格中数字去重排序思路及公式详解...
  13. L1-018 大笨钟 (10 分) — 团体程序设计天梯赛
  14. 计算机网络工程师多久过期,软考网络工程师证书有效期
  15. nfc修改饭卡软件下载_手机nfc模拟门禁卡app-NFC卡模拟软件中文版下载安卓标准版-西西软件下载...
  16. 高中生入门计算机编程,高中生必看:入门学软件编程,看这三点...
  17. 一江春水向东流 任正非
  18. 路由器显示找不到服务器从新设置,怎么重新设置路由器ip地址
  19. 【网络空间安全数学基础第8章】环和域
  20. 写在母亲节――5月8日的心情

热门文章

  1. 【案例教程】ArcGIS在洪水普查、风险评估及区划中的实践技术
  2. 骑士CMS存储型XSS(攻击管理员)
  3. GRE动词同义词汇介绍:刺 尖锐
  4. 步进电机的计算机控制系统设计,基于.51单片机的步进电机控制系统设计.doc
  5. Ubuntu 16.04安装有道词典(完全版)
  6. 大话制作外挂的可行性
  7. 转行数据科学路上的点点滴滴
  8. office2020与2016版的不同_2020年了,我们该如何选择Office365
  9. TextView 图文混排,图文居中对齐
  10. openlayers3线段添加闪烁_openLayers 4 canvas图例绘制,canvas循环添加图片,解决图片闪烁问题...