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

富文本编辑器官网_富文本编辑器是做什么的富文本编辑器,能够使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>

文本范围与选区

  • 富文本中,文本范围和选区是一个非常强大的功能,借助于文本选区,我们可以对选中文本做一些自定义设置。核心是两个对象,SelectionRange对象。用比较官方的说法是,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

发表回复

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