Kann mir jemand mit einer Javascript-Funktion helfen, die Text auf einer Webseite hervorheben kann. Und die Anforderung ist, - nur einmal hervorzuheben, nicht wie bei der Suche alle Vorkommen des Textes hervorzuheben.
Sie können die Abfrage Hervorhebungseffekt verwenden.
Wenn Sie sich für rohen Javascript-Code interessieren, schauen Sie sich an, was ich habe. Kopieren Sie einfach den Code 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
verwendenIch habe gesehen, dass diese Antwort an Popularität gewonnen hat. Ich dachte, ich könnte sie ergänzen. Sie können auch leicht ersetzen
"the fox jumped over the fence".replace(/fox/,"<span>fox</span>");
Oder Sie fügen bei mehreren Vorkommen (die für die Frage nicht relevant sind, aber in Kommentaren angegeben wurden) einfach global
zum regulären Ersetzungsausdruck hinzu.
"the fox jumped over the other fox".replace(/fox/g,"<span>fox</span>");
Hoffe das hilft den neugierigen Kommentatoren.
um den HTML-Code für eine gesamte Webseite zu ersetzen, sollten Sie sich auf innerHTML
im Hauptteil des Dokuments beziehen.
document.body.innerHTML
Die hier angebotenen Lösungen sind ziemlich schlecht.
&
Für &, <
Für <, >
Für>, ä
Für ä, ö
Für ö ü
für ü ß
für ß usw.Was Sie tun müssen:
Durchlaufen Sie das HTML-Dokument, finden Sie alle Textknoten, holen Sie sich das textContent
, holen Sie sich die Position des Hervorhebungs-Texts mit indexOf
(mit einem optionalen toLowerCase
, falls dies der Fall sein sollte -unempfindlich), füge alles vor indexof
als textNode
an, füge den übereinstimmenden Text mit einem Hervorhebungsbereich an und wiederhole ihn für den Rest des Textknotens (die Hervorhebungszeichenfolge kann in textContent
string).
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 kannst du es so benutzen:
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 mit LIKE
in einer Datenbank suchen,
z.B. WHERE textField LIKE CONCAT('%', @query, '%')
[was du nicht machen solltest, du solltest Volltextsuche oder Lucene benutzen], dann kannst du jedes Zeichen mit\maskieren und eine SQL-Escape-Anweisung hinzufügen, damit du Sonderzeichen findest das sind LIKE-Ausdrücke.
z.B.
WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE '\'
und der Wert von @query ist nicht '%completed%'
, sondern '%\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 TypeScript-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
Der Grund, warum es wahrscheinlich eine schlechte Idee ist, Ihre eigene Hervorhebungsfunktion von Grund auf neu zu erstellen, ist, dass Sie mit Sicherheit auf Probleme stoßen, die andere bereits gelöst haben. Herausforderungen:
innerHTML
der Fall wäre).Hört sich kompliziert an? Wenn Sie einige Funktionen wie das Ignorieren einiger Elemente von Hervorhebungen, diakritischen Zuordnungen, Synonymzuordnungen, die Suche in Iframes, die 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 Highlighter 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 zu bieten, mit Optionen für:
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 ).
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);
}
Ich habe das gleiche Problem, eine Reihe von 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 markieren:
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 die Optionen für g in regulären Ausdrücken 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, den 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>");
});
HINWEIS: Obwohl ich in vielen Punkten mit @Stefan einverstanden bin, brauchte ich nur eine einfache Übereinstimmungsmarkierung:
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;
}
}
}
Hier ist meine reine JavaScript-Lösung für reguläre Ausdrücke:
function highlight(text) {
document.body.innerHTML = document.body.innerHTML.replace(
new RegExp(text + '(?!([^<]+)?<)', 'gi'),
'<b style="background-color:#ff0;font-size:100%">$&</b>'
);
}
Keine der anderen Lösungen entsprach wirklich meinen Anforderungen, und obwohl die Lösung von Stefan Steiger erwartungsgemäß 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, etwas wie escape-string-regexp zu verwenden, wenn Ihre Schlüsselwörter Sonderzeichen enthalten können, die in regulären Ausdrücken maskiert werden müssten:
const keywordRegex = RegExp(keywords.map(escapeRegexp).join('|')), flags);
Seit HTML5 können Sie das <mark></mark>
Tags zum Markieren von Text. Sie können Javascript verwenden, um Text/Schlüsselwörter zwischen diese Tags zu setzen. Hier finden Sie ein kleines Beispiel für das Markieren und Aufheben der Markierung von Text.
Ich habe mich auch gefragt, ob Sie versuchen können, was ich auf this post 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 habe festgestellt, dass das markieren Plugin die beste Übereinstimmung ist. Mit diesem Plugin können Sie einen Teil des Inhalts markieren :
$ ('li'). highlight ('bla');