JQuery / JavaScript plugin pour surligner du texte

Je cherche un plugin jquery pour plusieurs textes en surbrillance dans un élément. J’ai trouvé un plugin très populaire pour cela: http://bartaz.github.com/sandbox.js/jquery.highlight.html avec beaucoup d’autres.

Ils fonctionnent bien, mais dans le cas où je voudrais mettre en surbrillance un texte qui chevauche le texte mis en surbrillance précédemment, cela ne fonctionne pas.

Est-ce que quelqu’un connait un plugin jquery ou javascript qui supporte plusieurs textes surlignés et qui surligne correctement les textes superposés?

Vous pouvez tout faire avec le plugin surligneur que vous avez trouvé si vous ajoutez quelques petites modifications. À titre d’illustration, j’ai posté pour bricoler un exemple de travail que j’ai rapidement rassemblé cet après-midi: http://jsfiddle.net/4bwgA/

Ici, je vais d’abord passer en revue tout ce que le plug-in (le PO fait référence) fait déjà et à la fin, donner la solution aux zones superposées qui se chevauchent.

Le surligneur consiste à mettre une étiquette autour du mot pour lequel vous l’appliquez. Donc si vous avez

Who is the quick brown fox?

et vous avez surligné le mot “marron” avec

  $("p").highlight("brown"); 

vous recevez

  

Who is the quick brown fox?

et une commande supplémentaire

  $("p").highlight("brown fox"); 

ne trouvera rien, car la chaîne n’a plus cette sous-chaîne, car elle a maintenant des balises autour de brun.

Donc, s’il ne s’agit que d’un chevauchement, la solution est simple. Le package offre une fonction de mise en surbrillance que vous pouvez appliquer avant la nouvelle mise en surbrillance

  $("p").unhighlight().highlight("brown fox"); 

et obtenir

  

Who is the quick brown fox?

Maintenant, rien n’excite jusqu’à présent. Mais que se passe-t-il si nous avons sélectionné “marron” en une fois, puis “renard” dans la suivante. Nous obtenons ceci

  

Who is the quick brown fox?

Ensuite, nous voulons rejoindre les zones en surbrillance voisines. Cela peut être fait avec une fonction supplémentaire, qui fait quelque chose comme ceci:

  function mergenode(node) { var parent1 = node.contents(); parent1.each(function (i) { if (i > 0 && this.nodeType !== 1 && //if text node this.data.search(/^\s*$/g) === 0 && //consisting only of hyphens or blanks parent1[i - 1].nodeName === "SPAN" && //bordering to SPAN elements parent1[i + 1].nodeName === "SPAN" && parent1[i - 1].className === "highlight" && //of class highlight parent1[i + 1].className === "highlight") { selected1.push(parent1[i - 1] .textContent.concat(this.data, parent1[i + 1].textContent)); } else if (this.nodeType === 1 && this.nodeName === "SPAN" && parent1[i + 1].nodeName === "SPAN" && this.className === "highlight" && parent1[i + 1].className === "highlight") { selected1.push(this.textContent.concat(parent1[i + 1].textContent)); } }); $(node).unhighlight().highlight(selected1); } 

Cela va fusionner toutes les étendues voisines avec la surbrillance de la classe (ceci est écrit uniquement pour la balise générale de surligneur, mais pourrait facilement être étendu avec deux arguments supplémentaires pour nodeName et className, pour les balises personnalisées). Le résultat ressemblera à ceci

  

Who is the quick brown fox?

Tout va bien jusqu’à présent. Mais que se passe-t-il si nos chaînes de recherche se chevauchent? !!! Premièrement … la meilleure chose à faire avec les chevauchements est de désélectionner l’ancienne sélection avant de rechercher les chaînes qui se chevauchent dans le texte effacé. Pour cela, nous devons garder en mémoire la sélection précédente, qui peut par exemple être sauvegardée dans un tableau (je l’ai appelé selected1 ), auquel une valeur est ajoutée à chaque sélection supplémentaire.

À chaque exécution, la sélection finale (toutes fusionnées) est enregistrée dans le tableau selected1 afin de pouvoir être utilisée pour la fusion et le chevauchement futurs.

Maintenant, comment Highlighter gère-t-il un tableau de chaînes? Il applique la fonction de surbrillance à chacune d’elles dans l’ordre dans lequel elles ont été transmises à la fonction. Ainsi, si deux chaînes se chevauchent complètement, nous pouvons résoudre ce problème en sortingant simplement le tableau de chaînes de sélection et en mettant en évidence les plus longues. Par exemple

  $("p").highlight(["brown fox","brown"]); 

je vais juste souligner

  

Who is the quick brown fox?

Le tableau peut être sortingé par longueur avec quelque chose comme ça

  words = words.sort(function (str1, str2) { return (str1.length < str2.length) ? 1 : 0; }); 

Les points forts complètement nesteds et voisins sont maintenant traités. Maintenant, nous devons nous assurer que nous obtenons les chaînes qui se chevauchent partiellement. Ici, j’ai écrit une fonction qui compare deux chaînes pour qu’elles se chevauchent ... Il existe d’autres moyens de le faire, mais ce que je veux montrer dans cette réponse, c’est surtout la séquence des étapes à suivre pour obtenir la surbrillance vouloir =)

Cette fonction prend deux chaînes, vérifie si elles se chevauchent et, si tel est le cas, les combine et enregistre la nouvelle chaîne combinée dans un tableau, toselect , qui à la fin est ajouté au tableau de words origine. Il y aura peut-être des combinaisons inutiles, mais cela ne fera pas mal - elles ne seront pas visibles à la fin.

  function overlap(a, b) { var l = b.length, m = a.length; for (var j = 1; j < l; j++) { if (a.indexOf(b.substr(l - j)) === 0) { toselect.push(b.concat(a.substr(j))); } else if (a.substr(m - j).indexOf(b.substr(0, j)) === 0) { toselect.push(a.concat(b.substr(j))); } } } 

Nous voulons maintenant appliquer cette fonction à toutes les paires d'éléments possibles dans le tableau de words . Nous pourrions répéter cela avec une boucle, mais je me suis un peu excité et je l'ai fait.

  $.each(arr, function (i) { $.each(arr.slice(i + 1), function (i, v) { overlap(arr[i], v); }); }); 

Il ne nous rest plus qu'à append le nouveau tableau toselect , dans lequel toutes les chaînes superposées possibles ont été concaténées, au tableau des words origine.

Nous avons donc maintenant toutes les pièces dont nous avons besoin et nous pouvons les assembler. Chaque fois que nous souhaitons mettre en évidence une nouvelle chaîne ou un nouveau tableau de chaînes, nous procédons comme suit:

  1. Désactivez tout ce qui est en surbrillance (tout ce qui a été mis en surbrillance sera dans le tableau selected1 ).
  2. Notre nouvelle chaîne ou tableau de chaînes va dans le tableau de words
  3. Ajouter selected1 words selected1
  4. Combinez toutes les paires de chaînes se chevauchant partiellement dans les words et ajoutez les nouvelles chaînes combinées aux words (à l'aide de la fonction overlap et de son enveloppe qui parcourt l'ensemble du tableau - overdiag dans l'exemple du violon)
  5. Triez les words en fonction de la longueur de la chaîne pour que les chaînes les plus longues passent en premier.
  6. Mettez en surbrillance toutes les chaînes de words
  7. Fusionner toutes les chaînes en surbrillance voisines (en utilisant la fonction mergenode )
  8. Le dernier ensemble de chaînes en surbrillance est enregistré dans selected1

J’ai rassemblé tout cela rapidement cet après-midi, ce n’est donc pas une implémentation parfaite de l’idée, mais cela fonctionne =) j’ai ajouté mon code dans le script de surligneur et les ai ajoutés à un exemple simple sur jsfiddle pour que vous puissiez jouer avec http: // jsfiddle .net / 4bwgA / . Il y a des boutons pour que vous puissiez suivre toutes les étapes et voir ce qu'elles font.