Quelqu'un peut-il m'aider avec une fonction javascript qui peut mettre en évidence du texte sur une page Web. Et l'exigence est de - mettre en surbrillance une seule fois, et non comme toutes les occurrences du texte, comme nous le faisons en cas de recherche.
Vous pouvez utiliser le jquery effet de surbrillance .
Mais si le code JavaScript brut vous intéresse, jetez un coup d'œil à ce que j'ai obtenu. Copiez-le simplement, collez-le dans un fichier HTML, ouvrez le fichier et cliquez sur "mettre en évidence". Le mot "renard" doit alors être mis en évidence. Performance sage, je pense que cela ferait pour petit texte et une répétition unique (comme vous l'avez spécifié)
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>
Modifications:
replace
Je vois que cette réponse a gagné en popularité, je pensais pouvoir l’ajouter. Vous pouvez également utiliser facilement remplacer
"the fox jumped over the fence".replace(/fox/,"<span>fox</span>");
Ou pour plusieurs occurrences (non pertinentes pour la question, mais qui ont été posées dans des commentaires), vous ajoutez simplement global
à l'expression régulière de remplacement.
"the fox jumped over the other fox".replace(/fox/g,"<span>fox</span>");
J'espère que cela aidera les commentateurs intrigués.
pour remplacer le code HTML d'une page Web entière, vous devez vous référer à innerHTML
du corps du document.
document.body.innerHTML
Les solutions proposées ici sont plutôt mauvaises.
&
pour &, <
pour <, >
pour>, ä
pour ä, ö
pour ö ü
pour ü ß
pour ß, etc.Ce que vous devez faire:
Parcourez le document HTML, recherchez tous les nœuds de texte, obtenez le textContent
, obtenez la position du texte surligné avec indexOf
(avec un _ optionnel toLowerCase
s'il doit être insensible à la casse) , ajoutez tout ce qui précède indexof
comme textNode
, ajoutez le texte correspondant avec une plage de surbrillance, puis répétez l'opération pour le reste du nœud de texte (la chaîne de surbrillance peut apparaître plusieurs fois dans la chaîne textContent
) .
Voici le code pour ceci:
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
};
Ensuite, vous pouvez l'utiliser comme ceci:
function TestTextHighlighting(highlightText)
{
var container = document.getElementById("testDocument");
InstantSearch.highlight(container, highlightText);
}
Voici un exemple de document HTML
<!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>
Par ailleurs, si vous recherchez dans une base de données avec LIKE
,
par exemple. WHERE textField LIKE CONCAT('%', @query, '%')
[que vous ne devriez pas faire, vous devriez utiliser fulltext-search ou Lucene], alors vous pouvez échapper à chaque caractère avec\et ajouter une instruction SQL-escape, qui vous permettra de trouver des caractères spéciaux qui sont LIKE-expressions.
par exemple.
WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE '\'
et la valeur de @query n'est pas '%completed%'
mais '%\c\o\m\p\l\e\t\e\d%'
(testé, fonctionne avec SQL-Server et PostgreSQL, ainsi que tous les autres systèmes SGBDR prenant en charge ESCAPE)
Une version révisée de TypeScript:
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
Usage:
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
C'est probablement une mauvaise idée de créer votre propre fonction de surbrillance à partir de zéro, c'est parce que vous rencontrerez certainement des problèmes que d'autres ont déjà résolus. Défis:
innerHTML
, par exemple).Cela semble compliqué? Si vous voulez des fonctionnalités comme ignorer certains éléments de la surbrillance, mapper les signes diacritiques, mapper les synonymes, rechercher dans des iframes, rechercher des mots séparés, etc., cela devient de plus en plus compliqué.
Lorsque vous utilisez un plugin existant, bien implémenté, vous n'avez pas à vous soucier des choses nommées ci-dessus. L'article 10 plugins de surligneur de texte jQuery sur Sitepoint compare les plugins les plus populaires surligneur.
mark.js est un tel plugin écrit en JavaScript pur, mais également disponible en tant que plugin jQuery. Il a été développé pour offrir plus d'opportunités que les autres plugins avec des options pour:
Sinon, vous pouvez voir ce violon .
Exemple d'utilisation :
// Highlight "keyword" in the specified context
$(".context").mark("keyword");
// Highlight the custom regular expression in the specified context
$(".context").markRegExp(/Lorem/gmi);
Il est gratuit et développé en open-source sur GitHub ( référence du projet ).
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);
}
J'ai le même problème, un tas de texte entre par une requête xmlhttp. Ce texte est en format HTML. Je dois souligner chaque occurrence.
str='<img src="brown fox.jpg" title="The brown fox" />'
+'<p>some text containing fox.</p>'
Le problème est que je n'ai pas besoin de surligner du texte dans les balises. Par exemple, je dois mettre en évidence le renard:
Maintenant je peux le remplacer par:
var Word="fox";
Word="(\\b"+
Word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
+ "\\b)";
var r = new RegExp(Word,"igm");
str.replace(r,"<span class='hl'>$1</span>")
Pour répondre à votre question: vous pouvez omettre les options de g dans regexp et seule la première occurrence sera remplacée, mais il s’agit toujours de celui dans la propriété img src et détruit la balise image:
<img src="brown <span class='hl'>fox</span>.jpg" title="The brown <span
class='hl'>fox</span> />
C'est la façon dont j'ai résolu le problème, mais je me demandais s'il y avait une meilleure façon, quelque chose que j'ai manqué dans les expressions régulières:
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>");
});
NOTE: Bien que je sois d’accord avec @Stefan sur beaucoup de choses, j’avais seulement besoin d’un simple surlignage:
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));
}
}
}
Et puis en construisant le résultat réel:
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;
}
}
}
Voici ma solution JavaScript pur regexp:
function highlight(text) {
document.body.innerHTML = document.body.innerHTML.replace(
new RegExp(text + '(?!([^<]+)?<)', 'gi'),
'<b style="background-color:#ff0;font-size:100%">$&</b>'
);
}
Aucune des autres solutions ne correspond vraiment à mes besoins, et bien que la solution de Stefan Steiger ait fonctionné comme prévu, je l'ai trouvée un peu trop verbeuse.
Voici ma tentative:
/**
* 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>
Je recommanderais également d'utiliser quelque chose comme escape-string-regexp si vos mots clés peuvent comporter des caractères spéciaux qui doivent être masqués dans les expressions rationnelles:
const keywordRegex = RegExp(keywords.map(escapeRegexp).join('|')), flags);
Depuis HTML5, vous pouvez utiliser les balises <mark></mark>
pour mettre du texte en surbrillance. Vous pouvez utiliser javascript pour insérer du texte/mot clé entre ces balises. Voici un petit exemple montrant comment marquer et désélectionner du texte.
Je me demandais cela aussi, vous pouvez essayer ce que j'ai appris sur this post.
J'ai utilisé:
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>
vous pouvez aussi l'essayer ici: http://henriquedonati.com/projects/Extension/extension.html
xc
J'ai trouvé le plugin mettre en évidence comme étant la meilleure correspondance; avec cela, vous pouvez mettre en évidence une partie du contenu :
$ ('li'). surligner ('bla');