Developing Rich Text Editor under vue takes you from beginners to abandonment. Personal development has been basically completed.

Keywords: Attribute Fragment git github

The last summary:

In fact, the basic principles of code development in the last article are almost the same, but there is an infinite nesting problem.

Summarize the problems encountered by rich text:

1. Element cross-label processing

2. How to correctly select the elements you want

3. Partial line breaks are not selected in the cross-line setting element (due to default carriage return event)

4. Direct cross-use of multiple functions (trade-offs)

5. The Mixed Problem of New and Old css

6. Code Block Insertion

7. In fact, there are more problems, but those that have not been developed really do not know the various tastes among them....

The unsolved problems are as follows:

Implementing the return label of csdn (this is a special problem, too many operations will lead to stylistic stagnation, and the problem that the return can not be successfully returned requires a separate return operation)

Here I hope that the development team of CSDN can tell me how to implement the return operation of rich text of csdn. There is no thought now.

Core Code Section:

This is what I think is the most core part of the operation, the core here is the operation of document fragments.

Because the operation principle is to get the element you selected first, then to operate on this part of the element, and then re-insert it. (First select and then get element processing, then delete and re-insert, first delete and then insert)

My code doesn't have any compatibility. It's actually a week from the last development to the present full calculation.

Another key piece of code is that basically all custom operations are implemented by this api.

document.execCommand("insertHTML", false, `<br>`);
import { CursorAcquisition } from "./selection";
import { delCss } from "./tool";
//Document Fragment Processing
const domFragmentHandle = () => {
  const { range } = CursorAcquisition();

  //Get the elements that need to be manipulated for processing
  let domst = range.commonAncestorContainer;
  domst = domst.nodeType === 1 ? domst : domst.parentNode;

  //Get the css attribute getSelectionText in the element
  let cssText = domst.style.cssText;

  let innerhtml = "";
  console.log("Nodes currently captured", domst.nodeName);
  //Processing node name, returning null if specified
  let nodeName = domst.nodeName;
  let nodelist = ["div"];

  if (nodelist.indexOf(nodeName.toLocaleLowerCase()) !== -1) {
    nodeName = "";
  }
  nodeName = nodeName.toLocaleLowerCase();

  //Judgment processing, if the parent node is the largest div, then change the selection method
  if (domst.id === "dht-editor-content") {
    let span = document.createElement("span");
    let elem = range.cloneContents();
    span.appendChild(elem);
    innerhtml = span.innerHTML;
  } else {
    //console.log(domst.childNodes);
    //dom element processing, do not need redundant tags, string extraction, but pay attention to maintaining the document structure.
    // However, this operation will result in invalid multi-line document indentation, etc.
    let child = domst.childNodes;
    for (let i = 0; i < child.length; i++) {
      if (child[i].nodeName === "BR") {
        innerhtml += `<br>`;
      } else {
        let node = child[i];
        innerhtml += node.nodeValue ? node.nodeValue : node.innerText;
      }
    }
  }

  //Ultimately returns the required elements
  return {
    innerhtml,
    cssText,
    nodeName
  };
};
//Independently selected area text
const getSelectionText = () => {
  const { range } = CursorAcquisition();

  //Get the css attribute in the element
  let cssText = "";

  let span = document.createElement("span");
  let elem = range.cloneContents();
  span.appendChild(elem);
  let innerhtml = span.innerHTML;

  //Ultimately returns the required elements
  return {
    innerhtml,
    cssText
  };
};
//Final Execution Function
const execOperation = (name, value = null) => {
  const { range } = CursorAcquisition();
  if (!range.toString()) {
    console.log("No element was selected");
    return false;
  }
  let bool = document.execCommand(name, false, value);

  range.detach();

  return bool;
};
//Generating html strings
//Afferent parameters:
/*
 * Inserted node name,
 * style: del: css name to be deleted
 * css: css for final application
 * */
const combinationHtml = style => {
  const { innerhtml, cssText, nodeName } = domFragmentHandle();
  let delcss = style.del || "";
  let css = style.css || "";
  let node = style.node || "span";
  let url = style.url;

  //let html = style.html || `<${node} style="${oldCss}; ${css}">${innerhtml}</${node}>`
  //Previous css
  let oldCss = cssText ? delCss(cssText, delcss) : "";

  console.log("html Processing", nodeName);
  //New and old node judgment processing, special nodes need to use old nodes such as span can not be mixed with h2
  if (nodeName && node !== nodeName && node !== "a") {
    node = nodeName;
  }
  //Define html elements to be inserted
  let html = "";
  if (node === "a") {
    html = `<${node} href="${url}" style="${oldCss}; ${css}">${innerhtml}</${node}>`;
  } else {
    html = `<${node} style="${oldCss}; ${css}">${innerhtml}</${node}>`;
  }

  console.log(html);
  return html;
};
export { domFragmentHandle, execOperation, getSelectionText, combinationHtml };

Personal git address:

https://github.com/ht-sauce/dream

Rich text file address:

dream/src/components/richTextEditor/

Access address: http://localhost:8080/dht_blog/richTextEditor

In the middle of the development, I want to give up a little:

The reason is that I added a group of wang rich texts. One of the developers said that it was meaningless, wasting time. He also said that he could write one for me in a year. I really have no help so far. Fortunately, wang rich texts are open source. (Thank you)

To the rich text address of wang: http://wangeditor.com

Posted by Zooter on Thu, 08 Aug 2019 03:04:04 -0700