The below code is part of a javascript function that I am using to highlight keywords:
for (var i = 0; i < keywords.length; i++)
{
var a = new RegExp(keywords[i], "igm");
container.innerHTML = container.innerHTML.replace(a, "<span style='background:#FF0;'>" + keywords[i] + "</span>");
}
It does in fact highlight the words in my search results while allowing the user to click a result. The problem comes when the user clicks a result and is transferred to the page containing more details. Smack in the middle of the URL variables is the 'span' tag.
details.aspx?id=2<span style='background:#FF0> /<span>&name=..
This in turn prevents my details page from being properly populated. If I comment out the problem line and use the below code the variables pass smoothly, but the keywords aren't highlighted:
container.innerHTML = container.innerHTML.replace(a keywords[i] );
My question is how do I remove the span tag from my URL so that my Variables are passed smoothly and the keywords remain highlighted?
because you are doing a text search on a string and your code is matching on the attributes inside of tags. You can not do a simple find and replace and you should not use regular expressions to match tags.
Related
I'm making an online text editor for a website I'm building, and I use custom tags for the markup.
To make it easier to read, the markup is highlighted by blue, which I do buy using the following function:
var imgOccurences = (informationText.match(/\[img/gi)).length;
for(var i = 0; i < imgOccurences; i++){
var imgLocation = informationText.indexOf('[img');
var endImgLocation = informationText.indexOf(']', imgLocation+1);
if(imgLocation != -1 && endImgLocation != -1){
var informationTextTemp1 = informationText.slice(0, imgLocation);
var informationTextTemp2 = informationText.slice(endImgLocation+1, -1);
var informationTextTemp3 = informationText.slice(imgLocation, endImgLocation+1);
informationTextTemp3 = "<span class='highlightWord'>"+informationTextTemp3+"</span>";
informationText = informationTextTemp1 + informationTextTemp3 + informationTextTemp2;
}
}
However the problem I face is that, when normalizing the text to HTML, I cannot use regex expressions, which I was previously using with the other tags, on the [img] tag, due to the fact that I wanted to highlight the image tag, and all of its contents, which includes a URL.
So I decided to count up all the occurrences of just the '[img' part of the [img] tag and then look for the next occurrence of ']', then slice it out of the normal text, then highlight it using a span, and then add it back to the normal text, while I put it in a for loop.
However only the first occurrence of the [img] tag is highlighted, and I am unsure as to how I should deal with this. Any help would be appreciated.
Basically I need to get everything which looks like: [img src='www.example.com/image.png']and make it look like:<span class='highlightWord'>[img src='example.com/image.png']</span> and then put it into the .innerHTML of the div called textHighlights.
Expected result:
The result I got:
You can do it much simpler since the .replace method accepts a regular expression as a parameter for the matching string.
informationText = informationText.replace(/(\[img.+?\])/gi, '<span class="highlightWord">$1</span>');
The above will replace all matches directly (by wrapping them in the span you want)
I'm designing a rudimentary spell checker of sorts. Suppose I have a div with the following content:
<div>This is some text with xyz and other text</div>
My spell checker correctly identifies the div (returning a jQuery object entitled current_object) and an index for the word (in the case of the example, 5 (due to starting at zero)).
What I need to do now, is surround this word with a span e.g.
<span class="spelling-error">xyz</span>
Leaving me with the final structure like this:
<div>
This is some text with
<span class="spelling-error">xyz</span>
and other text
</div>
However, I need to do this without altering the existing user selection / moving the caret / invoking methods that do so e.g.
window.getSelection().getRangeAt(0).cloneRange().surroundContents();
In other words, if the user is working on the 4th div in the contenteditable document, my code would identify issues in the other divs (1st - 3rd) while not removing focus from the 4th div.
Many thanks!
You've tagged this post as jQuery but I don't think it's particularly necessary to use it. I've written you an example.
https://jsfiddle.net/so0jrj2b/2/
// Redefine the innerHTML for our spellcheck target
spellcheck.innerHTML = (function(text)
{
// We're using an IIFE here to keep namespaces tidy.
// words is each word in the sentence split apart by text
var words = text.split(" ");
// newWords is our array of words after spellchecking.
var newWords = new Array;
// Loop through the sentences.
for (var i = 0; i < words.length; ++i)
{
// Pull the word from our array.
var word = words[i];
if (i === 5) // spellcheck logic here.
{
// Push this content to the array.
newWords.push("<span class=\"mistake\">" + word + "</span>");
}
else
{
// Push the word back to the array.
newWords.push(word);
}
}
// Return the rejoined text block.
return newWords.join(" ");
})(spellcheck.innerHTML);
Worth noting my usage of an IIFE her can be easily reproduced by moving that logic to its own function declaration to make better use of it.
Be aware you also need to account for punctuation in your spellchecking instances.
I'm retrieving tweets from Twitter with the Twitter API and displaying them in my own client.
However, I'm having some difficulty properly highlighting the right search terms. I want to an effect like the following:
The way I'm trying to do this in JS is with a function called highlightSearchTerms(), which takes the text of the tweet and an array of keywords to bold as arguments. It returns the text of the fixed tweet. I'm bolding keywords by wrapping them in a that has the class .search-term.
I'm having a lot of problems, which include:
Running a simple replace doesn't preserve case
There is a lot of conflict with the keyword being in href tags
If I try to do a for loop with a replace, I don't know how to only modify search terms that aren't in an href, and that I haven't already wrapped with the span above
An example tweet I want to be able to handle for:
Input:
This is a keyword. This is a <a href="http://search.twitter.com/q=%23keyword">
#keyword</a> with a hashtag. This is a link with kEyWoRd:
http://thiskeyword.com.
Expected Output:
This is a
<span class="search-term">keyword</span>
. This is a <a href="http://search.twitter.com/q=%23keyword"> #
<span class="search-term">keyword</span>
</a> with a hashtag. This is a link with
<span class="search-term">kEyWoRd</span>
:<a href="http://thiskeyword.com">http://this
<span class="search-term>keyword.com</span>
</a>.
I've tried many things, but unfortunately I can't quite find out the right way to tackle the problem. Any advice at all would be greatly appreciated.
Here is my code that works for some cases but ultimately doesn't do what I want. It fails to handle for when the keyword is in the later half of the link (e.g. http://twitter.com/this_keyword). Sometimes it strangely also highlights 2 characters before a keyword as well. I doubt the best solution would resemble my code too much.
function _highlightSearchTerms(text, keywords){
for (var i=0;i<keywords.length;i++) {
// create regex to find all instances of the keyword, catch the links that potentially come before so we can filter them out in the next step
var searchString = new RegExp("[http://twitter.com/||q=%23]*"+keywords[i], "ig");
// create an array of all the matched keyword terms in the tweet, we can't simply run a replace all as we need them to retain their initial case
var keywordOccurencesInitial = text.match(searchString);
// create an array of the keyword occurences we want to actually use, I'm sure there's a better way to create this array but rather than try to optimize, I just worked with code I know should work because my problem isn't centered around this block
var keywordOccurences = [];
if (keywordOccurencesInitial != null) {
for(var i3=0;i3<keywordOccurencesInitial.length;i3++){
if (keywordOccurencesInitial[i3].indexOf("http://twitter.com/") > -1 || keywordOccurencesInitial[i3].indexOf("q=%23") > -1)
continue;
else
keywordOccurences.push(keywordOccurencesInitial[i3]);
}
}
// replace our matches with search term
// the regex should ensure to NOT catch terms we've already wrapped in the span
// i took the negative lookbehind workaround from http://stackoverflow.com/a/642746/1610101
if (keywordOccurences != null) {
for(var i2=0;i2<keywordOccurences.length;i2++){
var searchString2 = new RegExp("(q=%23||http://twitter.com/||<span class='search-term'>)?"+keywordOccurences[i2].trim(), "g"); // don't replace what we've alrdy replaced
text = text.replace(searchString2,
function($0,$1){
return $1?$0:"<span class='search-term'>"+keywordOccurences[i2].trim()+"</span>";
});
}
}
return text;
}
Here's something you can probably work with:
var getv = document.getElementById('tekt').value;
var keywords = "keyword,big elephant"; // comma delimited keyword list
var rekeywords = "(" + keywords.replace(/\, ?/ig,"|") + ")"; // wraps keywords in ( and ), and changes , to a pipe (character for regex alternation)
var keyrex = new RegExp("(#?\\b" + rekeywords + "\\b)(?=[^>]*?<[^>]*>|(?![^>]*>))","igm")
alert(keyrex);
document.getElementById('tekt').value = document.getElementById('tekt').value.replace(keyrex,"<span class=\"search-term\">$1</span>");
And here is a variation that attempts to deal with word forms. If the word ends with ed,es,s,ing,etc, it chops it off and also, while looking for word-boundaries at the end of the word, it also looks for words ending in common suffixes. It's not perfect, for instance the past tense of ride is rode. Accounting for that with Regex is nigh-impossible without opening yourself up to tons of false-positives.
var getv = document.getElementById('tekt').value;
var keywords = "keywords,big elephant";
var rekeywords = "(" + keywords.replace(/(es|ing|ed|d|s|e)?\b(\s*,\s*|$)/ig,"(es|ing|ed|d|s|e)?$2").replace(/,/g,"|") + ")";
var keyrex = new RegExp("(#?\\b" + rekeywords + "\\b)(?=[^>]*?<[^>]*>|(?![^>]*>))","igm")
console.log(keyrex);
document.getElementById('tekt').value = document.getElementById('tekt').value.replace(keyrex,"<span class=\"search-term\">$1</span>");
Edit
This is just about perfect. Do you know how to slightly modify it so the keyword in thiskeyword.com would also be highlighted?
Change this line
var keyrex = new RegExp("(#?\\b" + rekeywords + "\\b)(?=[^>]*?<[^>]*>|(?![^>]*>))","igm")
to (All I did was remove both \\b's):
var keyrex = new RegExp("(#?" + rekeywords + ")(?=[^>]*?<[^>]*>|(?![^>]*>))","igm")
But be warned, you'll have problems like smiles ending up as smiles (if a user searches for mile), and there's nothing regex can do about that. Regex's definition of a word is alphanumeric characters, it has no dictionary to check.
In my javascript code,
I have a variable which have a string. String contains ' or quote in it. Example
var name= "hi's";
I am creating a link dynamically in a code. where it is written as a string i.e a variable content will be used dynamically to create a link on html page.
content= '<a onclick="javascript:fun(\'' + name + '\');">'
Here it is giving problem that quote in variable name completes the string in content. and hence rest portion of content is not recognised..
similar problem arises if var name = 'hi"s';
i.e. if double quote is present in it.
plz help
This is how you would create an anchor properly and completely avoid the need to escape anything.
var name = "Hi's",
anchor = document.createElement('a');
// should have an href
// links will be displayed differently by some browsers without it
anchor.href = '#';
// using onclick for pragmatic reasons
anchor.onclick = function() {
fun(name);
return false;
}
anchor.innerHTML = 'hello world';
// later
mydiv.appendChild(anchor);
Btw, the onclick attribute shouldn't start with "javascript:" at all; that's already implied.
Update
If you're still interested in the inline version, variables need two steps of encoding:
The first is to serialize the variable properly; I would use JSON.stringify() for that
The second is HTML escaping; the simplest form is simply to replace double quotes with their proper encoded values.
For example:
var content = '<a href="#" onclick="fun(' +
JSON.serialize(name).replace(/"/g, '"') + ');">hello</a>';
I am working on a functionality which will convert matching tags or keywords into links inside particular DIV tag.
Background: I store article body & keywords related to articles in database & while display article in a web page i pass keywords as and array to jQuery function which then search's through the text inside <div id ="article-detail-desc" > ...</div> and converts each matching element into link.
My code works fine but it has flows.
It doen't search for words it search's for any match even if it is part of a word or HTML element which breaks my HTML code.
how can this function be modified so that it also search for matching words
function HighlightKeywords(keywords)
{
var el = $("#article-detail-desc");
var language = "en-US";
var pid = 100;
var issueID = 10;
$(keywords).each(function()
{
var pattern = new RegExp("("+this+")", ["gi"]);
var rs = "<a class='ad-keyword-selected' href='en/search.aspx?Language="+language+"&PageId="+pid+"&issue="+issueID+"&search=$1' title='Seach website for: $1'><span style='color:#990044; tex-decoration:none;'>$1</span></a>";
el.html(el.html().replace(pattern, rs));
});
}
HighlightKeywords(["Amazon","Google","Starbucks","UK","US","tax havens","Singapore","Hong Kong","Dubai","New Jersey"]);
Link on fiddle http://jsfiddle.net/Dgysc/25/
I think the easiest way would be to use word boundaries. So you'd have that:
var pattern = new RegExp("(\\b"+this+"\\b)", ["gi"]);
Edit:
Quick hack to be sure it's not matching the US inside the html elements:
var pattern = new RegExp("(\\b"+this+"\\b)(?![^<]*?>)", ["gi"]);
SInce we are using direct word matching, adding space before and after the keywords may help you,
var pattern = new RegExp("( "+this+" )", ["gi"]);
http://jsfiddle.net/Dgysc/28/