Comment mettre en surbrillance le texte à l'aide de javascript

Quelqu'un peut-il m'aider avec une fonction javascript qui peut mettre en surbrillance le texte sur une page Web. Et l'exigence est de – mettre en surbrillance une seule fois, pas comme mettre en évidence toutes les occurrences du texte comme nous le faisons en cas de recherche.

Vous pouvez utiliser l' effet de surbrillance jquery.

Mais si vous êtes intéressé par le code javascript brut, regardez ce que j'ai obtenu. Copiez simplement coller dans un HTML, ouvrez le fichier et cliquez sur "mettre en surbrillance" – cela devrait mettre en surbrillance le mot "renard". En termes de performance, je pense que cela ferait pour un petit texte et une seule répétition (comme vous l'avez indiqué)

<script> function highlight(text) { 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 } } </script> <button onclick="highlight('fox')">Highlight</button> <style> .highlight { background-color:yellow; } </style> <div id="inputText"> The fox went over the fence </div> 

EDITs:

Utilisation de replace

Je vois que cette réponse a gagné de la popularité, je pensais pouvoir y ajouter. Vous pouvez également utiliser facilement remplacer

"the fox jumped over the fence".replace(/fox/,"<span>fox</span>");

Ou pour les occurrences multiples (pas pertinent pour la question, mais a été demandé dans les commentaires), vous ajoutez simplement global sur 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.

Remplacer le HTML sur l'ensemble de la page Web

Pour remplacer le HTML d'une page Web entière, vous devez vous référer à innerHTML du corps du document.

document.body.innerHTML

Les solutions offertes ici sont assez mauvaises.

  1. Vous ne pouvez pas utiliser regex, de cette façon, vous recherchez / mettez en surbrillance dans les balises html.
  2. Vous ne pouvez pas utiliser regex, car cela ne fonctionne pas correctement avec UTF * (n'importe quoi avec des caractères non latins / anglais).
  3. Vous ne pouvez pas simplement faire un innerHTML.replace, car cela ne fonctionne pas lorsque les caractères ont une notation HTML spéciale, par exemple, &auml; Pour ä, &ouml; Pour ö &uuml; Pour ü &szlig; Pour ß, etc.

Qu'as tu besoin de faire:

Faites une boucle dans le document HTML, trouvez tous les nœuds de texte, obtenez le textContent , obtenez la position du texte en indexOf avec indexOf (avec un optionnelLockCase s'il doit être insensible à la casse), ajoutez tout avant indexof tant que textNode , ajoutez le texte correspondant Avec une plage de surbrillance, et répétez pour le reste du nœud de texte (la chaîne de surbrillance peut se produire plusieurs fois dans la chaîne de 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&auml;&ouml;&uuml;&Auml;&Ouml;&Uuml;</span> </div> </body> </html> 

Soit dit en passant, 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 la recherche de texte intégral ou Lucene], vous pouvez échapper à chaque personnage avec \ et ajouter un SQL-escape- Déclaration, que vous trouverez des caractères spéciaux qui sont des expressions LIKE.

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, et tous les autres systèmes RDBMS qui supporte ESCAPE)

Pourquoi utiliser une fonction de mise en surbrillance automatique est une mauvaise idée

La raison pour laquelle c'est probablement une mauvaise idée de commencer à créer votre propre fonction de mise en surbrillance à partir de zéro est que vous rencontrerez certainement des problèmes que d'autres ont déjà résolus. Défis:

  • Vous devriez supprimer des nœuds de texte avec des éléments HTML pour mettre en surbrillance vos correspondances sans détruire les événements DOM et déclencher la régénération DOM à plusieurs reprises (ce qui serait le cas par exemple avec innerHTML )
  • Si vous souhaitez supprimer des éléments en surbrillance, vous devriez supprimer des éléments HTML avec leur contenu et combiner les nœuds de texte divisés pour d'autres recherches. Ceci est nécessaire parce que tous les plugins surlargeurs recherchent dans les nœuds de texte des correspondances et si vos mots-clés seront divisés en plusieurs nœuds de texte, ils ne seront pas trouvés.
  • Vous devriez également créer des tests pour vous assurer que votre plugin fonctionne dans des situations que vous n'avez pas pensées. Et je parle de tests multi-navigateurs!

Cela semble compliqué? Si vous souhaitez que certaines fonctionnalités, comme l'ignorance de certains éléments de la mise en surbrillance, la cartographie des diacritiques, la cartographie des synonymes, la recherche dans les iframes, la recherche de mots séparés, etc., cela devient de plus en plus compliqué.

Utiliser un plugin existant

Lorsque vous utilisez un plugin existant et bien implémenté, vous ne devez pas vous soucier des choses ci-dessus. L'article 10 jQuery Text Highlighter plugins sur Sitepoint compare les plugins populaires de surligneur.

Jetez un oeil à mark.js

Mark.js est un plugin qui est écrit en version JavaScript pure, mais est é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:

  • Rechercher des mots-clés séparément au lieu du terme complet
  • Carte diacritique (Par exemple, si "juste" devrait également correspondre à "justò")
  • Ignorer les correspondances à l'intérieur des éléments personnalisés
  • Utiliser un élément de surbrillance personnalisé
  • Utiliser une classe de mise en surbrillance personnalisée
  • Carte synonymes personnalisés
  • Rechercher aussi à l'intérieur des iframes
  • Recevoir des termes non trouvés

DEMO

Alternativement, 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); 

C'est gratuit et développé open-source sur GitHub ( référence de projet ).

 function stylizeHighlightedString() { //alert(text.focusOffset - text.anchorOffset); var text = window.getSelection(); var start = text.anchorOffset; alert(start); var end = text.focusOffset - text.anchorOffset; alert(end); range = window.getSelection().getRangeAt(0); range1 = window.getSelection().toString(); var selectionContents = range.extractContents(); var span = document.createElement("span"); span.appendChild(selectionContents); span.setAttribute("class", "uiWebviewHighlight"); span.style.backgroundColor = "yellow"; span.style.color = "black"; range.insertNode(span); } 

J'ai le même problème, un tas de texte arrive à travers une requête xmlhttp. Ce texte est formaté html. Je dois souligner toutes les occurrences.

 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 mettre en surbrillance le 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 laisser la g dans les options regexp et seule la première occurrence sera remplacée mais celle-ci est encore celle de la propriété img src et détruit la balise d'image:

 <img src="brown <span class='hl'>fox</span>.jpg" title="The brown <span class='hl'>fox</span> /> 

C'est la façon dont je l'ai résolu, 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>"); }); 

Exemple simple de typeScript

REMARQUE: Bien que je suis d'accord avec @Stefan dans beaucoup de choses, j'ai seulement besoin d'une simple mise en surbrillance:

 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 ensuite, la construction du 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; } } } 

J'ai trouvé le plugin de surbrillance pour être le meilleur match, avec vous, vous pouvez mettre en surbrillance une partie du contenu :

$ ('Li'). Highlight ('bla');

Je me demandais aussi, vous pourriez essayer ce que j'ai appris sur cette publication.

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> 

Voici ma solution regexp pure JavaScript:

 function highlight(text) { document.body.innerHTML = document.body.innerHTML.replace( new RegExp(text + '(?!([^<]+)?<)', 'gi'), '<b style="background-color:#ff0;font-size:100%">$&</b>' ); } 

Depuis HTML5, vous pouvez utiliser les balises <mark></mark> pour mettre en surbrillance le texte. Vous pouvez utiliser javascript pour envelopper un texte / mot-clé entre ces balises. Voici un petit exemple de la façon de marquer et de supprimer le texte.

JSFIDDLE DEMO

Utilisation de la méthode surroundContents () sur le type Range . Son seul argument est un élément qui enveloppera cette gamme.

 function styleSelected() { bg = document.createElement("span"); bg.style.backgroundColor = "yellow"; window.getSelection().getRangeAt(0).surroundContents(bg); }