Search For Words, Replace With Links
I have an array like this
var words = [
{
word: 'Something',
link: 'http://www.something.com'
},
{
word: 'Something Else',
link: 'http://www.something.com/else'
}
];
I want it to search the page for word and replace it with link. Is th开发者_运维问答ere an efficient way of doing this? It seems it may be CPU hungry.
Sorry should have explained more...
It would search each element with the class .message for instance. Then find all of the words within that class and replace it with link.
There would also be a few hundred within this array
A good strategy is:
1) Build an object whose keys are the phrases to replace and whose values are the links to replace them with.
2) While doing that, construct a regular expression that can match any of the keys, then
3) Use that regex to globally replace.
Rough example:
var replacementDict = {
'foo': 'http://www.foo.com/',
'bar': 'http://www.bar.net/'
};
var theRegex = /\b(foo|bar)\b/g;
theText.replace(theRegex, function(s, theWord) {
return "<a href='" + replacementDict[theWord] + "'>" + theWord + "</a>";
});
Given some content like:
<div class="message">Somethsg1</div>
<div class="message">Something</div>
<div class="message">Ssething</div>
<div class="message">Something Else</div>
<div class="message">Something da</div>
<div class="message">Somethin2g</div>
You can use something like:
//your array
var words = [
{
word: 'Something',
link: 'http://www.something.com'
},
{
word: 'Something Else',
link: 'http://www.something.com/else'
}
];
//iterate the array
$.each(words,
function() {
//find an element with class "message" that contains "word" (from array)
$('.message:contains("' + this.word + '")')
//substitute html with a nice anchor tag
.html('<a href="' + this.link + '">' + this.link + '</a>');
}
);
This solution has one immediate problem though (showed in the example too). If you search for example for Something and you find Something beautiful, the "contains" will be match.
If you want a strict selection, you have to do:
//for each array element
$.each(words,
function() {
//store it ("this" is gonna become the dom element in the next function)
var search = this;
$('.message').each(
function() {
//if it's exactly the same
if ($(this).text() === search.word) {
//do your magic tricks
$(this).html('<a href="' + search.link + '">' + search.link + '</a>');
}
}
);
}
);
It's your choice whether to iterate all array elements first then all the doms, or the other way around. It's also depends on which kind of "words" you are gonna search (See the two example for the "why").
BIG WARNING: if the array contains user-defined content, you have to sanitize it before injiecting it to the elements' html!
It would be possible to do it with something like:
$('*:contains("string to find")');
the problem with this approach is that "*" will return all elements that contain the string, including HTML, BODY, etc... and after that you still need to find the string inside the text node of each element, so it may be easier to just go and check every text node...
I'd suggest you take a look at the highlight plugin that already does something very similar to what you want (instead of linking, it highlights any text on a page), but from the source code it seems pretty easy to change it.
If you want to wrap in 'a' tag un-comment code and comment call above. Try this:
var words = [
{
word: 'Something',
link: 'http://www.something.com'
},
{
word: 'Something Else',
link: 'http://www.something.com/else'
}];
var changeWordsWithLink = function (words) {
if(document.getElementById && document.getElementsByTagName) {
var messages = document.getElementById('message');
if(messages) {
for(i = 0; i < messages.length; i++){
for (j = 0; j < words.length; j++) {
if(words[j].word == messages[i].innerHTML) {
messages[i].innerHTML = words[j].link;
//messages[i].innerHTML = wrapInATag(words[j].link, words[j].word);
}
}
}
}
}
}
var wrapInATag = function(link, word) {
return '<a href="' + link + '">' + word + '</a>';
}
精彩评论