Search that highlights text is having problems with special characters - javascript

I took this code from a blog which I don't remember the URL. The code is supposed to find in a list with many sections the text written by the user in an input field. If there is a match, the text will be highlighted; and if there is no match, the whole section will hide.
I've made a plunker so you can see how it works: Here's the link
This is the JS code:
$(document).ready(function() {
var $container = $('#global_div');
if (!$container.length) return true;
var $input = $('#searcher'),
$notfound = $('.not-found'),
$items = $container.find('.row'),
$item = $(),
itemsIndexed = [];
$items.each(function() {
itemsIndexed.push($(this).text().replace(/\s{2,}/g, ' ').toLowerCase());
});
$input.on('keyup', function(e) {
$items.each(function() {
$item = $(this);
$item.html($item.html().replace(/<span class="highlight">([^<]+)<\/span>/gi, '$1'));
});
var searchVal = $.trim($input.val()).toLowerCase();
if (searchVal.length) {
for (var i in itemsIndexed) {
$item = $items.eq(i);
if (itemsIndexed[i].indexOf(searchVal) != -1)
$item.removeClass('is-hidden').html($item.html().replace(new RegExp(searchVal + '(?!([^<]+)?>)', 'gi'), '<span class="highlight">$&</span>'));
else
$item.addClass('is-hidden');
}
} else $items.removeClass('is-hidden');
$notfound.toggleClass('is-visible', $items.not('.is-hidden').length == 0);
});
});
So far so good, but the problem is when there are certain characters in the html text or when writing some special characters in the input field. Please open the plunker so you can do the tests I'm about to tell you:
When writing down the letters "a", "s" or "n", you can see how it shows the &amp ; and &nbsp ; of the html. Also when writing down "&", and the whole thing breaks when writing a "." (point).
As I couldn't fix this, I added this code to avoid people from writing special characters in the input (this code isn't in the plunker, so you can test the errors):
$("#searcher").keypress(function(event) {
var character = String.fromCharCode(event.keyCode);
return isValid(character);
});
function isValid(str) {
return !/[~`!##$%\^&*()+=\-\[\]\\';/{}|\\":.<>\?]/g.test(str);
}
But there is still the problem when there are characters like &amp ; and &nbsp ; in the html and users write in the input field the letter "a", "s" or "n" ..or depending which other weird character be on the html.

Related

Javascript replace() using html entities not working

I've got the following script, which successfully replaces < and > with the code indicated below. The idea here is that a user would put into the text box if they want "Bold me" to appear bolded on their blog.
$('.blogbody').each(function() {
var string = $(this).html();
$(this).html(string.replace('<', '<span class="bold">'));
});
$('.blogbody').each(function() {
var string = $(this).html();
$(this).html(string.replace('>', '</span>'));
});
The problem comes with other html entities. I'm going to simply my example. I want to replace the [ html entity with a paragraph tag, but none of the lines in this script work. I've tried documenting each code that related to the '[' character.
$('.blogbody').each(function() {
var string = $(this).html();
$(this).html(string.replace('[', '<p>'));
});
$('.blogbody').each(function() {
var string = $(this).html();
$(this).html(string.replace('&lbrack;', '<p>'));
});
$('.blogbody').each(function() {
var string = $(this).html();
$(this).html(string.replace('&lsqb;', '<p>'));
});
$('.blogbody').each(function() {
var string = $(this).html();
$(this).html(string.replace('&lbrack;', '<p>'));
});
Any thoughts on this would be greatly appreciated! Thanks!
The character '[' is not a character entity so it is not encoded. Just pass it directly to replace:
string.replace('[' , '<p>')

Replace HTML Comment along with string variable

In my project I have some html with comments surrounding text so I can find the text between particular comments and replace that text whilst leaving the comments so I can do it again.
I am having trouble getting the regex to work.
Here is an html line I am working on:
<td class="spaced" style="font-family: Garamond,Palatino,sans-serif;font-size: medium;padding-top: 10px;"><!--firstname-->Harrison<!--firstname--> <!--lastname-->Ford<!--lastname--> <span class="spacer"></span></td>
Now, here is the javascript/jquery that I have at the moment:
var thisval = $(this).val(); //gets replacement text from a text box
var thistoken = "firstname";
currentTemplate = $("#gentextCodeArea").text(); //fetch the text
var tokenstring = "<!--" + thistoken + "-->"
var pattern = new RegExp(tokenstring + '\\w+' + tokenstring,'i');
currentTemplate.replace(pattern, tokenstring + thisval + tokenstring);
$("#gentextCodeArea").text(currentTemplate); //put the new text back
I think I'm pretty close, but I don't have the regex right yet.
The regex ought to replace the firstname with whatever is entered in the textbox for $thisval (method is attached to keyup procedure on textbox).
Using plain span tags instead of comments would make things easier, but either way, I would suggest not using regular expressions for this. There can be border cases that may lead to undesired results.
If you stick with comment tags, I would iterate over the child nodes and then make the replacement, like so:
$("#fname").on("input", function () {
var thisval = $(this).val(); //gets replacement text from a text box
var thistoken = "firstname";
var between = false;
$("#gentextCodeArea").contents().each(function () {
if (this.nodeType === 8 && this.nodeValue.trim() === thistoken) {
if (between) return false;
between = true;
} else if (between) {
this.nodeValue = thisval;
thisval = '';
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
New first name: <input id="fname">
<div id="gentextCodeArea">
<!--firstname-->Harrison<!--firstname-->
<!--lastname-->Ford<!--lastname-->
<span class="spacer"></span></div>
What went wrong in your code
By using text() you don't get the comment tags. To get those, you need to use html() instead
replace() does not mutate the variable given in the first argument, but returns the modified string. So you need to assign that back to currentTemplate
It would be better to use [^<]* instead of \w+ for matching the first name, as some first names have non-letters in them (hyphen, space, ...), and it may even be empty.
Here is the corrected version, but I insist that regular expressions are not the best solution for such a task:
$("#fname").on("input", function () {
var thisval = $(this).val(); //gets replacement text from a text box
var thistoken = "firstname";
currentTemplate = $("#gentextCodeArea").html(); //fetch the html
var tokenstring = "<!--" + thistoken + "-->"
var pattern = new RegExp(tokenstring + '[^<]*' + tokenstring,'i');
currentTemplate = currentTemplate.replace(pattern, tokenstring + thisval + tokenstring);
$("#gentextCodeArea").html(currentTemplate); //put the new text back
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
New first name: <input id="fname">
<div id="gentextCodeArea">
<!--firstname-->Harrison<!--firstname-->
<!--lastname-->Ford<!--lastname-->
<span class="spacer"></span></div>
here is a function which will generate an appropriate Regular expression:
function templatePattern(key) {
return new RegExp(`<!--${key}-->(.*?)<!--${key}-->`);
}
the (.*?) means "match as little as possible," so it will stop at the first instance of the closing tag.
Example:
'<!--firstname-->Harrison<!--firstname--> <!--lastname-->Ford<!--lastname-->'
.replace(templatePattern('firstname'), 'Bob')
.replace(templatePattern('lastname'), 'Johnson') // "Bob Johnson"
$(function(){
function onKeyUp(event)
{
if(event.which === 38) // if key press was the up key
{
$('.firstname_placeholder').text($(this).val());
}
}
$('#firstname_input').keyup(onKeyUp);
});
input[type=text]{width:200px}
<input id='firstname_input' type='text' placeholder='type in a name then press the up key'/>
<table>
<tr>
<td ><span class='firstname_placeholder'>Harrison</span> <span class='lastname_placeholder'>Ford</span> <span class="spacer"></span></td>
</tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Identifying if code between code tags is JavaScript or HTML

I am trying to match block of code to check if is html or javascript code, i tried doing this but am having problem while when have this html element "<div></div>" or php <? echo '';> inside javascript code it will match it as html element.
Please can someone help me with best way to archive this?
<script>
$(document).ready(function(){
function AssignLang(theLanguage){
var regex = /(<([^>]+)>|<([^>]+)>)/ig;
//var regex = "<(\"[^\"]*\"|'[^']*'|[^'\">])*>";
if(theLanguage.match(regex)){
var lang = 'markup';
}else{
var lang = 'javascript';
}
return lang;
}
$('pre code').each(function () {
var the = $(this).html();
/*I tried here to match from 0 to 50 but is not going to help because if the javascript tag begin with <script> still show as html
var theLanguage = the.replace(/\s/g, '').substring(0,50);
*/
var theLanguage = the.replace(/\s/g, '');
var langType = AssignLang(theLanguage);
$(this).addClass("fullcoded language-"+langType);
alert(theLanguage+"-"+langType);
});
});
</script>
Here am matching code inside pre and code element
<pre><code>
function check() {
var delvar = "<? $_POST["del"]; ?>";
var answer = confirm("Are you sure you want to delete the article?")
if (answer) {
window.location = "adm-site.php?del=" + delvar + "&delete=true";
}
}
</code></pre>
<pre><code>
<select name="del">
<option value="none" SELECTED></option>all articles echo'ed here by php
</select>
</code></pre>
Here is a link to https://jsfiddle.net/ppu9qw3n/
This is the regex I'm using /\w+\s\w+\(\)/i
\w+ matches 1 or more a-z, A-Z, 0-9 and _
\s matches 1 space
\( and \) matches ()
Basically I'm searching for a pattern consisting of function functionName() in the code between code tags. If a match is found then it's JavasScript code or else it's HTML code.
This is how you can implement the JavaScript:
$(document).ready(function(){
var regex = /\w+\s\w+\(\)/i;
$('pre code').each(function () {
var v = $(this).html();
if(regex.test(v)){
alert(v+'-'+'THIS IS JAVASCRIPT CODE')
}
else{
alert(v+'-'+'THIS IS HTML CODE')
}
});
});
Check it here on jsfiddle. It's working.
https://jsfiddle.net/swzaf5r1/

Find alphanumeric characters, text and replace with HTML

I'm trying to find and replace text in an HTML. And adding a bold element around the text.
For example, lets say I have the following text:
<div>This is a test content and I'm trying to write testimonial of an user.</div>
If user searches for "test" in my HTML string, I need to show all text containing search text in bold.
<div>This is a <b>test</b> content and I'm trying to write <b>test</b>imonial of an user.</div>
This is working using the below code:
$.fn.wrapInTag = function(opts) {
var o = $.extend({
words: [],
tag: '<strong>'
}, opts);
return this.each(function() {
var html = $(this).html();
for (var i = 0, len = o.words.length; i < len; i++) {
var re = new RegExp(o.words[i], "gi");
html = html.replace(re, o.tag + '$&' + o.tag.replace('<', '</'));
}
$(this).html(html);
});
$('div').wrapInTag({
tag: 'b',
words: ['test']
});
But the above javascript approach fails if I search something like:
*test or /test
Regex doesn't support here.
There are multiple approaches over net but none of them worked for alphanumeric text.
This is how I would perform the text highlight:
$("#search").keyup(function(){
$("#text").html($("#text").html().replace("<b>", "").replace("</b>", ""));
var reg = new RegExp($(this).val().replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"),"g");
$("#text").html($("#text").text().replace(reg, "<b>"+$("#search").val()+"</b>"));
});
Here is the JSFiddle demo
You need to escape the RegExp input. See How to escape regular expression in javascript?
function escapeRegExp(string){
return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}

Jquery: Copy text from a form to a DIV while checking the last letter

On my HTML form, users can enter their name.
Their name will then appear in a DIV as part of a book title.
The book title uses apostrophe 's (e.g. Amy's Holiday Album).
If the user enters a name which ends in a S, I don't want the apostrophe s to appear.
(e.g. it should be Chris' Holiday Album instead of Chris's Holiday Album).
I also only want this to occur if the form has a class of apostrophe. If this class does not exist, then the name should be copied as is without any apostrophe or 's'.
I know you can use slice() to get the last character of an element, so I thought I could combine this with an if statement. But it doesn't seem to work.
Here is JSFiddle
Here is my HTML:
<div><b class="title"></b> Holiday Album</div>
Here is my Jquery (1.8.3):
$(document).ready(function() {
$('.name').keyup(function() {
var finalname = text($(this).val());
var scheck = finalname.slice(-1);
var finaltitle;
if ($(".apostrophe")[0]) {
if (scheck == 's') {
finaltitle = finalname + "'";
}
else {
finaltitle = finalname + "'s";
}
$('.title').text(finaltitle);
}
else {
$('.title').text(finalname);
}
});
});
text method is not needed on
var finalname = $(this).val();
check fiddle
Use
var finalname = $(this).val();
instead of
var finalname = text($(this).val());
Simplified version
$(document).ready(function() {
//Code fires when user starts typing:
$('.name.apostrophe').keyup(function() {
if (this.value.indexOf("'s") != -1 ) {
$('.title').text(this.value.replace(/'s/g, "'"));
} else {
$('.title').text(this.value)
}
}); /* Capture Personalised Message */
});
This will also replace all occurrences of the 's with ' only.
Hope it helps!.

Categories