富文本编辑器官网_富文本编辑器是做什么的

富文本编辑器官网_富文本编辑器是做什么的富文本编辑器,能够使web页面像word一样,实现对文本的编辑,通常应用在一些文本处理比较多的系统中。现在业界有很多成熟的富文本编辑器,比如功能齐全啊TinyMCE、轻量高效的wangEditor、百度出品的UEditor等。富文本编辑器很多,但是却很少思考如何从零开始,实现一…

简介

富文本编辑器,能够使web页面像word一样,实现对文本的编辑,通常应用在一些文本处理比较多的系统中。现在业界有很多成熟的富文本编辑器,比如功能齐全啊TinyMCE、轻量高效的wangEditor、百度出品的UEditor等。富文本编辑器很多,但是却很少思考如何从零开始,实现一个富文本编辑器。本文主要简述如何从零开始,实现一个简易的富文本编辑器。

基本使用

普通的HTML标签,能够输入的通常只是表单,表单输入的是纯文本,不带格式的内容。富文本相对于表单,能够给输入文本内容增加一些自定义内容样式,比如加粗、字体颜色、背景…。富文本的实现,主要是给HTML标签,比如div增加一个contenteditable属性,拥有该属性的HTML标签,就能够对该标签里的内容,实现自定义的编辑。最简单的富文本编辑器如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
     
</head>
<body>
    <div id="app" style="width: 200px;height: 200px;background-color: antiquewhite;" contenteditable='true'></div>
</body>
</html>

基本操作

富文本类似于Word,有很多操作文本选项,比如文本的加粗、添加背景颜色、段落缩进等,使用方式是命令式的,只需要执行document.execCommand(aCommandName, aShowDefaultUI, aValueArgument),其中aCommandName是命令名称,aShowDefaultUI 一个 Boolean, 是否展示用户界面,一般为 false。Mozilla 没有实现。aValueArgument,额外参数,一般为null。

基本操作命令

以下简单列举一些富文本操作命令,下面给出一些例子的简单使用

命令 值 说明
backcolor 颜色字符串 设置文档的背景颜色
bold null 将选择的文本加粗
createlink URL字符串 将选择的文本转换成一个链接,指向指定的URL
indent null 缩进文本
copy null 将选择的文本复制到剪切板
cut null 将选择文本剪切到剪切板
inserthorizontalrule null 在插入字符处插入一个hr元素

Example:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
    <style> html, body{ width: 100%; height: 100%; padding: 0; margin: 0; } #app{ display: flex; flex-direction: column; justify-content: flex-start; width: calc(100% - 100px); height: calc(100% - 100px); padding: 50px; } .operator-menu{ display: flex; justify-content: flex-start; align-items: center; width: 100%; min-height: 50px; background-color: beige; padding: 0 10px; } .edit-area{ width: 100%; min-height: 600px; background-color: blanchedalmond; padding: 20px; } .operator-menu-item{ padding: 5px 10px; background-color: cyan; border-radius: 10px; cursor: pointer; margin: 0 5px; } </style>
  </head>
  <body>
    <div id="app">
      <div class="operator-menu">
        <div class="operator-menu-item" data-fun='fontBold'>加粗</div>
        <div class="operator-menu-item" data-fun='textIndent'>缩进</div>
        <div class="operator-menu-item" data-fun='inserthorizontalrule'>插入分隔符</div>
        <div class="operator-menu-item" data-fun='linkUrl'>链接百度</div>
      </div>
      <div class="edit-area" contenteditable="true"></div>
    </div>
    <script> let operationItems = document.querySelector('.operator-menu') // 事件监听采用mousedown,click事件会导致富文本编辑框失去焦点 operationItems.addEventListener('mousedown', function(e) { let target = e.target let funName = target.getAttribute('data-fun') if (!window[funName]) return window[funName]() // 要阻止默认事件,否则富文本编辑框的选中区域会消失 e.preventDefault() }) function fontBold () { document.execCommand('bold') } function textIndent () { document.execCommand('indent') } function inserthorizontalrule () { document.execCommand('inserthorizontalrule') } function linkUrl () { document.execCommand('createlink', null, 'www.baidu.com') } </script>
  </body>
</html>

文本范围与选区

  • 富文本中,文本范围和选区是一个非常强大的功能,借助于文本选区,我们可以对选中文本做一些自定义设置。核心是两个对象,Selection和Range对象。用比较官方的说法是,Selection对象,表示用户选择的文本范围或光标的当前位置,Range对象表示一个包含节点与文本节点的一部分的文档片段。简单来说,Selection是指页面中,我们鼠标选中的所有区域,Range是指页面中我们鼠标选中的单个区域,属于一对多的关系。比如,我们要获取当前页面的选区对象,可以调用var selection = window.getSelection(),如果想要获取到第一个文本选区信息,可以调用var rang = selection.getRangeAt(0),获取到选区文本信息,采用range.toString()。
  • 文本范围与选区,一个比较经典的用法就是,富文本粘贴格式过滤。在我们往富文本编辑器中复制文本时,会保留原文本的格式,如果我们要去除复制的默认格式,只保留纯文本,该如何操作呢?
  • 博主在处理这个问题时,首先想到的是,能不能监听粘贴事件(paste),在粘贴文本时,将剪切板内容替换掉。这一个里面也是有坑的,粘贴时操作剪切板是不生效的。在实现功能需求时,最初采用的是正则匹配,去除HTML标签。奈何文本格式五花八门,经常出现各种奇奇怪怪的字符,问题比较多,而且复制大文本时,页面存在性能问题,这并不是一种好的处理方式,直到后来真正理解了文本范围与选区,才发现这个设置,真香。 富文本选区的处理逻辑大致思路如下:
  1. 监听文本粘贴事件
  2. 阻止默认事件(阻止浏览器默认复制操作)
  3. 获取复制纯文本
  4. 获取页面文本选区
  5. 删除已选中文本选区
  6. 创建文本节点
  7. 将文本节点插入到选区中
  8. 将焦点移动到复制文本结尾

获取粘贴纯文本

let $editArea = document.querySelector('.edit-area')
$editArea.addEventListener('paste', e => {
    // 阻止默认的复制事件
    e.preventDefault()
    let txt = ''
    let range = null
    // 获取复制的文本
    txt = e.clipboardData.getData('text/plain')
    // 获取页面文本选区
    range = window.getSelection().getRangeAt(0)
    // 删除默认选中文本
    range.deleteContents()
    // 创建一个文本节点,用于替换选区文本
    let pasteTxt = document.createTextNode(txt)
    // 插入文本节点
    range.insertNode(pasteTxt)
    // 将焦点移动到复制文本结尾
    range.collapse(false)
})

除此之外,还有很多操作可以借助于选区来实现,比如光标的定位、选中区域内容包裹其他样式等。

实现手动将光标定位到最后一个字符


function keepLastIndex(element) {
    if (element && element.focus){
        element.focus();
    } else {
        return
    }
    let range = document.createRange();
    range.selectNodeContents(element);
    range.collapse(false);
    let sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
}

选中区域包裹其他样式

function addCode () {
    let selection = window.getSelection()
    // 暂时处理第一个选区
    let range = selection.getRangeAt(0)
    // 拷贝一份原始选中数据
    let cloneNodes = range.cloneContents()
    // 移除选区
    range.deleteContents()
    // 创建内容容器
    let codeContainer = document.createElement('code')
    codeContainer.appendChild(cloneNodes)
    // 往选区内添加文本
    range.insertNode(codeContainer)
}

附件

以下为测试代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <!-- https://electronjs.org/docs/tutorial/security#csp-meta-tag -->
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
    <style> html, body{ width: 100%; height: 100%; padding: 0; margin: 0; } #app{ display: flex; flex-direction: column; justify-content: flex-start; width: calc(100% - 100px); height: calc(100% - 100px); padding: 50px; } .operator-menu{ display: flex; justify-content: flex-start; align-items: center; width: 100%; min-height: 50px; background-color: beige; padding: 0 10px; } .edit-area{ width: 100%; min-height: 600px; background-color: blanchedalmond; padding: 20px; } .operator-menu-item{ padding: 5px 10px; background-color: cyan; border-radius: 10px; cursor: pointer; margin: 0 5px; } </style>
  </head>
  <body>
    <div id="app">
      <div class="operator-menu">
        <div class="operator-menu-item" data-fun='fontBold'>加粗</div>
        <div class="operator-menu-item" data-fun='textIndent'>缩进</div>
        <div class="operator-menu-item" data-fun='inserthorizontalrule'>插入分隔符</div>
        <div class="operator-menu-item" data-fun='linkUrl'>链接百度</div>
        <div class="operator-menu-item" data-fun='addCode'>code</div>
      </div>
      <div class="edit-area" contenteditable="true"></div>
    </div>
    <script> let operationItems = document.querySelector('.operator-menu') // 事件监听采用mousedown,click事件会导致富文本编辑框失去焦点 operationItems.addEventListener('mousedown', function(e) { let target = e.target let funName = target.getAttribute('data-fun') if (!funName) return window[funName]() // 要阻止默认事件,否则富文本编辑框的选中区域会消失 e.preventDefault() }) let $editArea = document.querySelector('.edit-area') $editArea.addEventListener('paste', e => { // 阻止默认的复制事件 e.preventDefault() let txt = '' let range = null // 获取复制的文本 txt = e.clipboardData.getData('text/plain') // 获取页面文本选区 range = window.getSelection().getRangeAt(0) // 删除默认选中文本 range.deleteContents() // 创建一个文本节点,用于替换选区文本 let pasteTxt = document.createTextNode(txt) // 插入文本节点 range.insertNode(pasteTxt) // 将焦点移动到复制文本结尾 range.collapse(false) keepLastIndex($editArea) }) function fontBold () { document.execCommand('bold') } function textIndent () { document.execCommand('indent') } function inserthorizontalrule () { document.execCommand('inserthorizontalrule') } function linkUrl () { document.execCommand('createlink', null, 'www.baidu.com') } function addCode () { let selection = window.getSelection() // 暂时处理第一个选区 let range = selection.getRangeAt(0) // 拷贝一份原始选中数据 let cloneNodes = range.cloneContents() // 移除选区 range.deleteContents() // 创建内容容器 let codeContainer = document.createElement('code') codeContainer.appendChild(cloneNodes) // 往选区内添加文本 range.insertNode(codeContainer) } function keepLastIndex(element) { if (element && element.focus){ element.focus(); } else { return } let range = document.createRange(); range.selectNodeContents(element); range.collapse(false); let sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } </script>
  </body>
</html>

参考资料

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13734.html

赞 (0)

相关推荐

  • 使用mypy提高Python代码质量

    使用mypy提高Python代码质量Python是一种简单易学的语言,拥有着强大的生态系统,并广泛应用于各种领域,如Web开发、数据分析、机器学习等等。然而,由于Python是一种动态类型语言,使用过程中容易出现类型错误,因此Python代码的质量往往无法与静态类型语言相提并论。为此,我们需要一种工具来保证Python代码的质量,这就是我们所要介绍的mypy。

    2024-05-27
    84
  • sql server decode函数_怎么将时间转化为字符串

    sql server decode函数_怎么将时间转化为字符串一.字符串函数 参数character_expression:由字符数据组成的字母数字表达式,可以是常量或变量,也可以是字符列或二进制数据列 参数integer_expression:是正整数,如果

    2022-12-30
    143
  • python训练营第一周(python训练营怎么样)

    python训练营第一周(python训练营怎么样)网络爬虫又称网络蜘蛛、网络蚂蚁、网络机器人等,可以自动化浏览网络中的信息,当然浏览信息的时候需要按照我们制定的规则进行,这些规则我们称之为网络爬虫算法。使用Python可以很方便地编写出爬虫程序,进行互联网信息的自动化检索。

    2023-11-18
    134
  • pg相关参考文档

    pg相关参考文档pg_probackup :https://postgrespro.com/docs/postgrespro/10/app-pgprobackup digoal blog: https://gith…

    2023-03-12
    162
  • 20200618_MySQL实战45讲_学习笔记_Order by

    20200618_MySQL实战45讲_学习笔记_Order by表结构 — auto-generated definition create table product_application_config ( id bigint auto_increment…

    2023-03-13
    160
  • Python数值处理:快速高效地进行数字计算

    Python数值处理:快速高效地进行数字计算Python作为一种高级编程语言,在数据科学领域表现出了强大的计算能力。Python作为一种动态的解释型语言,有很多便于快速开发的库可供使用,例如NumPy、SciPy和Pandas等。这些库用Python编写,主要用于进行快速的矢量化计算,以及对大规模数据进行高效处理。

    2024-04-04
    77
  • 删除Python

    删除PythonPython是一门非常流行的编程语言,它可以帮助我们完成各种任务。但是,在某些情况下,我们可能需要删除Python或者Python的某些模块。在本文中,我们将从多个方面来详细介绍如何删除Python。

    2024-06-06
    45
  • Oracle中的函数——Trunc()[亲测有效]

    Oracle中的函数——Trunc()[亲测有效]trunc(exp1) trunc(exp1)和Round(exp1,exp2)类似,只不过trunc()不指定截取的小数位数进行处理,只取到整数位,不做舍去处理 select trunc(123.1

    2023-02-20
    156

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注