Using .match() on Content of Textarea - javascript

I did some searching around and found some issues similar to mine, but I was hoping for a resolution that corrects my pre-existing code.
Here's the codepen if you want to see the whole thing: http://codepen.io/JTBennett/pen/ygyZwE
$('#ST_txt_write').keyup(function(){
var childText = $('#ST_cmp_body').text();
var count = (childText.match(/hi/g) || []).length;
$('#ST_KW').html(count);
});
The issue is that I can't get the matching function to work with a textarea so the user can type whatever they want in the box and that will be what the code seeks to match. I tried making a variable that returns the text content of the box (just like the childText var you see there) but that would only match once and be done instead of counting.
Any help in the right direction would be most appreciated. I'm sorry I'm not very good with jQuery, or anything for that matter.

The example you gave in your question has important differences from your codepen. In your question, you have a regex literal that you are passing into .match(), and in your codepen, you are passing a string into .match(). What you need to do is create a new regular expression using new RegExp() and pass it the global flag.
The code would look as follows:
$('#ST_txt_write').keyup(function(){
var childText = $('#ST_cmp_body').val();
var KW = $('#ST_KW_txt').val();
var regex = new RegExp(KW, 'g'); // <--- This creates a regex from the string in KW
var count = (childText.match(regex) || []).length; // <-- Use regex here instead of string
$('#ST_KW').html(count);
});
Here's a working example:
$(function() {
$('#ST_txt_write').keyup(function() {
var childText = $('#ST_cmp_body').val();
var KW = $('#ST_KW_txt').val();
var regex = new RegExp(KW, 'g');
var count = (childText.match(regex) || []).length;
$('#ST_KW').text(count);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="ST_txt_write">
<textarea id="ST_cmp_body" style="height: 200px; width: 300px;"></textarea>
</div>
<div>
Keywords:
<input type="text" id="ST_KW_txt" />
</div>
<div>
# of Keywords Found: <span id="ST_KW"></span>
</div>

Related

How can I remove all HTML elements from a string excluding a special class?

I've a problem. I'm currently looking for a way to remove any HTML elements from a string. But there are two conditions:
The content of the elements should be kept
Special elements with a defined class should not be removed
I've already tried lots of things and looked at plenty of questions/answers on SO, but unfortunately I can't really figure out any of the answers. Unfortunately, this exceeds my abilities by far. But I would like to know how something like this works.
Question/Answers I've tried:
How to strip HTML tags from string in JavaScript?,
Strip HTML from Text JavaScript
So when I have for example a string like this:
You have to pay <div class="keep-this">$200</div> per <span class="date">month</span> for your <span class="vehicle">car</span>
It should looks like this after stripping:
You have to pay <div class="keep-this">$200</div> per month for your car
I've actually tried following things:
jQuery(document).ready(function ($) {
let string = 'You have to pay <div class="keep-this">$200</div> per <span class="date">month</span> for your <span class="vehicle">car</span>';
console.log(string);
function removeHTMLfromString(string) {
let tmp = document.createElement("DIV");
tmp.innerHTML = string;
return tmp.textContent || tmp.innerText || "";
}
console.log(removeHTMLfromString(string));
console.log(string.replace(/<[^>]*>?/gm, ''));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
And I've also tried out a regex tool to see what get's removed, but unfortunately, I'm not making much progress here either:
https://www.regexr.com/50qar
I would love if someone can help me with this task. Thanks a lot!
Update
Maybe there is a way doing it with just a regex? If yes, how can I exclude my elements with a special class when using this regex: /<\/?[^>]+(>|$)/g?
It may be a little big code. But I think it may help you.
let str = 'You have to pay <div class="keep-this">$200</div> per <span class="date">month</span> for your <span class="vehicle">car</span> <div class="keep-this">$500</div> also';
const el = document.createElement("div");
el.innerHTML = str;
// Get all the elements to keep
const keep = el.querySelectorAll(".keep-this");
// Replace the keeping element from the original string
// With special pattern and index so that we can replace
// the pattern with original keeping element
keep.forEach((v, i) => {
const keepStr = v.outerHTML;
str = str.replace(keepStr, `_k${i}_`);
});
// Replace created element's innerHTML by patternised string.
el.innerHTML = str;
// Get the text only
let stringify = el.innerText;
// Replace patterns from the text string by keeping element
keep.forEach((v,i) => {
const keepStr = v.outerHTML;
stringify = stringify.replace(`_k${i}_`, keepStr);
});
console.log(stringify);
Leave me comment if anything misleading.
Update: Regular Expression approach
The same task can be done by using a regular expression. The approach is-
Find all the keepable elements by regex and store them.
Replace all the keepable elements from the input string by an identical pattern
Remove all the HTML tags from the sting.
Replace the identical patterns by keepable elements.
let htmlString = 'You have to pay <div class="keep-this">$200</div> per <span class="date">month</span> for your <span class="vehicle">car</span> Another <div class="keep-this">$400</div> here';
// RegExp for keep elements
const keepRegex = /<([a-z1-6]+)\s+(class=[\'\"](keep-this\s*.*?)[\'\"])[^>]*>.*?<\/\1>/ig;
// RegExp for opening tag
const openRegex = /<([a-z1-6]+)\b[^>]*>/ig;
// RegExp for closing tag
const closeRegex = /<\/[a-z1-6]+>/ig;
// Find all the matches for the keeping elements
const matches = [...htmlString.matchAll(keepRegex)];
// Replace the input string with any pattern so that it could be replaced later
matches.forEach((match, i) => {
htmlString = htmlString.replace(match[0], `_k${i}_`);
});
// Remove opening tags from the input string
htmlString = htmlString.replace(openRegex, '');
// Remove closing tags from the input string
htmlString = htmlString.replace(closeRegex, '');
// Replace the previously created pattern by keeping element
matches.forEach((match, index) => {
htmlString = htmlString.replace(`_k${index}_`, match[0]);
})
console.log(htmlString);
If date and vehicles div and class are coming from another function, you should just get rid of it from there.

javascript regular expression - getting value after colon, without the colon

I have tried the https://www.regex101.com/#javascript tool, as well as a similar stackoverflow question and yet haven't been able to solve/understand this. Hopefully someone here can explain what I am doing wrong. I have created as detailed, step-by-step of an example as I can.
My goal is to be able to parse custom attributes, so for example:
I wrote some jquery code to pull in the attribute and the value, and then wanted to run regex against the result.
Below is the html/js, the output screenshot, and the regular expression screenshot, which says my regex query should match what I am expecting.
Expected result: 'valOne'
Result: ':valOne' <-- why am I getting a ':' character?
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('[customAttr]').each(function(){
var attrValues = $(this).attr('customAttr');
var regEx_attrVal = /[\w:]+?(?=;|$)/g;
var regEx_preColon = /[\w]+?(?=:)/g;
var regEx_postColon = /:(\w*)+?(?=;|\b)/g;
var customAttrVal = attrValues.match(regEx_attrVal);
var customAttrVal_string = customAttrVal.toString();
console.log('customAttrVal:');
console.log(customAttrVal);
console.log('customAttrVal_string: '+customAttrVal_string);
var preColon = customAttrVal_string.match(regEx_preColon);
preColon_string =preColon.toString();
console.log('preColon');
console.log(preColon);
console.log('preColon_string: '+preColon_string);
var postColon = customAttrVal_string.match(regEx_postColon);
postColon_string = postColon.toString();
console.log('postColon');
console.log(postColon);
console.log('postColon_string: '+postColon_string);
console.log('pre: '+preColon_string);
console.log('post: '+postColon_string);
});
});
</script>
</head>
<body>
<div customAttr="val1:valOne">
Test custom attr
</div>
</body>
</html>
When you use String#match() with a regex with a global modifier, all the capture groups (those strings in the regex101.com right-hand bottom 'MATCH INFORMATION' pane are the values captured into Groups with ID 1 and higher) defined in the pattern are lost, and you only get an array of matched values.
You need to remove /g from your regexps and fix them as follows:
var regEx_attrVal = /[\w:]+(?=;|$)/;
var regEx_preColon = /\w+(?=:)/;
var regEx_postColon = /:(\w+)(?=;|\b)/;
Then, when getting the regEx_postColon captured value, use
var postColon = customAttrVal_string.match(regEx_postColon);
var postColon_string = postColon !== null ? postColon[1] : "";
First, check if there is a postColon regex match, then access the captured value with postColon[1].
See the whole updated code:
$(document).ready(function() {
$('[customAttr]').each(function() {
var attrValues = $(this).attr('customAttr');
var regEx_attrVal = /[\w:]+(?=;|$)/;
var regEx_preColon = /\w+(?=:)/;
var regEx_postColon = /:(\w+)(?=;|\b)/;
var customAttrVal = attrValues.match(regEx_attrVal);
var customAttrVal_string = customAttrVal.toString();
console.log('customAttrVal:');
console.log(customAttrVal);
console.log('customAttrVal_string: ' + customAttrVal_string);
var preColon = customAttrVal_string.match(regEx_preColon);
preColon_string = preColon.toString();
console.log('preColon');
console.log(preColon);
console.log('preColon_string: ' + preColon_string);
var postColon = customAttrVal_string.match(regEx_postColon);
var postColon_string = postColon !== null ? postColon[1] : "";
console.log('postColon');
console.log(postColon);
console.log('postColon_string: ' + postColon_string);
console.log('pre: ' + preColon_string);
console.log('post: ' + postColon_string);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div customAttr="val1:valOne">
Test custom attr
</div>
I haven't trudged through all the code, but something you need to understand about regexes is the difference between $0 and $1.
$0 is highlighted in blue. That is the entire part the regex matched.
You want $1. That's where the matches captured by the parenthesis are.
Read more about capture groups here.
var match = myRegexp.exec(myString);
alert(match[1]); // This accesses $1
use data attributes. you can store json strings in them and access them like objects.
HTML
<div id='div' data-custom='{"val1":"valOne","a":"b"}'></div>
jQ
$("#div").data("custom").val1; //valOne
$("#div").data("custom").a; //b
I guess this is the regex pattern that you're looking for:
(?!(.*?):).*
Explanation
(.*?:) Select all type of values and any number of times and a match that contains (:) simbol
(?! :) select inverse values of the first pattern, its kinda negation
( ).* Select all type of values after the evaluations
Also you can do the same with Jquery substring which for me the most simple way to do it, just like this:
How to substring in jquery

How To Remove All Text Before a Specific Value in a String

I have the following string, "blahblahhellothere", that I would like to be shortened to "hellothere" using JavaScript and/or JQuery.
I have tried using the following code:
var titletext123 = "blahblah<br>hellothere"
var injuryt3xt = titletext123.substring(titletext123.indexOf("<br>") +1);
Which only returns "br>hellothere".
Does anyone have any code which will get rid of the and all text before it?
Thank you very much. All of your help is appreciated!
Make it
var titletext123 = "blahblah<br>hellothere" var injuryt3xt = titletext123.substring(titletext123.indexOf("<br>") + 4);
So it is +4. Which accounts for all the characters in <br>.
You can use split() and get second element.
var titletext123 = "blahblah<br>hellothere" ;
var injuryt3xt = titletext123.split("<br>")[1];
alert(injuryt3xt);
Using regular expression:
var text = "blahblah<br>hellothere"
var clipped = str.replace(/.+\<br\>/, ""));
Another option (depending on circumstances) might be:
var injuryt3xt = titletext123.split("<br>")[1];
Which would split the string on <br> and return an array with the left-over parts ... the second of which is referred to with the [1]

Guide on word occurrence in a textarea

I have a Textarea box, a textbox and a button. I would like on clicking the button, for the word in the textbox to be checked against words in the textarea and count number of occurrence.
I have tried last 2 days to write a click function to do this but not getting anywhere since not sure what codes or logic follows next. Only managed to read the contents in the textarea but not sure how to get the word in the textbox and search against sentence in textarea.
Please I am a newbie in JQuery so not asking for anyone to write the code but more of a guide if possible. If this question isn't permitted here, I am more than happy to delete it. Thanks
Use string.match() along with processing to ensure the first string is not empty and that there actually is a match. Did the following in jQuery since you seemed interested in using it.
var textVal = $('#textbox').val();
var textArea = $('#textarea').val();
var matching = new RegExp('\\b' + textVal + '\\b','g');
var count = textArea.match(matching);
var result = 0;
if (count !== null) {
result = count.length;
}
http://jsfiddle.net/promiseofcake/t8Lg9/3/
You are looking for string occurrences, so take a look at this thread.
You could do this using match(), as suggested in the comments:
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "ig"));
// m.length contains number of matches
But that will also match partial words, like 'fox' in 'foxy'. So another method is to split the input into words and walk over them one by one:
var count = 0;
var words = searchText.split(' ');
for (x in words) {
if (words[x].toLowerCase() == wordMatch) {
count++;
}
}
Take a look at this full example: http://jsfiddle.net/z7vzb/
<input type="text"/>
<textarea>...</textarea>
<button>Get</button>
<div></div>
<script>
$("button").click(function(){
count=$("textarea").text().split($("input[type=text]").val()).length-1;
$("div").html(count);
})
</script>

RegExp to match words wrapped in braces

In javascript, I've got a block of HTML like this:
<h2>{title}</h2>
<p>{content}</p>
And I'm trying use regex "match" to spit out an array of all the {item}'s. So my output should look like:
['title', 'url', 'content']
I've gotten as far as:
var pattern = new RegExp("\{[a-zA-Z]+\}+");
var match = pattern.exec("{Sample} bob {text}");
But it's only returning the first tag.
This is just beyond my regex skills. Can anyone help?
Cheers!
You need to create a pattern with the global flag:
var pattern = new RegExp("\{[a-zA-Z]+\}", "g");
or:
var pattern = /\{[a-zA-Z]+\}/g;
Then you can call the match() method on your string to get a list of matches:
var matches = "{Sample} bob {text}".match(pattern);
I think you want:
var pattern = new RegExp("\{[a-zA-Z]+\}+", "g");
The second option is a flag telling it to search the entire string and return all matches.
See: http://www.evolt.org/article/Regular_Expressions_in_JavaScript/17/36435/ for more details.
Have you tried this yet?
<script>
var text = '<h2>{title}</h2>\n<p>{content}</p>';
var regex = /\{[a-z]+\}/ig;
var result = text.match(regex);
for (var i = 0; i < result.length; i++) {
console.debug(i + ". " + result[i]);
}
/*
gives:
0. {title}
1. {test}
2. {url}
3. {content}
*/
</script>
Much as I like to roll my own RegExp (and you really just need the global flag), have you looked at prototype templates, Trimpath JST or anything like that?
Because possibly rolling your own won't be as efficient for reuse as the above examples. EG:
String.prototype.template = function (obj) {
return this.replace(/{([^{}]+)}/g,
function (full, word) {
return((typeof obj[word]==='string'||typeof obj[word]==='number')?obj[word]:full);
}
);
};
"The {adj1} {adj2} {noun}.".template({adj1: 'lazy',adj2: 'brown', noun: 'dog'})
==> "The lazy brown dog."
This runs your regex each time, while I believe the prototype templates basically does it once.
I got off path by using exec for testing.

Categories

Resources