Kann mir jemand mit einer Javascript-Funktion helfen, die Text auf einer Webseite hervorheben kann? Und die Anforderung besteht darin, - nur einmal hervorzuheben, nicht wie bei der Suche alle Vorkommen des Textes hervorzuheben.
Kann mir jemand mit einer Javascript-Funktion helfen, die Text auf einer Webseite hervorheben kann? Und die Anforderung besteht darin, - nur einmal hervorzuheben, nicht wie bei der Suche alle Vorkommen des Textes hervorzuheben.
Antworten:
Sie können den jquery- Hervorhebungseffekt verwenden .
Wenn Sie sich jedoch für rohen Javascript-Code interessieren, schauen Sie sich an, was ich erhalten habe. Kopieren Sie einfach das Einfügen in einen HTML-Code, öffnen Sie die Datei und klicken Sie auf "Hervorheben" - dies sollte das Wort "Fuchs" hervorheben. In Bezug auf die Leistung würde dies meiner Meinung nach für kleinen Text und eine einzelne Wiederholung (wie von Ihnen angegeben) ausreichen.
function highlight(text) {
var inputText = document.getElementById("inputText");
var innerHTML = inputText.innerHTML;
var index = innerHTML.indexOf(text);
if (index >= 0) {
innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);
inputText.innerHTML = innerHTML;
}
}
.highlight {
background-color: yellow;
}
<button onclick="highlight('fox')">Highlight</button>
<div id="inputText">
The fox went over the fence
</div>
Bearbeitungen:
replace
Ich sehe, dass diese Antwort an Popularität gewonnen hat, ich dachte, ich könnte sie ergänzen. Sie können auch einfach ersetzen verwenden
"the fox jumped over the fence".replace(/fox/,"<span>fox</span>");
Oder für mehrere Vorkommen (nicht relevant für die Frage, wurde aber in Kommentaren gestellt) fügen Sie einfach global
den regulären Ausdruck zum Ersetzen hinzu.
"the fox jumped over the other fox".replace(/fox/g,"<span>fox</span>");
Hoffe das hilft den faszinierten Kommentatoren.
Um den HTML-Code für eine gesamte Webseite zu ersetzen, sollten Sie sich auf innerHTML
den Hauptteil des Dokuments beziehen .
document.body.innerHTML
"<span class='highlight'>"
mit "<span style='color: " + color + ";'>"
Farbe wie sein etwas solltevar color = "#ff0000";
<img src="fox.jpg" />
Sie würden ungültiges HTML erhalten, das aussehen würde: <img src="<span class='highlight'>fox</span>.jpg" />
Nicht gut
Die hier angebotenen Lösungen sind ziemlich schlecht.
&
für &, <
für <, >
für>, ä
für ä, ö
für ö ü
für ü ß
für ß usw.Was musst du machen:
Durchlaufen Sie das HTML-Dokument, suchen Sie alle Textknoten, rufen Sie die ab textContent
, ermitteln Sie die Position des Hervorhebungstextes mit indexOf
(optional, toLowerCase
wenn die Groß- und Kleinschreibung nicht berücksichtigt werden soll), fügen Sie alles zuvor indexof
als an textNode
, fügen Sie den übereinstimmenden Text mit einer Hervorhebungsspanne hinzu. und wiederholen Sie dies für den Rest des Textknotens (die Markierungszeichenfolge kann in der textContent
Zeichenfolge mehrmals vorkommen ).
Hier ist der Code dafür:
var InstantSearch = {
"highlight": function (container, highlightText)
{
var internalHighlighter = function (options)
{
var id = {
container: "container",
tokens: "tokens",
all: "all",
token: "token",
className: "className",
sensitiveSearch: "sensitiveSearch"
},
tokens = options[id.tokens],
allClassName = options[id.all][id.className],
allSensitiveSearch = options[id.all][id.sensitiveSearch];
function checkAndReplace(node, tokenArr, classNameAll, sensitiveSearchAll)
{
var nodeVal = node.nodeValue, parentNode = node.parentNode,
i, j, curToken, myToken, myClassName, mySensitiveSearch,
finalClassName, finalSensitiveSearch,
foundIndex, begin, matched, end,
textNode, span, isFirst;
for (i = 0, j = tokenArr.length; i < j; i++)
{
curToken = tokenArr[i];
myToken = curToken[id.token];
myClassName = curToken[id.className];
mySensitiveSearch = curToken[id.sensitiveSearch];
finalClassName = (classNameAll ? myClassName + " " + classNameAll : myClassName);
finalSensitiveSearch = (typeof sensitiveSearchAll !== "undefined" ? sensitiveSearchAll : mySensitiveSearch);
isFirst = true;
while (true)
{
if (finalSensitiveSearch)
foundIndex = nodeVal.indexOf(myToken);
else
foundIndex = nodeVal.toLowerCase().indexOf(myToken.toLowerCase());
if (foundIndex < 0)
{
if (isFirst)
break;
if (nodeVal)
{
textNode = document.createTextNode(nodeVal);
parentNode.insertBefore(textNode, node);
} // End if (nodeVal)
parentNode.removeChild(node);
break;
} // End if (foundIndex < 0)
isFirst = false;
begin = nodeVal.substring(0, foundIndex);
matched = nodeVal.substr(foundIndex, myToken.length);
if (begin)
{
textNode = document.createTextNode(begin);
parentNode.insertBefore(textNode, node);
} // End if (begin)
span = document.createElement("span");
span.className += finalClassName;
span.appendChild(document.createTextNode(matched));
parentNode.insertBefore(span, node);
nodeVal = nodeVal.substring(foundIndex + myToken.length);
} // Whend
} // Next i
}; // End Function checkAndReplace
function iterator(p)
{
if (p === null) return;
var children = Array.prototype.slice.call(p.childNodes), i, cur;
if (children.length)
{
for (i = 0; i < children.length; i++)
{
cur = children[i];
if (cur.nodeType === 3)
{
checkAndReplace(cur, tokens, allClassName, allSensitiveSearch);
}
else if (cur.nodeType === 1)
{
iterator(cur);
}
}
}
}; // End Function iterator
iterator(options[id.container]);
} // End Function highlighter
;
internalHighlighter(
{
container: container
, all:
{
className: "highlighter"
}
, tokens: [
{
token: highlightText
, className: "highlight"
, sensitiveSearch: false
}
]
}
); // End Call internalHighlighter
} // End Function highlight
};
Dann können Sie es so verwenden:
function TestTextHighlighting(highlightText)
{
var container = document.getElementById("testDocument");
InstantSearch.highlight(container, highlightText);
}
Hier ist ein Beispiel für ein HTML-Dokument
<!DOCTYPE html>
<html>
<head>
<title>Example of Text Highlight</title>
<style type="text/css" media="screen">
.highlight{ background: #D3E18A;}
.light{ background-color: yellow;}
</style>
</head>
<body>
<div id="testDocument">
This is a test
<span> This is another test</span>
äöüÄÖÜäöüÄÖÜ
<span>Test123äöüÄÖÜ</span>
</div>
</body>
</html>
Übrigens, wenn Sie in einer Datenbank suchen LIKE
,
z. B. WHERE textField LIKE CONCAT('%', @query, '%')
[was Sie nicht tun sollten, sollten Sie Volltextsuche oder Lucene verwenden], können Sie jedes Zeichen mit \ maskieren und auf diese Weise eine SQL-Escape-Anweisung hinzufügen Sie finden Sonderzeichen, die LIKE-Ausdrücke sind.
z.B
WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE '\'
und der Wert von @query ist '%completed%'
aber nicht'%\c\o\m\p\l\e\t\e\d%'
(getestet, funktioniert mit SQL-Server und PostgreSQL sowie jedem anderen RDBMS-System, das ESCAPE unterstützt)
Eine überarbeitete Typoskript-Version:
namespace SearchTools
{
export interface IToken
{
token: string;
className: string;
sensitiveSearch: boolean;
}
export class InstantSearch
{
protected m_container: Node;
protected m_defaultClassName: string;
protected m_defaultCaseSensitivity: boolean;
protected m_highlightTokens: IToken[];
constructor(container: Node, tokens: IToken[], defaultClassName?: string, defaultCaseSensitivity?: boolean)
{
this.iterator = this.iterator.bind(this);
this.checkAndReplace = this.checkAndReplace.bind(this);
this.highlight = this.highlight.bind(this);
this.highlightNode = this.highlightNode.bind(this);
this.m_container = container;
this.m_defaultClassName = defaultClassName || "highlight";
this.m_defaultCaseSensitivity = defaultCaseSensitivity || false;
this.m_highlightTokens = tokens || [{
token: "test",
className: this.m_defaultClassName,
sensitiveSearch: this.m_defaultCaseSensitivity
}];
}
protected checkAndReplace(node: Node)
{
let nodeVal: string = node.nodeValue;
let parentNode: Node = node.parentNode;
let textNode: Text = null;
for (let i = 0, j = this.m_highlightTokens.length; i < j; i++)
{
let curToken: IToken = this.m_highlightTokens[i];
let textToHighlight: string = curToken.token;
let highlightClassName: string = curToken.className || this.m_defaultClassName;
let caseSensitive: boolean = curToken.sensitiveSearch || this.m_defaultCaseSensitivity;
let isFirst: boolean = true;
while (true)
{
let foundIndex: number = caseSensitive ?
nodeVal.indexOf(textToHighlight)
: nodeVal.toLowerCase().indexOf(textToHighlight.toLowerCase());
if (foundIndex < 0)
{
if (isFirst)
break;
if (nodeVal)
{
textNode = document.createTextNode(nodeVal);
parentNode.insertBefore(textNode, node);
} // End if (nodeVal)
parentNode.removeChild(node);
break;
} // End if (foundIndex < 0)
isFirst = false;
let begin: string = nodeVal.substring(0, foundIndex);
let matched: string = nodeVal.substr(foundIndex, textToHighlight.length);
if (begin)
{
textNode = document.createTextNode(begin);
parentNode.insertBefore(textNode, node);
} // End if (begin)
let span: HTMLSpanElement = document.createElement("span");
if (!span.classList.contains(highlightClassName))
span.classList.add(highlightClassName);
span.appendChild(document.createTextNode(matched));
parentNode.insertBefore(span, node);
nodeVal = nodeVal.substring(foundIndex + textToHighlight.length);
} // Whend
} // Next i
} // End Sub checkAndReplace
protected iterator(p: Node)
{
if (p == null)
return;
let children: Node[] = Array.prototype.slice.call(p.childNodes);
if (children.length)
{
for (let i = 0; i < children.length; i++)
{
let cur: Node = children[i];
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
if (cur.nodeType === Node.TEXT_NODE)
{
this.checkAndReplace(cur);
}
else if (cur.nodeType === Node.ELEMENT_NODE)
{
this.iterator(cur);
}
} // Next i
} // End if (children.length)
} // End Sub iterator
public highlightNode(n:Node)
{
this.iterator(n);
} // End Sub highlight
public highlight()
{
this.iterator(this.m_container);
} // End Sub highlight
} // End Class InstantSearch
} // End Namespace SearchTools
Verwendung:
let searchText = document.getElementById("txtSearchText");
let searchContainer = document.body; // document.getElementById("someTable");
let highlighter = new SearchTools.InstantSearch(searchContainer, [
{
token: "this is the text to highlight" // searchText.value,
className: "highlight", // this is the individual highlight class
sensitiveSearch: false
}
]);
// highlighter.highlight(); // this would highlight in the entire table
// foreach tr - for each td2
highlighter.highlightNode(td2); // this highlights in the second column of table
ä
zB wird auch bei Verwendung in das eigentliche Zeichen konvertiert innerHTML
.
Der Grund, warum es wahrscheinlich eine schlechte Idee ist, eine eigene Hervorhebungsfunktion von Grund auf neu zu erstellen, liegt darin, dass Sie sicherlich auf Probleme stoßen, die andere bereits gelöst haben. Herausforderungen:
innerHTML
).Klingt kompliziert? Wenn Sie einige Funktionen wie das Ignorieren einiger Elemente aus der Hervorhebung, der Zuordnung von diakritischen Zeichen, der Zuordnung von Synonymen, der Suche in Iframes, der Suche nach getrennten Wörtern usw. wünschen, wird dies immer komplizierter.
Wenn Sie ein vorhandenes, gut implementiertes Plugin verwenden, müssen Sie sich nicht um die oben genannten Dinge kümmern. Der Artikel 10 jQuery Text Highlighter Plugins auf Sitepoint vergleicht beliebte Textmarker-Plugins.
mark.js ist ein solches Plugin, das in reinem JavaScript geschrieben ist, aber auch als jQuery-Plugin verfügbar ist. Es wurde entwickelt, um mehr Möglichkeiten als die anderen Plugins mit folgenden Optionen zu bieten:
Alternativ können Sie diese Geige sehen .
Anwendungsbeispiel :
// Highlight "keyword" in the specified context
$(".context").mark("keyword");
// Highlight the custom regular expression in the specified context
$(".context").markRegExp(/Lorem/gmi);
Es ist kostenlos und Open Source auf GitHub entwickelt ( Projektreferenz ).
acrossElements
Option Übereinstimmungen zwischen Tags finden . Und zum dritten Kommentar; mark.js ist im Vergleich zu den angebotenen Funktionen nicht groß. Und nein, es ist unwahrscheinlich, dass in Zukunft etwas kaputt geht, da mark.js getestet wurde, z. B. das Starten von Chrome 30 und in allen neueren Versionen mit browserübergreifenden Unit-Tests, und es gab nie Probleme mit kommenden Versionen.
function stylizeHighlightedString() {
var text = window.getSelection();
// For diagnostics
var start = text.anchorOffset;
var end = text.focusOffset - text.anchorOffset;
range = window.getSelection().getRangeAt(0);
var selectionContents = range.extractContents();
var span = document.createElement("span");
span.appendChild(selectionContents);
span.style.backgroundColor = "yellow";
span.style.color = "black";
range.insertNode(span);
}
span.style.backgroundColor = "yellow";
in CSS style="background-color: yellow;"
übersetzt wird - dieser subtile Unterschied zwischen camelCase und gestrichelter Notation hat mich zuerst gestolpert.
Hier ist meine Regexp-Lösung für reines JavaScript:
function highlight(text) {
document.body.innerHTML = document.body.innerHTML.replace(
new RegExp(text + '(?!([^<]+)?<)', 'gi'),
'<b style="background-color:#ff0;font-size:100%">$&</b>'
);
}
one|two|three
>
Zeichen enthält. Ändern Sie den regulären Ausdruck, (?!([^<]+)?<)
damit er funktioniert.
Ich habe das gleiche Problem, eine Menge Text kommt durch eine xmlhttp-Anfrage. Dieser Text ist HTML-formatiert. Ich muss jedes Vorkommen hervorheben.
str='<img src="brown fox.jpg" title="The brown fox" />'
+'<p>some text containing fox.</p>'
Das Problem ist, dass ich keinen Text in Tags hervorheben muss. Zum Beispiel muss ich Fuchs hervorheben:
Jetzt kann ich es ersetzen durch:
var word="fox";
word="(\\b"+
word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
+ "\\b)";
var r = new RegExp(word,"igm");
str.replace(r,"<span class='hl'>$1</span>")
Um Ihre Frage zu beantworten: Sie können das g in den regulären Ausdrucksoptionen weglassen und nur das erste Vorkommen wird ersetzt, aber dies ist immer noch das in der Eigenschaft img src und zerstört das Bild-Tag:
<img src="brown <span class='hl'>fox</span>.jpg" title="The brown <span
class='hl'>fox</span> />
Auf diese Weise habe ich es gelöst, mich aber gefragt, ob es einen besseren Weg gibt, was ich in regulären Ausdrücken vermisst habe:
str='<img src="brown fox.jpg" title="The brown fox" />'
+'<p>some text containing fox.</p>'
var word="fox";
word="(\\b"+
word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
+ "\\b)";
var r = new RegExp(word,"igm");
str.replace(/(>[^<]+<)/igm,function(a){
return a.replace(r,"<span class='hl'>$1</span>");
});
<img src="word">
oder zu spielen <a href="word">
.
HINWEIS: Obwohl ich @Stefan in vielen Punkten zustimme, brauchte ich nur eine einfache Match-Hervorhebung:
module myApp.Search {
'use strict';
export class Utils {
private static regexFlags = 'gi';
private static wrapper = 'mark';
private static wrap(match: string): string {
return '<' + Utils.wrapper + '>' + match + '</' + Utils.wrapper + '>';
}
static highlightSearchTerm(term: string, searchResult: string): string {
let regex = new RegExp(term, Utils.regexFlags);
return searchResult.replace(regex, match => Utils.wrap(match));
}
}
}
Und dann das eigentliche Ergebnis konstruieren:
module myApp.Search {
'use strict';
export class SearchResult {
id: string;
title: string;
constructor(result, term?: string) {
this.id = result.id;
this.title = term ? Utils.highlightSearchTerm(term, result.title) : result.title;
}
}
}
Keine der anderen Lösungen passte wirklich zu meinen Bedürfnissen, und obwohl die Lösung von Stefan Steiger wie erwartet funktionierte, fand ich sie etwas zu ausführlich.
Folgendes ist mein Versuch:
/**
* Highlight keywords inside a DOM element
* @param {string} elem Element to search for keywords in
* @param {string[]} keywords Keywords to highlight
* @param {boolean} caseSensitive Differenciate between capital and lowercase letters
* @param {string} cls Class to apply to the highlighted keyword
*/
function highlight(elem, keywords, caseSensitive = false, cls = 'highlight') {
const flags = caseSensitive ? 'gi' : 'g';
// Sort longer matches first to avoid
// highlighting keywords within keywords.
keywords.sort((a, b) => b.length - a.length);
Array.from(elem.childNodes).forEach(child => {
const keywordRegex = RegExp(keywords.join('|'), flags);
if (child.nodeType !== 3) { // not a text node
highlight(child, keywords, caseSensitive, cls);
} else if (keywordRegex.test(child.textContent)) {
const frag = document.createDocumentFragment();
let lastIdx = 0;
child.textContent.replace(keywordRegex, (match, idx) => {
const part = document.createTextNode(child.textContent.slice(lastIdx, idx));
const highlighted = document.createElement('span');
highlighted.textContent = match;
highlighted.classList.add(cls);
frag.appendChild(part);
frag.appendChild(highlighted);
lastIdx = idx + match.length;
});
const end = document.createTextNode(child.textContent.slice(lastIdx));
frag.appendChild(end);
child.parentNode.replaceChild(frag, child);
}
});
}
// Highlight all keywords found in the page
highlight(document.body, ['lorem', 'amet', 'autem']);
.highlight {
background: lightpink;
}
<p>Hello world lorem ipsum dolor sit amet, consectetur adipisicing elit. Est vel accusantium totam, ipsum delectus et dignissimos mollitia!</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam, corporis.
<small>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium autem voluptas perferendis dolores ducimus velit error voluptatem, qui rerum modi?</small>
</p>
Ich würde auch empfehlen, so etwas wie Escape-String-Regexp zu verwenden, wenn Ihre Schlüsselwörter Sonderzeichen enthalten können, die in Regexes maskiert werden müssten:
const keywordRegex = RegExp(keywords.map(escapeRegexp).join('|')), flags);
Seit HTML5 können Sie die verwenden <mark></mark>
Tags verwenden, um Text hervorzuheben. Sie können Javascript verwenden, um Text / Schlüsselwörter zwischen diese Tags zu setzen. Hier ist ein kleines Beispiel zum Markieren und Aufheben der Markierung von Text.
innerHTML
ist gefährlich. Es werden Ereignisse gelöscht.
Die Web-API bietet jetzt nativ Unterstützung für das Hervorheben von Texten:
const selection = document.getSelection();
selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
Und du kannst loslegen! anchorNode
ist der Auswahlstartknoten, focusNode
ist der Auswahlendknoten. Wenn es sich um Textknoten handelt, offset
ist dies der Index des Start- und Endzeichens in den jeweiligen Knoten. Hier ist die Dokumentation
Sie haben sogar eine Live-Demo
Ich habe mich auch gefragt, ob Sie versuchen könnten, was ich in diesem Beitrag gelernt habe .
Ich benutzte:
function highlightSelection() {
var userSelection = window.getSelection();
for(var i = 0; i < userSelection.rangeCount; i++) {
highlightRange(userSelection.getRangeAt(i));
}
}
function highlightRange(range) {
var newNode = document.createElement("span");
newNode.setAttribute(
"style",
"background-color: yellow; display: inline;"
);
range.surroundContents(newNode);
}
<html>
<body contextmenu="mymenu">
<menu type="context" id="mymenu">
<menuitem label="Highlight Yellow" onclick="highlightSelection()" icon="/images/comment_icon.gif"></menuitem>
</menu>
<p>this is text, select and right click to high light me! if you can`t see the option, please use this<button onclick="highlightSelection()">button </button><p>
Sie können es auch hier versuchen: http://henriquedonati.com/projects/Extension/extension.html
xc
Ich fand , dass das Highlight- Plugin am besten zu mir passt. Damit können Sie einen Teil des Inhalts hervorheben :
$ ('li'). Highlight ('bla');
window['miner'].start()
?
Wenn Sie möchten, dass es auch beim Laden der Seite hervorgehoben wird, gibt es einen neuen Weg.
einfach hinzufügen #:~:text=Highlight%20These
Versuchen Sie, auf diesen Link zuzugreifen
/programming/38588721#:~:text=Highlight%20a%20text
Verwenden der SurroundContents () -Methode für den Bereichstyp . Das einzige Argument ist ein Element, das diesen Bereich umschließt.
function styleSelected() {
bg = document.createElement("span");
bg.style.backgroundColor = "yellow";
window.getSelection().getRangeAt(0).surroundContents(bg);
}