考慮以下我需要突出顯示搜索文本的示例192.168.1.1HTML 。這只是一個示例,文本搜索和 HTML 結構是完全任意的,因為它將在最終用戶網站上運行,并帶有他們的輸入。該程式還將對插入的 執行其他操作span,而不僅僅是突出顯示(例如,在懸停時顯示工具提示,但只要我有span插入,這不是問題)。
編輯:我剛剛發現一個新行會導致中間的空格textContent不再正確。但是,我會將它們保留在那里以獲得更好的視覺效果。您可以檢查下面的代碼片段以獲取正確的 HTML 代碼
<div>
<span class="foo-1">The computer address</span>
<em>is</em>
<span class="ip-1">192</span>.
<span class="ip-2">168</span>.
<span class="ip-3">1</span>.
<span class="ip-4">1</span>
</div>
使用textContentor innerText,很容易找到我需要的帶有潛文本的最接近的元素(div示例中的有192.168.1.1全文)。但是下一步我想在不破壞原始結構或其他 HTML/CSSclass或屬性的情況下包裝這些部分。理想情況下,我希望最終的 HTML 為:
<div>
<span class="foo-1">The computer address</span>
<em>is</em>
<span class="my-highlight-span"><span class="ip-1">192</span>.
<span class="ip-2">168</span>.
<span class="ip-3">1</span>.
<span class="ip-4">1</span></span>
</div>
使用深度優先搜索我可以很容易地到達div,但是我不知道如何從那里繼續。還有一個棘手的案例:
<div>
<span class="foo-1">The computer address</span>
<em>is
<span class="ip-1">192</span>.</em>
<span class="ip-2">168</span>.
<span class="ip-3">1</span>.
<span class="ip-4">1</span>
</div>
我認為如果有解決方案,這應該是實作它的最簡單方法:
<div>
<span class="foo-1">The computer address</span>
<em>is
<span class="my-highlight-span"><span class="ip-1">192</span>.</span></em><span class="my-highlight-span">
<span class="ip-2">168</span>.
<span class="ip-3">1</span>.
<span class="ip-4">1</span></span>
</div>
如果相關代碼將在 Chrome 擴展環境中執行,但我認為這應該是純瀏覽器 Javascript 問題。
這是一個片段,您可以嘗試一下:
function transform(el, text) {
// Transform this Element to highlight text
}
const text = "192.168.1.1";
transform(document.querySelector("#case-1"), text);
transform(document.querySelector("#case-2"), text);
transform(document.querySelector("#case-simple"), text);
.my-highlight-span {
background-color: cornflowerblue;
}
<p>Case 1:</p>
<div id="case-1">
<span class="foo-1">The computer address</span>
<em>is</em>
<span class="ip-1">192</span>.<span class="ip-2">168</span>.<span class="ip-3">1</span>.<span class="ip-4">1</span>
</div>
<p>Case 2:</p>
<div id="case-2">
<span class="foo-1">The computer address</span>
<em>is
<span class="ip-1">192</span>.</em><span class="ip-2">168</span>.<span class="ip-3">1</span>.<span class="ip-4">1</span>
</div>
<p>Simple case:</p>
<div id="case-simple">
The computer address is 192.168.1.1
</div>
<hr />
<p>Desired Result:</p>
<div id="case-1-result">
<span class="foo-1">The computer address</span>
<em>is</em>
<span class="my-highlight-span"><span class="ip-1">192</span>.<span class="ip-2">168</span>.<span class="ip-3">1</span>.<span class="ip-4">1</span></span>
</div>
<div id="case-2-result">
<span class="foo-1">The computer address</span>
<em>is
<span class="my-highlight-span"><span class="ip-1">192</span>.</span></em><span class="my-highlight-span">
<span class="ip-2">168</span>.<span class="ip-3">1</span>.<span class="ip-4">1</span></span>
</div>
<div id="case-simple-result">
The computer address is <span class="my-highlight-span">192.168.1.1</span>
</div>
uj5u.com熱心網友回復:
我終于使用RangeAPI得到了答案,歸功于這里的精彩解釋和Range.surroundContents().
使用
scanForText我遞回掃描的方法textContent來TEXT_NODE確定搜索詞的開始和結束。然后我使用
RangeAPI 來選擇和提取內容,并在用我的span.
顯然有一些限制,但這應該適用于大多數情況。例如,在情況 2 中,我的代碼會<span >在內部生成一個額外的空<em>.
function scanForText(el, expectingStart, expectingEnd, result) {
if (el.nodeType === Node.TEXT_NODE) {
const nodeContent = el.textContent;
result[4] = nodeContent;
const currText = result[4];
if (expectingStart < currText.length && !result[0]) {
result[0] = el;
result[1] = expectingStart - (currText.length - nodeContent.length);
}
if (expectingEnd <= currText.length && !result[2]) {
result[2] = el;
result[3] = expectingEnd - (currText.length - nodeContent.length);
return;
}
} else {
for (let childEl of el.childNodes) {
scanForText(childEl, expectingStart, expectingEnd, result);
if (result[2]) { // When already found ending, return
return;
}
}
}
}
function transform(el, text) {
const fullText = el.textContent;
const startIndex = fullText.indexOf(text);
const endIndex = startIndex text.length;
const scanState = [null, -1, null, -1, ""];
scanForText(el, startIndex, endIndex, scanState);
const [startNode, startRangeIndex, endNode, endRangeIndex] = scanState;
if (!startNode || !endNode) {
console.warn("This should not be happening");
return;
}
const range = new Range();
range.setStart(startNode, startRangeIndex);
range.setEnd(endNode, endRangeIndex);
const surrounding = document.createElement("span");
surrounding.className = "my-highlight-span";
// This can't be used when cutting one text boundary.
// Alternative is offered at https://developer.mozilla.org/en-US/docs/Web/API/Range/surroundContents
// range.surroundContents(surrounding)
const extracted = range.extractContents();
surrounding.appendChild(extracted);
range.insertNode(surrounding);
}
const text = "192.168.1.1";
transform(document.querySelector("#case-1"), text);
transform(document.querySelector("#case-2"), text);
transform(document.querySelector("#case-simple"), text);
.my-highlight-span {
background-color: cornflowerblue;
}
<p>Case 1:</p>
<div id="case-1">
<span class="foo-1">The computer address</span>
<em>is</em>
<span class="ip-1">192</span>.<span class="ip-2">168</span>.<span class="ip-3">1</span>.<span class="ip-4">1</span>
</div>
<p>Case 2:</p>
<div id="case-2">
<span class="foo-1">The computer address</span>
<em>is
<span class="ip-1">192</span>.</em><span class="ip-2">168</span>.<span class="ip-3">1</span>.<span class="ip-4">1</span>
</div>
<p>Simple case:</p>
<div id="case-simple">
The computer address is 192.168.1.1
</div>
<hr />
<p>Desired Result:</p>
<div id="case-1-result">
<span class="foo-1">The computer address</span>
<em>is</em>
<span class="my-highlight-span"><span class="ip-1">192</span>.<span class="ip-2">168</span>.<span class="ip-3">1</span>.<span class="ip-4">1</span></span>
</div>
<div id="case-2-result">
<span class="foo-1">The computer address</span>
<em>is
<span class="my-highlight-span"><span class="ip-1">192</span>.</span></em><span class="my-highlight-span">
<span class="ip-2">168</span>.<span class="ip-3">1</span>.<span class="ip-4">1</span></span>
</div>
<div id="case-simple-result">
The computer address is <span class="my-highlight-span">192.168.1.1</span>
</div>
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/419811.html
標籤:
上一篇:雞尾酒排序總是比冒泡排序更好嗎?
下一篇:串列之間的交集長度串列串列
