我想要对一个指定起始位置和结束位置的文本范围进行高亮(应用CSS),但这比看起来更加困难,因为文本中可能会有其他需要忽略的标签。
例如:
<div>abcd<em>efg</em>hij</div>
highlight(2, 6)
需要在不删除标签的情况下突出显示"cdef
"。
我已经尝试使用TextRange对象,但没有成功。
预先感谢!
我想要对一个指定起始位置和结束位置的文本范围进行高亮(应用CSS),但这比看起来更加困难,因为文本中可能会有其他需要忽略的标签。
例如:
<div>abcd<em>efg</em>hij</div>
highlight(2, 6)
需要在不删除标签的情况下突出显示"cdef
"。
我已经尝试使用TextRange对象,但没有成功。
预先感谢!
document.execCommand(...)
生成的。您可以通过检查文档中每个跨度的计算值background-color
来搜索跨度,例如在https://dev59.com/NV3Ua4cB1Zd3GeqP9Bbc#8106283中所示。 - Tim Downhttp://mashajs.com/index_eng.html
这个项目也在GitHub上https://github.com/SmartTeleMax/MaSha。
即使在移动版Safari和IE上也可以正常运行!
我知道这个问题与此无关,但这正是我正在寻找的。
请使用以下原则:使用{{link1:Selection
}} {{link2:Range
}}方法进行操作,就像这样
document.getSelection().getRangeAt(0).surroundContents(YOUR_WRAPPER_NODE) // Adds wrapper
document.getSelection().getRangeAt(0).insertNode(NEW_NODE) // Inserts a new node
就是这样,我建议你多学习一下Range
方法。
我曾经也为此苦苦挣扎,我的搜索请求也不正确,所以我决定在这里发布它,以防有像我一样的人。
再次对不相关的答案表示抱歉。
YOUR_WRAPPER_NODE
和NEW_NODE
是同一个实体,因此最好将它们命名为相同的名称。此外,你的解决方案在范围包含部分选定元素时无法正常工作。在这种情况下,将调用surroundContents
替换为YOUR_WRAPPER_NODE.appendChild(document.getSelection().getRangeAt(0).extractContents())
。 - aadcg以下解决方案在IE上不起作用,您需要应用TextRange对象等。由于这使用选择来执行此操作,在正常情况下它不应该破坏HTML,例如:
<div>abcd<span>efg</span>hij</div>
使用 highlight(3,6);
输出:
<div>abc<em>d<span>ef</span></em><span>g</span>hij</div>
<div>abc<em>d<span>ef</em>g</span>hij</div>
代码:
var r = document.createRange();
var s = window.getSelection()
r.selectNode($('div')[0]);
s.removeAllRanges();
s.addRange(r);
// not quite sure why firefox has problems with this
if ($.browser.webkit) {
s.modify("move", "backward", "documentboundary");
}
function highlight(start,end){
for(var st=0;st<start;st++){
s.modify("move", "forward", "character");
}
for(var st=0;st<(end-start);st++){
s.modify("extend", "forward", "character");
}
}
highlight(2,6);
var ra = s.getRangeAt(0);
var newNode = document.createElement("em");
newNode.appendChild(ra.extractContents());
ra.insertNode(newNode);
例子:http://jsfiddle.net/niklasvh/4NDb9/
编辑 看起来至少我的FF4有一些问题。
s.modify("move", "backward", "documentboundary");
但同时,它似乎可以在没有它的情况下工作,所以我只是将其更改为
if ($.browser.webkit) {
s.modify("move", "backward", "documentboundary");
}
编辑 正如Tim所指出的,修改仅适用于FF4及以上版本,因此我采取了不同的方法来获取选择,这种方法不需要修改方法,希望能使它更具浏览器兼容性(IE仍需要自己的解决方案)。
代码:
var r = document.createRange();
var s = window.getSelection()
var pos = 0;
function dig(el){
$(el).contents().each(function(i,e){
if (e.nodeType==1){
// not a textnode
dig(e);
}else{
if (pos<start){
if (pos+e.length>=start){
range.setStart(e, start-pos);
}
}
if (pos<end){
if (pos+e.length>=end){
range.setEnd(e, end-pos);
}
}
pos = pos+e.length;
}
});
}
var start,end, range;
function highlight(element,st,en){
range = document.createRange();
start = st;
end = en;
dig(element);
s.addRange(range);
}
highlight($('div'),3,6);
var ra = s.getRangeAt(0);
var newNode = document.createElement("em");
newNode.appendChild(ra.extractContents());
ra.insertNode(newNode);
Selection.modify()
,并不支持WebKit支持的所有细粒度设置。具体而言,它不支持“documentboundary”。请参见https://developer.mozilla.org/en/DOM/selection/modify。 - Tim Down基于jQuery.highlight插件的思想。
private highlightRange(selector: JQuery, start: number, end: number): void {
let cur = 0;
let replacements: { node: Text; pos: number; len: number }[] = [];
let dig = function (node: Node): void {
if (node.nodeType === 3) {
let nodeLen = (node as Text).data.length;
let next = cur + nodeLen;
if (next > start && cur < end) {
let pos = cur >= start ? cur : start;
let len = (next < end ? next : end) - pos;
if (len > 0) {
if (!(pos === cur && len === nodeLen && node.parentNode &&
node.parentNode.childNodes && node.parentNode.childNodes.length === 1 &&
(node.parentNode as Element).tagName === 'SPAN' && (node.parentNode as Element).className === 'highlight1')) {
replacements.push({
node: node as Text,
pos: pos - cur,
len: len,
});
}
}
}
cur = next;
}
else if (node.nodeType === 1) {
let childNodes = node.childNodes;
if (childNodes && childNodes.length) {
for (let i = 0; i < childNodes.length; i++) {
dig(childNodes[i]);
if (cur >= end) {
break;
}
}
}
}
};
selector.each(function (index, element): void {
dig(element);
});
for (let i = 0; i < replacements.length; i++) {
let replacement = replacements[i];
let highlight = document.createElement('span');
highlight.className = 'highlight1';
let wordNode = replacement.node.splitText(replacement.pos);
wordNode.splitText(replacement.len);
let wordClone = wordNode.cloneNode(true);
highlight.appendChild(wordClone);
wordNode.parentNode.replaceChild(highlight, wordNode);
}
}
ab<x>cd<em>ef</x>f</em>
。你需要做类似这样的事情:ab<x>cd</x><em><x>ef</x>g</em>
。 - serg