Remove excess words from a textbox - javascript

I have a script which is almost complete but I can't figure out the last bit here. The script is meant to limit the amount of words that can be entered into a text area and if they go over the word limit these extra words are removed. I have the amount of words beyond the max labeled as overage. For instance, if you were to enter in 102 words, then the overage would be 2. How would I remove those two words from the text area?
jQuery(document).ready(function($) {
var max = 100;
$('#text').keyup(function(e) {
if (e.which < 0x20) {
return;
}
var value = $('#text').val();
var regex = /\s+/gi;
var wordCount = value.trim().replace(regex, ' ').split(' ').length;
if (wordCount == max) {
// Reached max, prevent additional.
e.preventDefault();
} else if (wordCount > max) {
<!--Edited to show code from user3003216-->
<!--Isn't working like this, textarea doesn't update.-->
var overage = wordCount - max;
var words = value.split(' ');
for(var i = 0; i<overage; i++){
words.pop();
}
}
});
});

The easiest way to approach this is just to count the number of words on keypress and go from there. Check whether there are more words than the amount allowed. If so, remove all the excess words: while (text.length > maxWords). Then just replace the value of the text box with the updated text.
fiddle
JavaScript
var maxWords = 10;
$("#myText").keypress(function (event) {
var text = $(this).val().split(" "); // grabs the text and splits it
while (text.length > maxWords) { // while more words than maxWords
event.preventDefault();
text.pop(); // remove the last word
// event.preventDefault() isn't absolutely necessary,
// it just slightly alters the typing;
// remove it to see the difference
}
$(this).val(text.join(" ")); // replace the text with the updated text
})
HTML
<p>Enter no more than 10 words:</p>
<textarea id="myText"></textarea>
CSS
textarea {
width: 300px;
height: 100px;
}
You can easily test whether it works by pasting more than maxWords—in this case, 10—words into the textarea and pressing space. All the extra words will be removed.

You can put below code into your else if statement..
else if (wordCount > max) {
var overage = wordCount - max;
var words = value.split(' ');
for(var i = 0; i<overage; i++){
words.pop();
}
}
And if you want to get your string back from that words, you can use join like below:
str = words.join(' ');

well it would be better to use java script so here you go:
var maxWords = 20;
event.rc = true;
var words = event.value.split(" ");
if (words.length>maxWords) {
app.alert("You may not enter more than " + maxWords + " words in this field.");
event.rc = false;
}

jsFiddle Demo
You can use val to re-value the text-box. The array slice method will allow you to pull the first 100 words out of the array. Then just join them with a space and stick them back in the text-box.
$(document).ready(function($) {
var max = 100;
$('#text').keyup(function(e) {
if (e.which < 0x20) {
return;
}
var value = $('#text').val();
var words = value.trim().split(/\s+/gi);
var wordCount = words.length;
if (wordCount == max) {
// Reached max, prevent additional.
e.preventDefault();
} else if (wordCount > max) {
var substring = words.slice(0, max).join(' ');
$("#text").val(substring + ' ');
}
});
});

While you've already accepted an answer I thought I might be able to offer a slightly more refined version:
function limitWords(max){
// setting the value of the textarea:
$(this).val(function(i,v){
// i: the index of the current element in the collection,
// v: the current (pre-manipulation) value of the element.
// splitting the value by sequences of white-space characters,
// turning it into an Array. Slicing that array taking the first 10 elements,
// joining these words back together with a single space between them:
return v.split(/\s+/).slice(0,10).join(' ');
});
}
$('#demo').on('keyup paste input', limitWords);
JS Fiddle demo.
References:
JavaScript:
Array.prototype.join().
Array.prototype.slice().
String.prototype.split().
jQuery:
on().
val().

Related

Add Text At Location from indexOf

I am working on inserting text to the bottom of certain wordpress posts based on the amount of times a string occurs. I've managed to add the text to the bottom with append but instead I would like to insert at a specific location using indexOf.
here is the original text:
if ($('body').hasClass("single-post")){
var count = 0;
var cSearch = $('body').text();
var words = cSearch.indexOf('Words To Find')
while (words !== -1){
count++;
words = cSearch.indexOf('Words To Find', words + 1);
}
if( count >= 2){
$('.entry-content').append('<br><br>Sample Text');
}
}
Here is how I will get the location I want to insert before:
var insertLocation = cSearch.indexOf('Show what ya');
How can I splice the "Sample Text" into the location specified with insertLocation?
I found a bit about using polyfil for .splice but I'm not sure it works for this. Using it such as:
$(cSearch).splice( insertLocation, -1 ).text( "Sample Text" );
Can someone suggest a way to do this? Thanks!
Try creating variables representing total matches , indexOf() match plus matched text .length , using .slice() to insert original text before second match , new text ti insert , followed by remainder of original text
var text = $("div").text(),
match = "Words To Find",
txt = " Sample Text ",
matches = 0,
n = 0,
// `max` : total number of `matches` before inserting `txt`
max = 2;
while (matches < max) {
if (text.indexOf(match, n) !== -1) {
i = text.indexOf(match, n);
n = i + match.length;
++matches
}
}
// insert `re` after second match of `"Words To find"`
var re = text.slice(0, i + match.length) + txt;
$("div").text(re + text.slice(i));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<body>
<div>Words To Find abc def Words To Find ghi Words To Find</div>
</body>

jQuery: Count words with more than X characters in string

I have an input field and a textarea in a form. For each of those two fields I'd like to count the number of words, number of dots, and number of words longer than 7 characters.
I've already got the code for the two first numbers (number of words and number of dots), but I can't figure out how to count the number of words longer than 7 characters in each of the fields.
Can anyone help me out with this one?
Here is my current code (fiddle):
var titleElem = $('#title');
var numberOfWords = countWords(titleElem);
var numberOfDots = countDots(titleElem);
function countWords(input) {
var a, z, inputValue, total;
inputValue = input.val();
total = 0;
a = inputValue.replace(/\s/g, ' ');
a = a.split(' ');
for (z = 0; z < a.length; z++) { if (a[z].length > 0) total++; }
return total;
}
function countDots(input) {
var inputVal;
inputVal = input.val();
return inputVal.split(".").length - 1;
}
It depends what you classify as a word. Does that include hyphens/apostrophes? You could use a simple regex for this:
var wordCount = $("input").val().match(/[\w0-9]{8,}/gi).length
The {8,} ensures that it only captures words more than 7 characters in length.

textarea with limited lines and char limits

i need functionaliy which will have TextArea with
1) maximum total lines- 6 and
2) in each line there must be maximum of 16 chars
3) if user enters 17th character the cursor should go to the next line
and user will type in there (the line will be counted)
4) if user reaches to the 7th line it will not allow user to write
5) if user type e.g "Hello, I Love StackOverflow and its features" (counting
from 1st Char 'H', the 16th char is 't' but it is whole word 'StackOverflow',
it shouldn't break and continue to next line e.g.
Hello, I Love St
ackOverflow
now the whole word should come to next line like:
Hello, I Love
StackOverflow
and its features
here is the link what i have done so far
http://jsfiddle.net/nqjQ2/2/
sometimes some of the functionality work, some times not, and facing browser issues for onKeyUp and onKeyDown
can anyone help me with it ?
I think this is mostly what you want:
<textarea id="splitLines"></textarea>
JavaScript:
var textarea = document.getElementById("splitLines");
textarea.onkeyup = function() {
var lines = textarea.value.split("\n");
for (var i = 0; i < lines.length; i++) {
if (lines[i].length <= 16) continue;
var j = 0; space = 16;
while (j++ <= 16) {
if (lines[i].charAt(j) === " ") space = j;
}
lines[i + 1] = lines[i].substring(space + 1) + (lines[i + 1] || "");
lines[i] = lines[i].substring(0, space);
}
textarea.value = lines.slice(0, 6).join("\n");
};
See the fiddle in action.
In Jquery
$(function () {
var limit = function (event) {
var linha = $(this).attr("limit").split(",")[0];
var coluna = $(this).attr("limit").split(",")[1];
var array = $(this)
.val()
.split("\n");
$.each(array, function (i, value) {
array[i] = value.slice(0, linha);
});
if (array.length >= coluna) {
array = array.slice(0, coluna);
}
$(this).val(array.join("\n"))
}
$("textarea[limit]")
.keydown(limit)
.keyup(limit);
})
<textarea limit='10,5' cols=10 rows=5 ></textarea>
http://jsfiddle.net/PVv6c/

jQuery: Count words in real time

I am using the following jQuery functionality to count words in real time:
$("input[type='text']:not(:disabled)").each(function(){
var input = '#' + this.id;
word_count(input);
$(this).keyup(function(){
word_count(input);
})
});
var word_count = function(field) {
var number = 0;
var original_count = parseInt($('#finalcount').val());
var matches = $(field).val().match(/\b/g);
if(matches) {
number = matches.length/2;
}
$('#finalcount').val(original_count + number)
}
The issue I am running into is that when I start typing in an input field, the count increases immediately by two, even on spaces and my delete key. Any ideas why this would happen?
I was following this tutorial: http://www.electrictoolbox.com/jquery-count-words-textarea-input/
Input:
<input class="widest" id="page_browser_title" name="page[browser_title]" size="30" type="text" value="">
Display Input:
<input class="widest" disabled="disabled" id="finalcount" name="page[word_count]" size="30" type="text" value="662">
It is incrementing with every key press because you are telling it to with:
$('#finalcount').val(original_count + number)
And if you add another word, you will find that it increments not by 2, but by 3. Presumably, you have several inputs on the page, and you intend for the finalcount input to display the number of words in each input. Either store the counts in a variable and add the variables together to get your finalcount value. Or count the words in each input every time.
var wordCounts = {};
function word_count (field) {
var number = 0;
var matches = $(field).val().match(/\b/g);
if (matches) {
number = matches.length / 2;
}
wordCounts[field] = number;
var finalCount = 0;
$.each(wordCounts, function(k, v) {
finalCount += v;
});
$('#finalcount').val(finalCount)
}
Working demo: http://jsfiddle.net/gilly3/YJVPZ/
Edit: By the way, you've got some opportunities to simplify your code a bit by removing some redundancy. You can replace all of the JavaScript you posted with this:
var wordCounts = {};
$("input[type='text']:not(:disabled)").keyup(function() {
var matches = this.value.match(/\b/g);
wordCounts[this.id] = matches ? matches.length / 2 : 0;
var finalCount = 0;
$.each(wordCounts, function(k, v) {
finalCount += v;
});
$('#finalcount').val(finalCount)
}).keyup();
http://jsfiddle.net/gilly3/YJVPZ/1/
Edit
Check this example.
Why don't you use split(" ") instead of matching and dividing the result? You will have an array containing all your words, the length of the array will be the number of words.
var matches = $(field).val().split(" ");
Also, why are you adding every time the matches to the old result?
$('#finalcount').val(original_count + number)
Isn't this adding every time all the words twice?

Using javascript substring() to create a read more link

I'm developing a Classic ASP page that pulls some content from a database and creates a Read more link after the first 100 characters as follows;
<div class="contentdetail"><%=StripHTML(rspropertyresults.Fields.Item("ContentDetails").Value)%></div>
<script type="text/javascript">
$(function() {
var cutoff = 200;
var text = $('div.contentdetail').text();
var rest = $('div.contentdetail').text().substring(cutoff);
if (text.length > 200) {
var period = rest.indexOf('.');
var space = rest.indexOf(' ');
cutoff += Math.max(Math.min(period, space), 0);
}
var visibleText = $('div.contentdetail').text().substring(0, cutoff);
$('div.contentdetail')
.html(visibleText + ('<span>' + rest + '</span>'))
.append('<a title="Read More" style="font-weight:bold;display: block; cursor: pointer;">Read More…</a>')
.click(function() {
$(this).find('span').toggle();
$(this).find('a:last').hide();
});
$('div.contentdetail span').hide();
});
</script>
However, the script obviously just cuts the text off after 100 characters. Preferably I would like it to keep on writing text until the first period or space, for example. Is this possible to do?
Thank you.
var cutoff = 100;
var text = $('div.contentdetail').text();
var rest = text.substring(cutoff);
if (text.length > cutoff) {
var period = rest.indexOf('.');
var space = rest.indexOf(' ');
cutoff += Math.max(Math.min(period, space), 0);
}
// Assign the rest again, because we recalculated the cutoff
rest = text.substring(cutoff);
var visibleText = $('div.contentdetail').text().substring(0, cutoff);
EDIT: shortened it a bit.
EDIT: Fixed a bug
EDIT: QoL improvement
How about:
var text= $('div.contentdetail').text();
var match= text.match( /^(.{100}([^ .]{0,20}[ .])?)(.{20,})$/ );
if (match!==null) {
var visibleText = match[1];
var textToHide = match[3];
...do replacement...
}
The {0,20} will look forward for a space or period for up to 20 characters before giving up and breaking at exactly 100 characters. This stops an extremely long word from breaking out of the length limitation. The {20,} at the end stops a match being made when it would only hide a pointlessly small amount of content.
As for the replacement code, don't do this:
.html(visibleText + ('<span>' + textToHide + '</span>'))
This is inserting plain-text into an HTML context without any escaping. If visibleText or textToHide contains any < or & characters you will be mangling them, perhaps causing a XSS security problem in the process.
Instead create the set the text() of the div and the span separately, since that's the way you read the text in the first place.
Here is a fairly simple approach to getting endings at the word level, and shooting for about your given limit in characters.
var limit = 100,
text = $('div.contentdetail').text().split(/\s+/),
word,
letter_count = 0,
trunc = '',
i = 0;
while (i < text.length && letter_count < limit) {
word = text[i++];
trunc += word+' ';
letter_count = trunc.length-1;
}
trunc = $.trim(trunc)+'...';
console.log(trunc);

Categories