web-dev-qa-db-fra.com

Mettez en surbrillance un mot avec jQuery

J'ai essentiellement besoin de mettre en évidence un mot particulier dans un bloc de texte. Par exemple, supposez que je veuille mettre en évidence le mot "dolor" dans ce texte:

<p>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer dolor ullamcorper libero.
    Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>

Comment convertir ce qui précède en quelque chose comme ceci:

<p>
    Lorem ipsum <span class="myClass">dolor</span> sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer <span class="myClass">dolor</span> ullamcorper
    libero. Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>

Est-ce possible avec jQuery?

Edit: Comme Sebastiana fait remarquer , c'est tout à fait possible sans jQuery - mais j'espérais qu'il pourrait y avoir une méthode spéciale de jQuery qui vous permettrait de sélectionner le texte lui-même. J'utilise déjà beaucoup jQuery sur ce site, alors garder tout en place dans jQuery rendrait les choses un peu plus ordonnées.

89
nickf

Essayez highlight: texte JavaScript mettant en évidence le plugin jQuery . ! Avertissement - Le code source disponible sur cette page contient un script d’extraction cryptographique, utilisez le code ci-dessous ou supprimez le script d’extraction du téléchargement sur le site Web. !

/*

highlight v4

Highlights arbitrary terms.

<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>

MIT license.

Johann Burkard
<http://johannburkard.de>
<mailto:[email protected]>

*/

jQuery.fn.highlight = function(pat) {
 function innerHighlight(node, pat) {
  var skip = 0;
  if (node.nodeType == 3) {
   var pos = node.data.toUpperCase().indexOf(pat);
   if (pos >= 0) {
    var spannode = document.createElement('span');
    spannode.className = 'highlight';
    var middlebit = node.splitText(pos);
    var endbit = middlebit.splitText(pat.length);
    var middleclone = middlebit.cloneNode(true);
    spannode.appendChild(middleclone);
    middlebit.parentNode.replaceChild(spannode, middlebit);
    skip = 1;
   }
  }
  else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
   for (var i = 0; i < node.childNodes.length; ++i) {
    i += innerHighlight(node.childNodes[i], pat);
   }
  }
  return skip;
 }
 return this.length && pat && pat.length ? this.each(function() {
  innerHighlight(this, pat.toUpperCase());
 }) : this;
};

jQuery.fn.removeHighlight = function() {
 return this.find("span.highlight").each(function() {
  this.parentNode.firstChild.nodeName;
  with (this.parentNode) {
   replaceChild(this.firstChild, this);
   normalize();
  }
 }).end();
};

Essayez également la version "mise à jour" du script original .

/*
 * jQuery Highlight plugin
 *
 * Based on highlight v3 by Johann Burkard
 * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
 *
 * Code a little bit refactored and cleaned (in my humble opinion).
 * Most important changes:
 *  - has an option to highlight only entire words (wordsOnly - false by default),
 *  - has an option to be case sensitive (caseSensitive - false by default)
 *  - highlight element tag and class names can be specified in options
 *
 * Usage:
 *   // wrap every occurrance of text 'lorem' in content
 *   // with <span class='highlight'> (default options)
 *   $('#content').highlight('lorem');
 *
 *   // search for and highlight more terms at once
 *   // so you can save some time on traversing DOM
 *   $('#content').highlight(['lorem', 'ipsum']);
 *   $('#content').highlight('lorem ipsum');
 *
 *   // search only for entire Word 'lorem'
 *   $('#content').highlight('lorem', { wordsOnly: true });
 *
 *   // don't ignore case during search of term 'lorem'
 *   $('#content').highlight('lorem', { caseSensitive: true });
 *
 *   // wrap every occurrance of term 'ipsum' in content
 *   // with <em class='important'>
 *   $('#content').highlight('ipsum', { element: 'em', className: 'important' });
 *
 *   // remove default highlight
 *   $('#content').unhighlight();
 *
 *   // remove custom highlight
 *   $('#content').unhighlight({ element: 'em', className: 'important' });
 *
 *
 * Copyright (c) 2009 Bartek Szopka
 *
 * Licensed under MIT license.
 *
 */

jQuery.extend({
    highlight: function (node, re, nodeName, className) {
        if (node.nodeType === 3) {
            var match = node.data.match(re);
            if (match) {
                var highlight = document.createElement(nodeName || 'span');
                highlight.className = className || 'highlight';
                var wordNode = node.splitText(match.index);
                wordNode.splitText(match[0].length);
                var wordClone = wordNode.cloneNode(true);
                highlight.appendChild(wordClone);
                wordNode.parentNode.replaceChild(highlight, wordNode);
                return 1; //skip added node in parent
            }
        } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
                !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
                !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
            for (var i = 0; i < node.childNodes.length; i++) {
                i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
            }
        }
        return 0;
    }
});

jQuery.fn.unhighlight = function (options) {
    var settings = { className: 'highlight', element: 'span' };
    jQuery.extend(settings, options);

    return this.find(settings.element + "." + settings.className).each(function () {
        var parent = this.parentNode;
        parent.replaceChild(this.firstChild, this);
        parent.normalize();
    }).end();
};

jQuery.fn.highlight = function (words, options) {
    var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
    jQuery.extend(settings, options);

    if (words.constructor === String) {
        words = [words];
    }
    words = jQuery.grep(words, function(Word, i){
      return Word != '';
    });
    words = jQuery.map(words, function(Word, i) {
      return Word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
    });
    if (words.length == 0) { return this; };

    var flag = settings.caseSensitive ? "" : "i";
    var pattern = "(" + words.join("|") + ")";
    if (settings.wordsOnly) {
        pattern = "\\b" + pattern + "\\b";
    }
    var re = new RegExp(pattern, flag);

    return this.each(function () {
        jQuery.highlight(this, re, settings.element, settings.className);
    });
};
77
mlarsen
function hiliter(Word, element) {
    var rgxp = new RegExp(Word, 'g');
    var repl = '<span class="myClass">' + Word + '</span>';
    element.innerHTML = element.innerHTML.replace(rgxp, repl);
}
hiliter('dolor');
41
Andrew Hedges

Pourquoi utiliser une fonction de surbrillance personnalisée est une mauvaise idée

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:

  • Vous devez supprimer les nœuds de texte contenant des éléments HTML pour mettre en surbrillance vos correspondances sans détruire les événements DOM ni déclencher la régénération DOM encore et encore (ce qui serait le cas avec innerHTML, par exemple).
  • Si vous souhaitez supprimer les éléments en surbrillance, vous devez supprimer les éléments HTML avec leur contenu et également combiner les nœuds de texte fractionnés pour des recherches ultérieures. Cela est nécessaire car chaque plug-in Highlighter recherche des correspondances dans les nœuds de texte et si vos mots-clés sont scindés en plusieurs nœuds de texte, ils ne seront pas trouvés.
  • Vous devrez également créer des tests pour vous assurer que votre plug-in fonctionne dans des situations auxquelles vous n'avez pas pensé. Et je parle de tests multi-navigateurs!

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é.

Utiliser un plugin existant

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 jQuery sur Sitepoint compare les plugins les plus populaires. Cela inclut les plugins de réponses à cette question.

Regardez mark.js

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:

  • rechercher des mots-clés séparément au lieu du terme complet
  • map diacritics (Par exemple, si "justo" doit é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 surbrillance personnalisée
  • mapper des synonymes personnalisés
  • rechercher aussi à l'intérieur des iframes
  • recevoir des termes non trouvés

D&EACUTE;MO

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 ).

27
dude

Voici une variante qui ignore et préserve le cas:

jQuery.fn.highlight = function (str, className) {
    var regex = new RegExp("\\b"+str+"\\b", "gi");

    return this.each(function () {
        this.innerHTML = this.innerHTML.replace(regex, function(matched) {return "<span class=\"" + className + "\">" + matched + "</span>";});
    });
};
11
bjarlestam

JSFiddle

Utilise .each (), .replace (), .html (). Testé avec jQuery 1.11 et 3.2.

Dans l'exemple ci-dessus, lit le «mot-clé» à surligner et ajoute une balise span à la classe «highlight». Le texte "mot clé" est mis en surbrillance pour toutes les classes sélectionnées dans le fichier .each (). 

HTML

<body>
   <label name="lblKeyword" id="lblKeyword" class="highlight">keyword</label>
   <p class="filename">keyword</p>
   <p class="content">keyword</p>
   <p class="system"><i>keyword</i></p>
</body>

JS

$(document).ready(function() {
   var keyWord = $("#lblKeyword").text(); 
   var replaceD = "<span class='highlight'>" + keyWord + "</span>";
   $(".system, .filename, .content").each(function() {
      var text = $(this).text();
      text = text.replace(keyWord, replaceD);
      $(this).html(text);
   });
});

CSS

.highlight {
    background-color: yellow;
}
2
Van Peer

Vous pouvez utiliser mon plugin en surbrillance jQuiteLight , qui peut également fonctionner avec des expressions régulières.

Pour installer avec npm tapez:

npm install jquitelight --save

Pour installer avec bower tapez:

bower install jquitelight 

Utilisation:

// for strings
$(".element").mark("query here");
// for RegExp
$(".element").mark(new RegExp(/query h[a-z]+/));

Utilisation plus avancée ici

2
iamawebgeek

Vous devez obtenir le contenu de la balise p et y remplacer toutes les couleurs par la version en surbrillance.

Vous n'avez même pas besoin d'avoir jQuery pour cela. :-)

2
Sebastian Hoitz

J'ai écrit une fonction très simple qui utilise jQuery pour itérer les éléments enveloppant chaque mot clé avec une classe.

function highlight_words(Word, element) {
    if(Word) {
        var textNodes;
        Word = Word.replace(/\W/g, '');
        var str = Word.split(" ");
        $(str).each(function() {
            var term = this;
            var textNodes = $(element).contents().filter(function() { return this.nodeType === 3 });
            textNodes.each(function() {
              var content = $(this).text();
              var regex = new RegExp(term, "gi");
              content = content.replace(regex, '<span class="highlight">' + term + '</span>');
              $(this).replaceWith(content);
            });
        });
    }
}

Plus d'informations:

http://www.hawkee.com/snippet/9854/

1
Hawkee

J'ai créé un référentiel sur un concept similaire qui modifie les couleurs des textes dont les couleurs sont reconnues par html5 (nous n'avons pas à utiliser les valeurs réelles de #rrggbb et nous pourrions simplement utiliser les noms html5 normalisés. environ 140 d'entre eux)

COLORS.JScolors.js

$( document ).ready(function() {
	
	function hiliter(Word, element) {
		var rgxp = new RegExp("\\b" + Word + "\\b" , 'gi'); // g modifier for global and i for case insensitive 
		var repl = '<span class="myClass">' + Word + '</span>';
		element.innerHTML = element.innerHTML.replace(rgxp, repl);
			
			};

	hiliter('dolor', document.getElementById('dolor'));
});
.myClass{

background-color:red;
}
<!DOCTYPE html>
<html>
	<head>
		<title>highlight</title>
		
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
	
		 <link href="main.css" type="text/css"  rel="stylesheet"/>
		 
	</head>
	<body id='dolor'>
<p >
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer dolor ullamcorper libero.
    Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>
 <script type="text/javascript" src="main.js" charset="utf-8"></script>
	</body>
</html>

0
abe312