视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
H5编辑器核心思想的实例分析
2020-11-27 15:07:42 责编:小采
文档


代码和特性在chrome49下测试有效。

文本渲染的本质是对文本节点的渲染,通过浏览器内置的对象Range可以获得选择的起始点、与终止点

var range = getRangeObject();var start = range.startOffset,
end = range.endOffset;var startContainer = range.startContainer;var endContainer = range.endContainer;

getRangeObjec代码如下

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

 起始点始终在左面,终止点始终在右面,不受选择方向的影响。

  只有当起始点的开头或终止点的末尾是<br/>时,返回的不是文本节点,可以通过start,end确定br元素的位置分别是startContainer.childNodes[start],endContainer.childNodes[end-1]。返回的是文本节点start表示光标相对于起始文本节点所在的起始位置,end表示光标相对于终止文本节点所在的终止位置。

获得下一个文本节点的算法为

function getNextTextNode(startNode,dir = "nextSibling"){//记录startNode变化之前的状态,startNode变化后无效时便于状态的回滚let unchangeNode = startNode;if(startNode.nodeType == 3){
 startNode = startNode[dir];
 }while (true){if(startNode == undefined){if(unchangeNode == undefined){//保护机制throw new Error("程序会陷入死循环");break;
 }/*startNode所在的父元素所有选中节点遍历完毕,将sartNode指向父元素的兄弟节点*/let parent = unchangeNode.parentElement;
 unchangeNode = parent;
 startNode = parent[dir];
 }else if(startNode.nodeType == 3){//文本节点则退出循环break;
 }else if(startNode.tagName == "BR"){//处理单标签,避免不必要的迭代unchangeNode = startNode;
 startNode = startNode[dir];
 }else if(startNode.nodeType == 1){/*如果是双标签元素则进入*/unchangeNode = startNode;if(dir == "previousSibling"){

 startNode = $(startNode).contents().last().get(0);
 }else if(dir == "nextSibling"){
 startNode = $(startNode).contents().first().get(0);
 }else {//便于错误的定位throw new Error("错误的遍历方向:"+dir);
 }
 }else {//便于错误的定位throw new Error("不期待的元素类型=》"+startNode);

 }
 } return startNode;
 
}

  //上述函数用外部变量+while循环的方式取代递归,加入的保护机制减少误用、潜在bug导致极差的体验。
获得起始节点和结束节点之间的所有文本节点

function getTextNodes(startTextNode,endTextNode){
 let textNodeArray = [];
 let node = startTextNode;while (true) {
 node = getNextTextNode(node);if(node == endTextNode){break;
 }
 textNodeArray.push(node);
 } return textNodeArray;
}

下载本文
显示全文
专题