H5 editor Core algorithms and ideas-, h5 Editor
The code and features are valid in the chrome49 test.
The essence of text rendering is the rendering of text nodes. The starting point and ending point can be obtained through the preset object Range in the browser.
var range = getRangeObject();var start = range.startOffset,end = range.endOffset;var startContainer = range.startContainer;var endContainer = range.endContainer;
The getRangeObjec code is as follows:
function getRangeObject(){if(window.getSelection){var selection = window.getSelection();if(selection.rangeCount > 0){return selection.getRangeAt(0);}}else if(document.selection){return document.selection.createRange(); }return null;};
View Code
The start point is always on the left, and the end point is always on the right.
Only when the start or end of the start point is <br/>, the returned result is not a text node. You can use start and end to determine that the position of the br element is startContainer. childNodes [start], endContainer. childNodes [end-1]. The returned text node start indicates the starting position of the cursor relative to the starting text node, and end indicates the Ending position of the cursor relative to the ending text node.
The algorithm for obtaining the next text node is
Function getNextTextNode (startNode, dir = "nextSibling") {// record the status before the startNode changes. if the status is invalid after the startNode changes, it is easy to roll back the let unchangeNode = startNode; if (startNode. nodeType = 3) {startNode = startNode [dir];} while (true) {if (startNode = undefined) {if (unchangeNode = undefined) {// protection mechanism throw new Error ("the program will be in an endless loop"); break;}/* The traversal of all selected nodes in the parent element of startNode is complete, direct the sartNode to the sibling node of the parent element */let parent = unchangeNode. parentElement; unchangeNode = parent; startNode = parent [dir];} else if (startNode. nodeType = 3) {// The text node exits the loop break;} else if (startNode. tagName = "BR") {// process a single tag to avoid unnecessary iterations of unchangeNode = startNode; startNode = startNode [dir];} else if (startNode. nodeType = 1) {/* if it is a dual-label element, enter */unchangeNode = startNode; if (dir = "previussibling") {startNode = $ (startNode ). contents (). last (). get (0);} else if (dir = "nextSibling") {startNode = $ (startNode ). contents (). first (). get (0) ;}else {// It is easy to locate the Error throw new Error ("Incorrect traversal direction:" + dir );}} else {// facilitate Error locating throw new Error ("unexpected element type =" "+ startNode) ;}} return startNode ;}
// The above functions replace recursion with external variables + while loops. The added protection mechanism reduces the poor experience caused by misuse and potential bugs.
Obtain all text nodes between the start and end nodes
function getTextNodes(startTextNode,endTextNode){ let textNodeArray = []; let node = startTextNode; while (true) { node = getNextTextNode(node); if(node == endTextNode){ break; } textNodeArray.push(node); } return textNodeArray;}
Appreciated support