ilP*_*tiz 1 javascript range selection contenteditable rich-text-editor
我正在尝试一下contentEditable并遇到这个问题:我有以下js片段
var range = document.getSelection().getRangeAt(0);
var newNode = document.createElement("span");
newNode.className = "customStyle";
range.surroundContents(newNode);
Run Code Online (Sandbox Code Playgroud)
这个HTML片段:
<ul>
<li>the <b>only entry</b> of the list</li>
</ul>
<p>Some text here in paragraph</p>
Run Code Online (Sandbox Code Playgroud)
js代码允许使用<span>标记包装当前选择.
当选择包括整个HTML标签(例如,选择'唯一条目')时,它完美地工作,但当然,当选择仅包括其结尾之一时(例如,从'条目'选择'有些',两者都包括在内) .
虽然我知道这个问题并非无足轻重,但我正在寻找有关最佳方法的建议.提前致谢!
如果您只对包装文本部分感兴趣,那么基本方法是:
<span>元素中的每个文本节点这是我的Rangy库的类应用程序模块采用的方法.
我创建了一个例子,主要是使用改编自Rangy的代码:
function getNextNode(node) {
var next = node.firstChild;
if (next) {
return next;
}
while (node) {
if ( (next = node.nextSibling) ) {
return next;
}
node = node.parentNode;
}
}
function getNodesInRange(range) {
var start = range.startContainer;
var end = range.endContainer;
var commonAncestor = range.commonAncestorContainer;
var nodes = [];
var node;
// Walk parent nodes from start to common ancestor
for (node = start.parentNode; node; node = node.parentNode) {
nodes.push(node);
if (node == commonAncestor) {
break;
}
}
nodes.reverse();
// Walk children and siblings from start until end is found
for (node = start; node; node = getNextNode(node)) {
nodes.push(node);
if (node == end) {
break;
}
}
return nodes;
}
function getNodeIndex(node) {
var i = 0;
while ( (node = node.previousSibling) ) {
++i;
}
return i;
}
function insertAfter(node, precedingNode) {
var nextNode = precedingNode.nextSibling, parent = precedingNode.parentNode;
if (nextNode) {
parent.insertBefore(node, nextNode);
} else {
parent.appendChild(node);
}
return node;
}
// Note that we cannot use splitText() because it is bugridden in IE 9.
function splitDataNode(node, index) {
var newNode = node.cloneNode(false);
newNode.deleteData(0, index);
node.deleteData(index, node.length - index);
insertAfter(newNode, node);
return newNode;
}
function isCharacterDataNode(node) {
var t = node.nodeType;
return t == 3 || t == 4 || t == 8 ; // Text, CDataSection or Comment
}
function splitRangeBoundaries(range) {
var sc = range.startContainer, so = range.startOffset, ec = range.endContainer, eo = range.endOffset;
var startEndSame = (sc === ec);
// Split the end boundary if necessary
if (isCharacterDataNode(ec) && eo > 0 && eo < ec.length) {
splitDataNode(ec, eo);
}
// Split the start boundary if necessary
if (isCharacterDataNode(sc) && so > 0 && so < sc.length) {
sc = splitDataNode(sc, so);
if (startEndSame) {
eo -= so;
ec = sc;
} else if (ec == sc.parentNode && eo >= getNodeIndex(sc)) {
++eo;
}
so = 0;
}
range.setStart(sc, so);
range.setEnd(ec, eo);
}
function getTextNodesInRange(range) {
var textNodes = [];
var nodes = getNodesInRange(range);
for (var i = 0, node, el; node = nodes[i++]; ) {
if (node.nodeType == 3) {
textNodes.push(node);
}
}
return textNodes;
}
function surroundRangeContents(range, templateElement) {
splitRangeBoundaries(range);
var textNodes = getTextNodesInRange(range);
if (textNodes.length == 0) {
return;
}
for (var i = 0, node, el; node = textNodes[i++]; ) {
if (node.nodeType == 3) {
el = templateElement.cloneNode(false);
node.parentNode.insertBefore(el, node);
el.appendChild(node);
}
}
range.setStart(textNodes[0], 0);
var lastTextNode = textNodes[textNodes.length - 1];
range.setEnd(lastTextNode, lastTextNode.length);
}
document.onmouseup = function() {
if (window.getSelection) {
var templateElement = document.createElement("span");
templateElement.className = "highlight";
var sel = window.getSelection();
var ranges = [];
var range;
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
ranges.push( sel.getRangeAt(i) );
}
sel.removeAllRanges();
// Surround ranges in reverse document order to prevent surrounding subsequent ranges messing with already-surrounded ones
i = ranges.length;
while (i--) {
range = ranges[i];
surroundRangeContents(range, templateElement);
sel.addRange(range);
}
}
};Run Code Online (Sandbox Code Playgroud)
.highlight {
font-weight: bold;
color: red;
}Run Code Online (Sandbox Code Playgroud)
Select some of this text and it will be highlighted:
<ul>
<li>the <b>only entry</b> of the list</li>
</ul>
<p>Some text here in paragraph</p>
<ul>
<li>the <b>only entry</b> of the list</li>
</ul>
<p>Some text here in paragraph</p>
<ul>
<li>the <b>only entry</b> of the list</li>
</ul>
<p>Some text here in paragraph</p>Run Code Online (Sandbox Code Playgroud)