当前位置: 首页 > news >正文

前端 富文本编辑器原理——从javascript、html、css开始入门

文章目录

    • ⭐前言
    • ⭐html的contenteditable属性
      • 💖 输入的光标位置(浏览器获取selection)
        • ⭐使用Selection.toString () 返回指定的文本
        • ⭐getRangeAt 获取指定索引范围
      • 💖 修改光标位置
      • 💖 设置选取range
    • ⭐总结
    • ⭐结束

yma16-logo

⭐前言

大家好,我是yma16,本文分享关于前端 富文本编辑器原理——从javascript、html、css开始。
富文本编辑器
富文本编辑器是指具有格式化文本和图像编辑功能的文本编辑器

参考文档:https://w3c.github.io/selection-api/#abstract

⭐html的contenteditable属性

全局属性 contenteditable 是一个枚举属性,表示元素是否可被用户编辑。如果可以,浏览器会修改元素的组件以允许编辑。

  • contenteditable boolean (false | true) 默认false
    简单理解,加上contenteditable ,html可以编辑具有input 输入的基本功能,所见即所得。
    例:
    html demo 标签配置contenteditable
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>富文本编辑器</title></head><style>blockquote {background: #eee;border-radius: 5px;margin: 16px 0;}blockquote p {padding: 15px;}cite {margin: 16px 32px;font-weight: bold;}blockquote p::before {content: '\201C';}blockquote p::after {content: '\201D';}[contenteditable='true'] {caret-color: red;}</style><body><blockquote contenteditable="true"><p>Edit this content to add your own quote</p></blockquote><cite contenteditable="true">-- Write your own name here</cite></body>
</html>

效果如下,可以输入编辑html元素:
rich-text

💖 输入的光标位置(浏览器获取selection)

getSelection() method
GetSelection ()方法返回一个 Selection 对象,该对象表示用户选择的文本范围或插入符号的当前位置。

⭐使用Selection.toString () 返回指定的文本

例:

<body><blockquote contenteditable="true"><p>Edit this content to add your own quote</p></blockquote><cite contenteditable="true">-- Write your own name here</cite><button onclick="printSelection()">console.log(getSelection)</button></body>
<script type="text/javascript">const printSelection=()=>{const selection=window.getSelection()console.log('selection',selection)console.log('selection.toString()',selection.toString())}
</script>

效果如下:
selection.toString

⭐getRangeAt 获取指定索引范围

函数接受一个索引值
返回,其中
结束的索引值,endOffset
开始的索引值,startOffset
效果如下图:
getRangeAt

💖 修改光标位置

调用 setStart() 和 setEnd() 方法,来修改一个光标的位置或拖蓝范围
Range.setStart()
Range.setStart() 方法用于设置 Range的开始位置。

如果起始节点类型是 Text、Comment 或 CDATASection之一,那么 startOffset 指的是从起始节点算起字符的偏移量。对于其他 Node 类型节点,startOffset 是指从起始结点开始算起子节点的偏移量。

如果设置的起始位点在结束点之下(在文档中的位置),将会导致选区折叠,起始点和结束点都会被设置为指定的起始位置。
startNode
startNode 用于设定 Range的起始位置。

startOffset
必须为不小于 0 的整数。表示从startNode的开始位置算起的偏移量。
Range.setEnd()
Range.setEnd()
方法用于设置 Range的结束位置。

如果结束节点类型是 Text、Comment 或 CDATASection之一,那么 endOffset 指的是从结束节点算起字符的偏移量。对于其他 Node 类型节点,endOffset 是指从结束结点开始算起子节点的偏移量。

如果设置的结束点在起始点之上(在文档中的位置),将会导致选区折叠,起始点和结束点都会被设置为指定的结束位置。
endNode
endNode用于设定 Range的结束位置。

endOffset
必须为不小于 0 的整数。表示从endNode的结束位置算起的偏移量。
语法

range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);

例:
点击不失去焦点跳转开始和结束,避免失去焦点使用preventDefault

<body><blockquote contenteditable="true"><p>Edit this content to add your own quote</p></blockquote><cite contenteditable="true">-- Write your own name here</cite><button onclick="printSelection()">console.log(getSelection)</button><button id='start-id'>jumpt start</button><button id='end-id'>jumpt end</button></body>
<script type="text/javascript">function printSelection() {const selection = window.getSelection()console.log('selection', selection)console.log('selection.toString()', selection.toString())console.log('selection.getRangeAt(0)', selection.getRangeAt(0))}function jumpStart() {let range = window.getSelection().getRangeAt(0);let textEle = range.commonAncestorContainer;range.setStart(range.startContainer, 0);range.setEnd(range.startContainer, 0);}function jumpEnd() {let range = window.getSelection().getRangeAt(0);let textEle = range.commonAncestorContainer;range.setStart(range.startContainer, textEle.length);range.setEnd(range.endContainer, textEle.length);}window.onload = function() {document.getElementById('start-id').addEventListener('click', function(e) {jumpStart()})document.getElementById('start-id').addEventListener('mousedown', function(e) {e.preventDefault()})document.getElementById('end-id').addEventListener('click', function(e) {jumpEnd()})document.getElementById('end-id').addEventListener('mousedown', function(e) {e.preventDefault()})}
</script>

效果如下图:
riche-editor-positon

💖 设置选取range

Selection.addRange()
概述
向选区(Selection)中添加一个区域(Range)。

语法

sel.addRange(range)

例子:
失去焦点之后恢复选区

<body><blockquote contenteditable="true"><p>Edit this content to add your own quote</p><b>yma16</b></blockquote><cite contenteditable="true">-- Write your own name here</cite><br><button id='print-id'>console.log(getSelection)</button><br><br><button id='start-id'>jump start</button><button id='end-id'>jump end</button><button id='focus-id'>focus content</button></body>
<script type="text/javascript">const config = {selection: null}function printSelection() {const selection = window.getSelection()range = document.getSelection().getRangeAt(0).cloneRange();config.cloneRange = range;console.log('selection', selection)// console.log('selection.toString()', selection.toString())// console.log('selection.getRangeAt(0)', selection.getRangeAt(0))}function jumpStart() {let range = window.getSelection().getRangeAt(0);let textEle = range.commonAncestorContainer;range.setStart(range.startContainer, 0);range.setEnd(range.startContainer, 0);range = document.getSelection().getRangeAt(0).cloneRange();config.cloneRange = range;}function jumpEnd() {let range = window.getSelection().getRangeAt(0);let textEle = range.commonAncestorContainer;range.setStart(range.startContainer, textEle.length);range.setEnd(range.endContainer, textEle.length);range = document.getSelection().getRangeAt(textEle.length).cloneRange();config.cloneRange = range;}function focusContent() {document.getSelection().removeAllRanges(); //把没用的Ranges删除console.log('config.cloneRange',config.cloneRange)document.getSelection().addRange(config.cloneRange); //恢复Range}window.onload = function() {document.getElementById('print-id').addEventListener('click', function(e) {printSelection()})document.getElementById('print-id').addEventListener('mousedown', function(e) {e.preventDefault()})document.getElementById('start-id').addEventListener('click', function(e) {jumpStart()})document.getElementById('start-id').addEventListener('mousedown', function(e) {e.preventDefault()})document.getElementById('end-id').addEventListener('click', function(e) {jumpEnd()})document.getElementById('end-id').addEventListener('mousedown', function(e) {e.preventDefault()})document.getElementById('focus-id').addEventListener('click', function(e) {focusContent()})document.getElementById('focus-id').addEventListener('mousedown', function(e) {e.preventDefault()})}
</script>

效果如下:
focus-content

⭐总结

Contenteditable属性
Contenteditable是一种HTML属性,用于指定页面中的元素是否可以编辑。以下是Contenteditable的总结:

  1. Contenteditable属性可以应用于HTML元素上,如div、span、p、h1等等。

  2. 当Contenteditable属性设置为true时,用户可以编辑元素内的文本、图像等内容。

  3. Contenteditable属性的取值包括true和false,分别表示可编辑和不可编辑。

  4. Contenteditable属性可以通过JavaScript来动态修改。

  5. Contenteditable属性的兼容性很好,支持大多数现代浏览器。

  6. 虽然Contenteditable属性很方便,但也存在一些潜在的安全问题,因此应该谨慎使用。

富文本编辑器

富文本编辑器是一种允许用户编辑带有样式和格式的文本的编辑器。它与普通文本编辑器的区别在于,它允许用户使用各种字体、颜色、大小、加粗、斜体、下划线、超链接、图片等来设计和呈现文本内容。其原理主要包括以下几个方面:

  • DOM操作:富文本编辑器通过操作DOM树来实现文本样式和格式的改变。当用户在编辑器中输入或选择文本时,编辑器会将文本转换为DOM节点,并将节点添加到DOM树中。通过对DOM节点的增删改查,实现对文本样式和格式的修改操作。

  • 事件监听:通常情况下,富文本编辑器会监听用户的输入事件、鼠标点击事件和键盘事件等,以便及时捕捉用户的操作并做出相应的反应。

  • 样式和格式化:富文本编辑器通常内置了样式和格式化工具,比如字体、颜色、大小、加粗、斜体、下划线、超链接等,可以通过这些工具来控制文本的样式和格式。

  • 插件和组件:富文本编辑器可以通过插件和组件来扩展其功能,比如图片上传组件、表格插件、代码高亮插件等,可以让编辑器满足更多的需求。

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!
scene

👍 点赞,是我创作的动力!
⭐️ 收藏,是我努力的方向!
✏️ 评论,是我进步的财富!
💖 感谢你的阅读!

http://www.lryc.cn/news/182879.html

相关文章:

  • 堆--数据流中第K大元素
  • 【算法|动态规划No.12】leetcode152. 乘积最大子数组
  • Covert Communication 与选择波束(毫米波,大规模MIMO,可重构全息表面)
  • 计算机毕业设计 基于协调过滤算法的绿色食品推荐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
  • 华为云云耀云服务器L实例评测|部署在线影音媒体系统 Jellyfin
  • GhostNet原理解析及pytorch实现
  • 视频二维码的制作方法,支持内容修改编辑
  • 清华GLM部署记录
  • 贪心算法+练习
  • 使用华为eNSP组网试验⑷-OSPF多区域组网
  • P1843 奶牛晒衣服 【贪心】
  • 91、Redis - 事务 与 订阅-发布 相关的命令 及 演示
  • GPU如何成为AI的加速器
  • Map声明、元素访问及遍历、⼯⼚模式、实现 Set - GO语言从入门到实战
  • 机器人中的数值优化|【七】线性搜索牛顿共轭梯度法、可信域牛顿共轭梯度法
  • websocket实现go(server)与c#(client)通讯
  • 洛谷题目题解详细解答
  • 【C语言】八大排序算法
  • 2023年中国智能电视柜产量、需求量、市场规模及行业价格走势[图]
  • docker容器使用初体验
  • React Hooks ——性能优化Hooks
  • C#学习系列相关之多线程(一)----常用多线程方法总结
  • Vscode爆红Delete `␍`eslintprettier/prettier
  • Mac安装Ecplise产品报错:dose not contain the JNI_CreateJavaVM symbol
  • 如何使用大语言模型来绘制图画
  • 代码随想录算法训练营第23期day11 | 20. 有效的括号、1047. 删除字符串中的所有相邻重复项 、150. 逆波兰表达式求值
  • 数据结构-优先级队列(堆)
  • C++11新特性(语法糖,新容器)
  • 开机可用内存分析Tip
  • 【Python基础】4. 基本语句