0

My problem is bit complex, I will try my best to explain it.

What I am trying to do?
I want to provide users with a script that they can add to their webpage/blog which will highlight cretain text on their web pages and put a menu/box their which displays on hover. Something like kontera.

To do this, I am doing the following:
1. Parse the HTML of the page where the script is loaded by the following method:
Regexp to search/replace only text, not in HTML attribute
(see the first answer)
2. If its a text node than check the value of the text node for any keywords present in it. (I have around 1000 keywords) and if a keyword is found, replace it with highlighted text and the needed things.

When I apply this to my blog on blogger.com is hangs the browser as the parser function call itself recursively.
I tried to confirm this by limiting my keywords to only 5 from 100's.
Than to solve it I limited that if the nodes are of type DIV or P or BODY than only call the function recursively, still it hangs.
When I remove DIV and leave only P and BODY, than it works.
Can you help me? Thanks in advance! :)

2 Answers 2

0

I'm not convinced you need a recursive function for this. Is there any reason something like this wouldn't work?:

var searchTerms = [ ... your list of words ... ];
for (var i = 0; i < searchTerms.length; i++) {
    var regex = new RegExp(">([^<]*)?("+searchTerms[i]+")([^>]*)?<","ig");
    var tempinnerHTML = element.innerHTML;
    element.innerHTML = tempinnerHTML.replace(regex,'>$1<span style="background-color:#DDF">$2</span>$3<');
}
Sign up to request clarification or add additional context in comments.

2 Comments

In the link that I have mentioned in the question, there is a comment by Chad. Can you confirm that it is the best way of doing it? at least safe way of doing it?
I can't guarantee that this is the best or even a safe way to do this because HTML is not a subset of XML. It depends on your expected input. However, I have been using a similar script myself for some time.
0

Maybe you can try a different way to wrap Keyword terms within the markup. I use this code for searching within a document (created a Search Bookmarklet for iPad so I could search within MobileSafari).

Maybe you could repurpose it for you needs if its effective:

var SearchFor = {
    run: function(defaultText){
      if (!defaultText) {
        defaultText = "";
      }
      var searchText = prompt("Search for:", defaultText);
      if (!searchText)  {
        return false;
      }
      return this.highlightKeyword(searchText);
    },

    highlightKeyword: function(searchText) {

      var searchArray = [searchText];

      if (!document.body || typeof(document.body.innerHTML) == "undefined") {
        return false;
      }

      var bodyText = document.body.innerHTML;
      for (var i = 0; i < searchArray.length; i++) {
        bodyText = this.highlight(bodyText, searchArray[i]);
      }

      document.body.innerHTML = bodyText;
      return true;
    },

    highlight: function(bodyText, searchTerm) {

     var highlightStartTag = "<span style='color:#CCCCCC; background-color:#FAF9DC;'>";
     var highlightEndTag   = "</span>";

      var newText = "";
      var i = -1;
      var lcSearchTerm = searchTerm.toLowerCase();
      var lcBodyText   = bodyText.toLowerCase();

      while (bodyText.length > 0) {
        i = lcBodyText.indexOf(lcSearchTerm, i+1);
        if (i < 0) {
          newText += bodyText;
          bodyText = "";
        } else {
          // skip anything inside an HTML tag
          if (bodyText.lastIndexOf(">", i) >= bodyText.lastIndexOf("<", i)) {
            // skip anything inside a <script> block
            if (lcBodyText.lastIndexOf("/script>", i) >= lcBodyText.lastIndexOf("<script", i)) {
              newText += bodyText.substring(0, i) + highlightStartTag + bodyText.substr(i, searchTerm.length) + highlightEndTag;
              bodyText = bodyText.substr(i + searchTerm.length);
              lcBodyText = bodyText.toLowerCase();
              i = -1;
            }
          }
        }
      }
      return newText;
    }
};

SearchFor.run('KeywordExample');

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.