2009-12-29 15 views
6

Chcę funkcji, która znajdzie ciągi znaków w tablicy DOM i podkreślę je.javascript: znajdź ciągi znaków w dom i podkreśl go.

np.

keywords[0] = 'linux'; 
keywords[1] = 'suse pro'; 

<body> 
    im a huge fan of <em>linux</em> and at the moment im using <em>suse pro</em> and finds it amazing. 
</body> 

jaki sposób mogę to zrobić w najprostszy sposób. z góry dzięki

EDYCJA: znalazłem bardzo prosty sposób na osiągnięcie tego: jquery highlight plugin! Twoje zdrowie!

+0

rodzaju duplikat http://stackoverflow.com/questions/1972409 (od tej samej osoby) oprócz tego, że pytanie dotyczy kwestii, jak to zrobić w PHP, mając na uwadze, że ten pyta o to, jak to zrobić w JavaScript. – MatrixFrog

+3

, ale to nie jest dupe. jego 2 różne języki :) – ajsie

Odpowiedz

7

Musiałem to zrobić kilka miesięcy temu Początkowo ktoś użył manipulacji ciągiem innerHTML, jak sugerują to inni tutaj, ale ta droga prowadzi do szaleństwa.Trudne przypadki narożne są: Co jeśli słowo kluczowe jest zaznaczone jest elementem nazwa klasy lub identyfikator. Nie chcemy też kojarzyć żadnego wbudowanego javascripta i przypadkowo powodować nieprawidłowe oznaczenia. style CSS. W końcu kończysz pisanie parsera tekstowego dla HTML4.0 + ECMAscript + css, który nawet w ograniczonym przypadku jest dużo pracy - pisze twoja przeglądarka - IN JAVASCRIPT!

Ale mamy już parser HTML + JS + CSS w przeglądarce, który generuje dla nas ładne drzewo DOM. Więc postanowiłem to wykorzystać. To jest to, co wymyśliłem w końcu:

keywords = ['hello world','goodbye cruel world']; 
function replaceKeywords (domNode) { 
    if (domNode.nodeType === Node.ELEMENT_NODE) { // We only want to scan html elements 
     var children = domNode.childNodes; 
     for (var i=0;i<children.length;i++) { 
      var child = children[i]; 

      // Filter out unwanted nodes to speed up processing. 
      // For example, you can ignore 'SCRIPT' nodes etc. 
      if (child.nodeName != 'EM') { 
       replaceKeywords(child); // Recurse! 
      } 
     } 
    } 
    else if (domNode.nodeType === Node.TEXT_NODE) { // Process text nodes 
     var text = domNode.nodeValue; 

     // This is another place where it might be prudent to add filters 

     for (var i=0;i<keywords.length;i++) { 
      var match = text.indexOf(keywords[i]); // you may use search instead 
      if (match != -1) { 
       // create the EM node: 
       var em = document.createElement('EM'); 

       // split text into 3 parts: before, mid and after 
       var mid = domNode.splitText(match); 
       mid.splitText(keywords[i].length); 

       // then assign mid part to EM 
       mid.parentNode.insertBefore(em,mid); 
       mid.parentNode.removeChild(mid); 
       em.appendChild(mid); 
      } 
     } 
    } 
} 

Dopóki jesteś ostrożny o odfiltrowanie rzeczy, których nie chcą przetwarzać (na przykład puste węzły tekstowe zawierające tylko białe znaki - istnieją wiele z nich, zaufajcie mi) jest to bardzo szybkie.

Dodatkowe filtrowanie nie zaimplementowane dla przejrzystości algorytmicznej - pozostawione jako ćwiczenie dla czytnika.

+0

co powinienem zamienić domNode na? Mam tekst w div z identyfikatorem. – ajsie

+0

@unknown Możesz wywołać to jako 'replaceKeywords (document.getElementById (" someid "))'. @slebetman Możesz chcieć zastąpić stałe '1' i' 3' 'Node.ELEMENT_NODE' i' Node.TEXT_NODE' dla większej przejrzystości. –

+0

@Brian zrobi. Również do przetworzenia całego dokumentu można go nazwać 'replaceKeywords (document.body)' filtr, który ignoruje 'EM', uniemożliwi przetwarzanie tekstu już przetworzonego. – slebetman