Count Specific Words Using Jquery - javascript

I have the following HTML code:
<ul>
<li>apples <span id="apples-density">1</span></li>
<li>pears <span id="pears-density">0</span></li>
<li>oranges <span id="oranges-density">2</span></li>
</ul>
<textarea>This is where I love to eat apples and oranges</textarea>
<textarea>I also like oranges on Sundays!</textarea>
What I would to achieve is that when ever the textarea is updated (on key up), the density of the 3 specific words is counted and then the value inside the SPAN is updated.
However, the page can contain up to 10 words that will need to be counted and also an unlimited number of TEXTAREA elements. And... the actual 3 words that are being counted are different each time, so the code has to allow for some sort of automation.
I can sort of see how it should work in my head, but not quite how to implement...
perform a jquery .each on the textarea values.
perform a jquery to grab each of the <li> values
so some sort of regex to match the content of the textarea's and count the words.
update the .text of the correct to show the value.

My own suggestion would be:
function wordsUsed(){
// get all the text from all the textarea elements together in one string:
var text = $('textarea').map(function(){
return $(this).val();
}).get().join(' '),
reg;
// iterate over the span elements found in each li element:
$('li > span').each(function(i,el){
// cache the variable (in case you want to use it more than once):
var that = $(el);
// create a RegExp (regular expression) object:
// the '\\b' is a word boundary double-escaped because it's a string;
// we shorten the id of the current element by removing '-frequency'
// (I didn't think 'density' was an appropriate description) to find
// the word we're looking for;
// 'gi' we look through the whole of the string (the 'g') and
// ignore the case of the text (the 'i'):
reg = new RegExp('\\b' + el.id.replace('-frequency','') + '\\b', 'gi');
// we look for the regular-expression ('reg') matches in the string ('text'):
var matched = text.match(reg),
// if matched does not exist (there were no matched words) we set
// the count to 0, otherwise we use the number of matches (length):
matches = !matched ? 0 : matched.length;
// setting the text of the current element:
that.text(matches);
});
}
$('textarea')
// binding the keyup event-handler, using 'on()':
.on('keyup', wordsUsed)
// triggering the keyup event, so the count is accurate on page-load:
.keyup();
JS Fiddle demo.
The above works on the (pedantically) modified HTML:
<ul>
<li>apples <span id="apples-frequency"></span>
</li>
<li>pears <span id="pears-frequency"></span>
</li>
<li>oranges <span id="oranges-frequency"></span>
</li>
</ul>
<textarea>actual text removed for brevity</textarea>
<textarea>actual text removed for brevity</textarea>
References:
'Plain' JavaScript:
JavaScript regular expressions.
RegExp().
String.prototype.match().
String.prototype.replace().
jQuery:
each().
get().
map().
on().
text().

// Get all the textarea values
var all_text = '';
$('textarea').each(function() {
all_text += ' ' + $(this).text();
}
// Process each of the LIs
$('li span').each(function() {
var word = this.id.split('-')[0]; // Get the search word
// Convert it to a regular expression. Use 'g' option to match all occurrences.
var regex = new RegEx('\b'+word+'\b', 'g');
var count = all_text.match(regex).length;
$(this).text(count);
}

Related

Add HTML Around Regex Matches From Element Inner Text

I have a span element with a piece of inner text. I need to target specific pieces of that text through regex and turn my matches into span elements with a class attribute class="hightlight-yellow" and a custom attribute called my-custom-attribute="hello".
Here is my input and expected output...
Input
<span class="message"> This is some text $HIGH:LOW $LOW:HIGH </span>
Output
<span> This is some text <span class="highlight-yellow" my-custom-attribute="hello">$HIGH:LOW</span> <span class="highlight-yellow" my-custom-attribute="hello">$LOW:HIGH</span></span>
How can I do the replace? Here is my current code colleting the matches
function handle()
{
let element = document.getElementsByClassName('message')
let text = element[0].innerText;
let regex = /([^=])\$([A-Za-z:]{1,})/g;
let matches = text.match(regex);
if(matches != null)
{
for(let i = 0; i < matches.length; ++i)
{
// TODO takes matches are replace with spans with attributes.
}
}
}
You can simply use your regex in String.prototype.replace() and replace it with the desired markup wrapping your capturing group.
I have removed the first capturing group since it matches the empty whitespace before, which is not what you want. On top of that, I'd suggest using querySelectorAll and iterate through the node list to future proof your setup.
If you really only want to select the first element that matches the selector .message, that's also possible.
NOTE: Your output also seems to remove the message class from your original <span> element, but I'm not sure if that is a typo or intentional.
See proof-of-concept below:
function handle() {
const regex = /\$([A-Za-z:]{1,})/g;
document.querySelectorAll('.message').forEach(el => {
el.innerHTML = el.innerText.replace(regex, '<span class="highlight-yellow" my-custom-attribute="hello">$1</span>');
});
}
handle();
span.highlight-yellow {
background-color: yellow;
}
<span class="message">This is some text $HIGH:LOW $LOW:HIGH</span>

Remove all commas from a string in Jquery

I have many classes and want to remove the commas in them if any commas exist there.
I wrote the below code but the code does not work correctly. The second class value is replaced with the first value.
var removebox = $(".remove"),
removeboxHtml = removebox.html();
removebox.html(removeboxHtml.replace(/,/g , ''));
<html>
<head>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.4.min.js"></script>
</head>
<body>
<span class="remove">,17500000</span>
<span class="remove">,2479000</span>
</body>
</html>
Try this. Updated your code:
$(".remove").each(function(){
$(this).html($(this).html().replace(/,/g , ''));
});
<html>
<head>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.4.min.js"></script>
</head>
<body>
<span class="remove">,17500000</span>
<span class="remove">,2479000</span>
</body>
</html>
I would iterate over each element and change its' text:
var removebox = $(".remove");
removebox.each(function () {
var oldtext = $(this).text();
$(this).text(oldtext.replace(',', ''));
});
While you've already accepted an answer to this problem it's worth pointing out that they're both rather too verbose, and one answer, shennan's (at the time of writing), will only remove one comma from each of the given elements should multiple commas be present therein.
That said, a more concise version is below:
// select the elements to update:
$('.remove')
// we then use the text method's anonymous function,
// using the two arguments:
// index: the index of the current element in the collection,
// currentText: the text of the current element of the
// collection over the text method iterates:
.text(function(index, currentText) {
// here we access the currentText variable and use
// String.prototype.replace(), with a regular literal (/.../)
// to remove all occurrences (g) of the specified comma character
// replacing those occurrences with an empty string (''); this
// is comma-removed string is returned to the text method in
// order to update the text of each element as required:
return currentText.replace(/,/g, '');
});
$('.remove').text(function(index, currentText) {
return currentText.replace(/,/g, '');
});
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.4.min.js"></script>
<span class="remove">,17500000</span>
<span class="remove">,2479000</span>
<span class="remove">5,279,000</span>
Of course it's also worth showing that the above is perfectly possible in plain JavaScript, and still relatively concise:
// we use document.querySelectorAll() to retrieve
// a non-live HTMLCollection of elements matched
// by the supplied CSS selector:
var elements = document.querySelectorAll('.remove');
// we use Array.from() to convert an Array-like Object
// into an Array, in order that we can then iterate
// over those elements using Array.prototype.forEach():
Array.from(elements).forEach(function(elem) {
// 'elem', the first argument, is a reference to the
// current element of the Array of elements over
// which we're iterating.
// here we retrieve the current text-content of the
// current element, and use String.prototype.replace(),
// with a regular expression (exactly as above) to
// replace all occurrences ('g') of the comma character
// (',') in the string supplied by elem.textContent and
// we replace those commas with a empty string (''):
elem.textContent = elem.textContent.replace(/,/g, '');
});
var elements = document.querySelectorAll('.remove');
Array.from(elements).forEach(function(elem) {
elem.textContent = elem.textContent.replace(/,/g, '');
});
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.4.min.js"></script>
<span class="remove">,17500000</span>
<span class="remove">,2479000</span>
<span class="remove">5,279,000</span>
References:
JavaScript:
Array.from().
Array.prototype.forEach().
Document.querySelectorAll().
"Guide to JavaScript Regular Expressions."
String.prototype.replace().
jQuery:
text().

Match String of Input to text/element and highlight reactive

HTML(JADE)
p#result Lorem ipsum is javascript j s lo 1 2 4 this meteor thismeteor. meteor
input.search
JS
Template.pg.events({
'keyup .search': function(e){
e.preventDefault();
var text = $('p#result').text();
var splitText = text.match(/\S+\s*/g);
var input = $(e.target).val();
var splitInput = input.match(/\S+\s*/g);
if(_.intersection(splitText, splitInput)) {
var match = _.intersection(splitText, splitInput);
var matchToString = match.toString();
$('p#result').text().replace(matchToString, '<b>'+matchToString+ '</b>')
}
console.log(splitText); //check what I get
console.log(splitInput); //check what I get
}
})
I have the above code.
What I'm trying to do is matching the input field's value, and then matching the text. I added it the function to keyup so that this is reactive.
When the fields and text match, it will add bold tagsto the matched strings (texts).
I think I'm almost there, but not quite yet.
How would I proceed on from here?
MeteorPad
Here
In your code, you seem to only be matching on whole words, although your question does not specify that. If you want to match on any text in the input (e.g., if you type "a", all "a"s in the text are made bold), you can do that relatively easily using the javascript split and join String methods:
Template.pg.events({
'keyup .search': function(e){
e.preventDefault();
var text = $('p#result').text();
var input = $(e.target).val();
var splitText = text.split(input); // Produces an array without whatever's in the input
console.log(splitText);
var rep = splitText.join("<b>" + input + "</b>"); // Produces a string with inputs replaced by boldened inputs
console.log(rep);
$('p#result').html(rep);
}
});
Notably, you have to replace the text on the page using $('p#result').html(), which was missing in your MeteorPad example. Note also that this is a case-sensitive implementation; you can use a regex to do the split, but it gets a bit more complicated when you want to replace the text in the join. You can play around with it on this MeteorPad.
To do this case-insensitively, the split is very straightforward -- you can use a RegExp like so:
...
var regex = new RegExp($(e.target).val(), 'gi'); // global and case-insensitive, where `input` used to be
The tricky thing is to extract the correct case of what you want to pull out, then put it back in -- you can't do this with a simple join, so you'll have to interleave the two arrays. You can see an example of interleaved arrays here, which was taken from this question. I've amended that a bit to deal with the uneven array lengths, here:
var interleave = function(array1, array2) {
return $.map(array1, function(v, i) {
if (array2[i]) { return [v, array2[i]]; } // deals with uneven array lengths
else { return [v]; }
});
}
I've also created another MeteorPad that you can play around with that does all of this. lo is a good test string to check out.

Find previous <p> after nth character?

I want to create a "Read more" button that appears if an elements contains over 1700 characters.
I have achieved this as such:
var textlength = $(this).text().length;
if(textlength > 1700){
$(this).html($(this).html().substring(0, 1700));
$(this).append(readmorelink);
};
This removes all characters after the 1700th. But I would like to remove characters from the 1700th and back to the last </p> tag.
Does anyone know how I can traverse back from an nth character to a specific element?
Fiddle here: http://jsfiddle.net/xvWcH/
Use the lastIndexOf method to find the last occurance of a string before a specific index in the string:
var text = $(this).html();
var index = text.lastIndexOf('</p>', 1700);
$(this).html(text.substring(0, index + 4));

Find a string after a special character, move it and wrap a div around it

I have this HTML code, for example:
<div class="new">
<div class="in"></div>
<label>some text now watch this | the-thing</label>
</div>
I want to:
find the text thats after the "|" character
move it outside the label
wrap a span tag around it
I know how to do the 2nd and 3rd part, but I don't understand how to manipulate the string to begin with.
Here's a working example: http://jsfiddle.net/jfriend00/TaDKp/.
var re = /\|\s*(.*)$/;
var o = $(".new label");
var match = o.text().match(re);
if (match) {
o.text(o.text().replace(re, ""));
o.after("<span class='special'>" + match[1] + "</span>");
}
The steps described:
Find the desired label object
Find the text in the text of the label object using a regular expression
If the text is found, remove it from the label
Insert a span with that text after the label
You can use a regular expression to get/replace the text. Then create a span element and append it after the label.
var str = $( "div.new label" ).html();
var match = str.match( /\|(.*)/ )[1];
$( "div.new label" ).html( str.replace( /\|(.*)/, "" ) );
$( "div.new" ).append( "<span>" + match + "</span>" );
Example: http://jsfiddle.net/4m9AX/
You could use JavaScript regular expressions to capture and replace the text after the special character. Read about the standard RegExp class.
To do the first part you need to access the content of the label. Do that using jQuery. Something like:
$(".new > label").val();
And then to get the text after the "|" character, what you need is two javascript functions: indexOf and substr.
You'll need to use indexOf() to find the text after the character
var str = $('.new label').text();
var strToMove = str.substring(str.indexOf('|') + 1);
I don't have time to write the code, but here is probably how you should go about it:
1: Add an id to the label e.g. <label id="originaltext">
2. In your javascript, assign a variable to: document.getElementById("originaltext").innerText;
3. Use string.split to split the text using the '|' character into 2 variables
4. Set the contents of the original div to the text before the pipe using: document.getElementById("originaltext").innerText = stringbeforepipe
5. Set the contents of the new div using the same method except using the variable storing the string after the seperator.
So you want the final html snippet to be
<div class="new">
<div class="in"></div>
<span>the-thing</span>
<label>some text now watch this</label>
</div>
?
The jquery would look something like this:
var node = $('label').contains('|').
var txt = node.val();
var newtxt = txt.substr(0, txt.indexOf('|')-1);
var cuttxt = txt.substr(txt.indexOf('|')+);
node.before('<span>'' + cuttxt + '</span>');
node.text(newtxt);
Not test, probably won't work, YMMV, etc...
You can get the string thus:
var str = $('div.new label').text();
Then use string primitives to slice the bit of the string you want.

Categories

Resources