gpt4 book ai didi

javascript 在遇到意外的 anchorOffset 时执行多个 createrange()

转载 作者:行者123 更新时间:2023-11-30 19:51:49 24 4
gpt4 key购买 nike

我的目标:

Let users highlight different substring in a single long string.

但是,一旦我用 range.surroundContents(newNode) 突出显示了一个子字符串(newNode 是一个黄色背景的 span),innerHTML整个长字符串的一部分发生了变化——它开始包含 span元素;因此,如果用户想要在同一个长字符串中突出显示前一个突出显示的子字符串之后的子字符串,则 anchorOffset将返回从 after 开始的索引上一个跨度。

例如,在这个长字符串中:

"Mr. and Mrs. Dursley, of number four, Privet Drive, were proud to say that they were perfectly normal, thank you very much."

这个长句子被p包裹起来类名是noting .如果range.surroundContents()方法子字符串“女贞路”,然后,当我想得到 window.getSelection().anchorOffset子串“thank”的错误答案是53,而正确答案应该是102。我应该怎么做?谢谢!!

附言我不想用substring方法找位置,谢谢!

$(".noting").mouseup(function(e){            
$("#noteContent").val("");/*flushing*/
curSentNum = $(this).attr("id").split("-")[1];
$('#curSentNum').val(curSentNum);
highlightLangName = $(this).attr("id").split("-")[2];
$('#highlightLangName').val(highlightLangName);
//console.log(".noting $(this).html()"+$(this).html()+" "+$(this).attr("id"));//id, for example: p-2-French
if (window.getSelection) {
highlightedText = window.getSelection().toString();
curAnchorOffset = window.getSelection().anchorOffset;

$('#anchorAt').val(curAnchorOffset);
$('#highlightLen').val(highlightedText.length);

}
else if (document.selection && document.selection.type != "Control") {
highlightedText = document.selection.createRange().text;
}

});

然后我将保存 anchorAt信息到数据库;在 db 操作之后,我将立即使用之前保留的变量调用此函数:

function highlightNoteJustSaved(){
var curI = noteCounter;
var anchorAt = parseInt($("#anchorAt").val());
var highlightLen = parseInt($("#highlightLen").val());
/*p to find, for example: p-2-French*/
var curP = document.getElementById('p-'+curSentNum.toString()+"-"+$("#highlightLangName").val());
var range = document.createRange();
root_node = curP;

range.setStart(root_node.childNodes[0], anchorAt);
range.setEnd(root_node.childNodes[0], anchorAt+highlightLen);

var newNode = document.createElement("span");
newNode.style.cssText="background-color:#ceff99";//yellow
newNode.className = alreadyNoteStr;
newNode.setAttribute('id','already-note-'+curI.toString());

range.surroundContents(newNode);
}

对于HTML树节点结构,请看下面的评论(我没有弄清楚如何在这个提问区复制粘贴代码)。

最佳答案

我用两种方法替换了您突出显示文本的方法。 highlightTextNodes 查找节点内容中的单词。寻找每个 child 。我还实现了一个高光去除器来展示它是如何工作的。我用 mark 标签替换了 span

let alreadyNoteStr = 'already';
let noteCounter = 0;
let elementId;

$('p.noting').mouseup(function(e) {
elementId = $(this).attr('id');
$('#noteContent').val(''); /*flushing*/
curSentNum = elementId.split('-')[1];
$('#curSentNum').val(curSentNum);
highlightLangName = elementId.split('-')[2];
$('#highlightLangName').val(highlightLangName);
//console.log(".noting $(this).html()"+$(this).html()+" "+$(this).attr("id"));//id, for example: p-2-French
if (window.getSelection) {
highlightedText = window.getSelection().toString();
curAnchorOffset = window.getSelection().anchorOffset;

$("#noteContent").val(highlightedText);
$('#anchorAt').val(curAnchorOffset);
$('#highlightLen').val(highlightedText.length);

highlight(elementId, highlightedText);
} else if (document.selection && document.selection.type != "Control") {
highlightedText = document.selection.createRange().text;
}
});

function highlightNoteJustSaved() {
let curI = noteCounter;
let anchorAt = parseInt($("#anchorAt").val());
let highlightLen = parseInt($("#highlightLen").val());
/*p to find, for example: p-2-French*/
let curP = document.getElementById('p-' + curSentNum.toString() + "-" + $("#highlightLangName").val());
let range = document.createRange();
rootNode = curP;
let childNode = rootNode.childNodes[0];

range.setStart(rootNode.childNodes[0], anchorAt);
range.setEnd(rootNode.childNodes[0], anchorAt + highlightLen);

var newNode = document.createElement("span");
newNode.style.cssText = "background-color:#ceff99"; //yellow
newNode.className = alreadyNoteStr;
newNode.setAttribute('id', 'already-note-' + curI.toString());

range.surroundContents(newNode);
}

/*
* Takes in an array of consecutive TextNodes and returns a document fragment with `word` highlighted
*/
function highlightTextNodes(nodes, word) {
if (!nodes.length) {
return;
}

let text = '';

// Concatenate the consecutive nodes to get the actual text
for (var i = 0; i < nodes.length; i++) {
text += nodes[i].textContent;
}

let fragment = document.createDocumentFragment();

while (true) {
// Tweak this if you want to change the highlighting behavior
var index = text.toLowerCase().indexOf(word.toLowerCase());

if (index === -1) {
break;
}

// Split the text into [before, match, after]
var before = text.slice(0, index);
var match = text.slice(index, index + word.length);
text = text.slice(index + word.length);

// Create the <mark>
let mark = document.createElement('mark');
mark.className = 'found';
mark.appendChild(document.createTextNode(match));

// Append it to the fragment
fragment.appendChild(document.createTextNode(before));
fragment.appendChild(mark);
}

// If we have leftover text, just append it to the end
if (text.length) {
fragment.appendChild(document.createTextNode(text));
}

// Replace the nodes with the fragment
nodes[0].parentNode.insertBefore(fragment, nodes[0]);

for (var i = 0; i < nodes.length; i++) {
let node = nodes[nodes.length - i - 1];
node.parentNode.removeChild(node);
}
}


/*
* Highlights all instances of `word` in `$node` and its children
*/
function highlight(id, word) {
let node = document.getElementById(id);
let children = node.childNodes;
let currentRun = [];

for (var i = 0; i < children.length; i++) {
let child = children[i];

if (child.nodeType === Node.TEXT_NODE) {
// Keep track of consecutive text nodes
currentRun.push(child);
} else {
// If we hit a regular element, highlight what we have and start over
highlightTextNodes(currentRun, word);
currentRun = [];

// Ignore text inside of our <mark>s
if (child.nodeType === Node.ELEMENT_NODE && child.className !== 'found') {
highlight(child, word);
}
}
}

// Just in case we have only text nodes as children
if (currentRun.length) {
highlightTextNodes(currentRun, word);
}
}

/*
* Removes all highlighted <mark>s from the given node
*/
function unhighlight(id) {
let node = document.getElementById(id);
let marks = [].slice.call(node.querySelectorAll('mark.found'));

for (var i = 0; i < marks.length; i++) {
let mark = marks[i];

// Replace each <mark> with just a text node of its contents
mark.parentNode.replaceChild(document.createTextNode(mark.childNodes[0].textContent), mark);
}
}
label {
display: block;
position: relative;
padding-left: 100px;
}

button {
margin-top: 20px;
margin-bottom: 20px;
padding: 10px;
}

label>span {
position: absolute;
left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" onclick="unhighlight(elementId);">Unhighlight</button>
<div id="div-0" class="only-left-border">
<p class="lan-English noting" id="p-1-English">Mr. and Mrs. Dursley, of number four, Privet Drive, were proud to say that they were perfectly normal, thank you very much.</p>
</div>

<label><span>Content:</span><input type="text" id="noteContent"></input></label>
<label><span>Numer:</span><input type="text" id="curSentNum"></input></label>
<label><span>Language:</span><input type="text" id="highlightLangName"></input></label>
<label><span>Anchor:</span><input type="text" id="anchorAt"></input></label>
<label><span>Length:</span><input type="text" id="highlightLen"></input></label>

关于javascript 在遇到意外的 anchorOffset 时执行多个 createrange(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54393815/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com