Getting a text rich text editor

Brief introduction

Rich text editor, enabling webthe page, like word, like, realize editing of the text, usually used in some more text processing system. Now the industry has a lot of mature rich text editor, such as full-function ah TinyMCE , lightweight and efficient wangEditor , Baidu produced UEditor and so on. Many rich text editor, but few think about how to start from scratch, to achieve a rich text editor. This paper briefly from scratch how to implement a simple rich text editor.

Basic use

Common HTMLlabels can be input is generally only form, form input plain text, without the content format. Rich text relative to the form, be able to add some custom content styles to input text, such as bold, font color, background .... Rich text, mainly to the HTML tags, such as divadding a contenteditableproperty, possession of the property HTMLlabel, the label can be in the content, implement custom editing. The simplest rich text editor as follows:

<!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>

Basic Operations

Rich text similar to Word, there are many options for manipulating text, such as bold text, add background color, paragraph indents, use is imperative, only need to perform document.execCommand(aCommandName, aShowDefaultUI, aValueArgument), which aCommandNameis the command name , aShowDefaultUI
a Boolean, whether to show the user interface , generally false. Mozilla did not materialize. aValueArgument, Additional parameters , usually null.

Basic Operations Command

The following are some examples of simple operations rich text commands, some examples are given below using simple

command value Explanation
backcolor Color string Set the background color of the document
bold null The selected text bold
createlink URL string To convert the selected text into a link to the specified URL
indent null Indent text
copy null Copy the selected text to the clipboard
cut null Cut selected text to the clipboard
inserthorizontalrule null Hr insert a character at the insertion element

Example:

<!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>
      <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>

Text selection and range

Rich text, the text selection range and is a very powerful means of text selection, we can do some custom settings for the selected text. The core is two objects, Selectionand Rangeobjects. Comparison with the official statement is, Selectionthe object is represented by the current position of the text cursor or a range of user-selected , Rangethe object represents a portion of a document fragment comprising nodes and text nodes . In simple terms, Selectionrefers to the page, we all areas of the mouse to select, Rangerefer to the page in our mouse to select a single region, belonging to many relationship. For example, we want to get the selection object for the current page, you can call var selection = window.getSelection(), if you want to get to the first text selection information, you can call var rang = selection.getRangeAt(0), text selection to get information, the use of range.toString().
Text selection and range, is the use of a more classic, rich text format to paste filter . When we copy text into the rich text editor, this will retain the original format, if we are to remove the copy of the default format, leaving only plain text, how does it work?
Bloggers in dealing with this problem, the first thought is, you can listen to paste the event (paste), when you paste text, will replace the clipboard contents. It is also inside a pit, clipboard paste operation is not in force. In implementing functional requirements, the initial uses a regular match, remove HTML tags. But since the text format varied, often all kinds of weird characters, more problems, but when copying large text, page performance issues, this is not a good approach, really understand until later text range and selection , only to find this setting, delicious.
Rich text selection processing logic of the general idea is as follows:

  1. Paste text event listener
  2. Prevent the default event (to prevent the browser's default copy operation)
  3. Gets Copy plaintext
  4. Get the page text selection
  5. Delete selected text selection
  6. Create a text node
  7. Text node into constituencies
  8. Move focus to the end of the copied text

Sample code is as follows:

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)
})

Reference material

Published 184 original articles · won praise 141 · Views 350,000 +

Guess you like

Origin blog.csdn.net/sinat_27535209/article/details/104053520