Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

javascript - Howto exclude jpeg-names from regexp replace?

I'm using a search-function for a documentation site which upon selection of search hit shows page with text highlighted (just as a pdf-reader or netbeans would do).

To achive the highlight i use javascript with:

function searchHighlight(searchTxt) {
  var target = $('#page').html();
  var re = new RegExp(searchTxt, 'gi');
  target = target.replace(
    re,
    '<span class="high">' + searchTxt + '</span>'
  );
  $('#page').html(target);
}

Problem / Question:

Since page incudes images with filenames based on md5, some searches messes up the image src.

Searching on "1000" will distort the

<img src="53451000abababababa---.jpg"

to

<img src="5334<span class="hl">1000</span>abababab--.jpg">

Is it possible to solve this with regexp, somehow excluding anything anjcent to ".jpg"?

Or would it be possible to, before highligting replace the images with placeholders, and after replace revert back to src?

Example:

  • replace all <img *> with {{I-01}}, {{I-02}} etc and keep the real src in a var.
  • Do the replace above.
  • Revert back from {{I-01}} to the <img src=".."/>

DOM-manipulation is of course an option, but I figure this could be done with regexp somehow, however, my regexp skills are lacking badly.

UPDATE This code works for me now:

function searchHighlight(searchTxt) {    
var stack = new Array();
var stackPtr = 0;
var target = $('#page').html();
//pre
target = target.replace(/<img.+?>/gi,function(match) {
  stack[stackPtr] = match;
  return '{{im' + (stackPtr++) + '}}';
});
//replace
var re = new RegExp(searchTxt, 'gi');
target = target.replace(re,'<span class="high">' + searchTxt + '</span>');
//post
stackPtr = 0;
target = target.replace(/{{im.+?}}/gi,function(match) {
    return stack[stackPtr++];
});
$('#page').html(target);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One approach would be to create an array of all possible valid search terms. Set the terms as .textContent of <span> elements within #page parent element.

At searchHighlight function check if searchTxt matches an element within array. If searchTxt matches an element of array, select span element using index of matched array element, toggle "high" .className at matched #page span element, else notify user that searchTxt does not match any valid search terms.

$(function() {
  var words = [];
  var input = $("input[type=text]");
  var button = $("input[type=button][value=Search]");
  var reset = $("input[type=button][value=Reset]");
  var label = $("label");
  var page = $("#page");
  var contents = $("h1, p", page).contents()
    .filter(function() {
      return this.nodeType === 3 && /w+/.test(this.nodeValue)
    }).map(function(i, text) {
      var span = text.nodeValue.split(/s/).filter(Boolean)
        .map(function(word, index) {
          words.push(word);
          return "<span>" + word + "</span> "
        });
      $(text.parentElement).find(text).replaceWith(span);
    })
  var spans = $("span", page);
  button.on("click", function(event) {
    spans.removeClass("high");
    label.html("");
    if (input.val().length && /w+/.test(input.val())) {
      var terms = input.val().match(/w+/g);
      var indexes = $.map(terms, function(term) {
        var search = $.map(words, function(word, index) {
          return word.toLowerCase().indexOf(term.toLowerCase()) > -1 && index
        }).filter(Boolean);
        return search
      });
      if (indexes.length) {
        $.each(indexes, function(_, index) {
          spans.eq(index).addClass("high")
        })
      } else {
        label.html("Search term <em>" + input.val() + "</em> not found.");
      }
    }
  });
  reset.on("click", function(event) {
    spans.removeClass("high");
    input.val("");
    label.html("");
  })
})
.high {
  background-color: #caf;
}
label em {
  font-weight: bold;
  background-color: darkorange;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
<input type="button" value="Search" />
<input type="button" value="Reset" />
<label></label>
<div id="page" style="max-width:500px;border:1px solid #ccc;">
  <h1 style="margin:0px;">test of replace</h1>
  <p>After Luke comes to Dagobah, Yoda initially withholds his true identity. He’s trying to get a sense of who Luke is as a person; Yoda understands that there’s a lot at risk in training Luke to be a Jedi, especially considering what happened with his
    father.
    <img style="float:right;" width="200" src="http://a.dilcdn.com/bl/wp-content/uploads/sites/6/2013/11/04-400x225.jpg">And Yoda is not impressed — Luke is impatient and selfish. With “Adventure. Excitement. A Jedi craves not these things,” the Jedi Master makes clear that Luke must understand the significance and meaning of the journey he thinks he wants to make.
    It’s an important lesson for Luke and for audiences, because when Luke faces Vader at the film’s climax, we see the stakes involved in the life of a Jedi</p>
  <p>Now Yoda-search works, however a search on "sites" will break the image-link. (Yes, I know this implementation isn't perfect but I'm dealing with reality)</p>
</div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...