What I need is to be able to limit the number of lines in a textarea. And to limit the number of characters in each line (force adding a newline when maximum number of characters has been added.
I am not interested in the "rows" and "cols" attributes. They do not work.
Also, I would like to have it working even if the user cuts or pastes something, or if he returns to a line and modifies it.
Not sure if this is an overly complex way of doing it but you can loop through the textarea and add a newline every X characters. This solution won't allow users to insert their own line breaks (it strips off any existing line breaks) .
<textarea onkeyup="formatTextArea(this)"></textarea>
<script type="text/javascript">
function formatTextArea(myArea)
{
//strip off any line breaks first
var str = myArea.value.replace(/\n|\r/g, "");
var result = '';
var i = 0
var formattedText = '';
//number of lines needed
var limit = 5
// number of characters
var limitPerLine = 20;
// loop through the text, adding a new line every limitPerLine characters
// stop after limit lines
while (str.length > 0 && i < limit)
{
i++;
formattedText += str.substring(0, limitPerLine);
str = str.substring(limitPerLine);
//only add a new line if we're not at the end of the content
if(str.length > 0 && i < limit)
{
formattedText += '\n';
}
}
myArea.value = formattedText;
}
</script>
Related
I am creating a GDocs Apps Script to check my document to see if it is in Standard Pilish. I'd like to have the checker return both the position of the first error and the word that is incorrect. I can get the position of the first error in pi, but since the word list does not necessarily perfectly reflect that positioning.
For example, I used a modified quote from Peter Walder: "Two mathematicians accommodatingly promenade to tavern, quest everything". The error lies in the 8th word in the list, but the 10th position in pi.
This is the script I've landed at, and I originally tried to just words[positionOne] before realizing my counting error.
function pilishTranslate() {
var doc = DocumentApp.getActiveDocument();
var text = doc.getBody().getText();
// Remove quotation marks from the text
text = text.replace(/\"/g, "");
// Replace all non-letter characters with white space
text = text.replace(/[^a-zA-Z\s]/g, " ");
// Split the text into an array of words
var words = text.split(/\s+/);
// Count word length
var wordLengths = words.map(function(word) {
return word.length;
});
// Change 10 character counts to 0
wordLengths = wordLengths.map(function(length) {
return length === 10 ? 0 : length;
});
// Join character counts into single string
var wordLengthsString = wordLengths.join('');
// Create variable for pi
var decimal15 = '314159265358979'
// Find common prefix of strings a and b.
var prefix = function(a,b){
return a && a[0] === b[0] ? a[0] + prefix(a.slice(1), b.slice(1)) : '';
};
// Find index of first difference.
var diff = function(a,b){
return a===b ? -1 : prefix(a,b).length;
};
// actual test case
var tests = [
[wordLengthsString,decimal15],
];
// find first position of error
var positionOne = tests.map(test => diff(test[0], test[1]))
console.log(positionOne);
}
function checkPilish(text) {
// Remove quotation marks from the text
text = text.replace(/\"/g, "");
// Replace all non-letter characters with white space
text = text.replace(/[^a-zA-Z\s]/g, " ");
// Split the text into an array of words
var words = text.split(/\s+/);
// Create variable for pi
var decimal15 = '314159265358979'
let pi_index = 0;
// Loop over words
for (let i = 0; i < words.length; i++) {
// convert word length to Standard Pilish digits
let length_str = String(words[i].length);
if (length_str == '10') {
word_length = '0';
}
// check if this matches the current position in pi
if (decimal15.substr(pi_index, length_str.length) != length_str) {
return [i+1, words[i]];
}
pi_index += length_str.length;
}
return [];
}
console.log(checkPilish("Two mathematicians accommodatingly promenade to tavern, quest everything"));
console.log(checkPilish("Two mathematicians accommodatingly promenade to tavern, quest all"));
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().
I have a string
var string = "mario rossi laureato";
and I have only 15 characters available to write in a td of a table.
so the expected results should be this:
<td id="firstTD">mario rossi</td> //this td has 15 characters available
<td id="secondTD">laureato</td>
fifteenth place intersects the word "laureato", so it's calculated the excess , and takes the previous word.
another example:
var string2 = "hello my name is Paolo"
so the expected results should be this:
<td id="firstTD">hello my name</td> //this td has 15 characters available
<td id="secondTD">is Paolo</td>
fifteenth place intersects the word "is", so it's calculated the excess , and takes the previous word.
Guys any idea about this?
Try this: http://jsfiddle.net/Zh8RR/
// Sample string, to make it easy to see the cut points I've use 1-15 in hex to give us a nice easy way to see the breaks
var string = "1234567 9ABCDE 12345 7 89AB 123456 89ABC E 12 45 789A CD 123";
// Break input string up into words
var parts = string.split(' ');
var sections = [""];
var rows = 0;
// For each word
for (var i = 0; i < parts.length; ++i) {
// If it makes the section too long push it to the next section:
if (sections[rows].length + parts[i].length + 1 > 15) {
rows++;
}
// If we have no text initialise it to be the current word
if(!sections[rows]) {
sections[rows] = parts[i];
} else {
// Otherwise use a space as a separator and concat them.
sections[rows] += " " + parts[i];
}
}
// Write them out to a sample div so we can check.
$('div').html(sections.join("<br />"));
you could do:
var str = "mario rossi laureato";
var strArr = str.match(/.{1,15}/g);
console.log(strArr.length);
for(var s=0,slen=strArr.length; s < slen; s++) {
console.log(strArr[s]);
//create td and append or append strArr[s] to existing td
}
I'm trying to use basic operators to create my own custom array in JavaScript, I guess.
This book I'm reading, "Eloquent JavaScript", has an exercise in Chapter 1 that asks me to make a pyramid using the "print" function. There's no print function in any of my interpreters, and it doesn't say how to make a print function. So, I don't have a print function, and I'm using alerts.
Here's the code.
var line = "";
var counter = 0;
while (counter < 10) {
line = line + "#";
print(line);
counter = counter + 1;
}
So, I was trying to use alerts, instead:
var line = "";
var counter = 0;
while (counter < 10) {
line = line + "#";
alert(line);
counter = counter + 1;
}
But the alert isn't a triangle. It's a bunch of boxes where the number of pound signs grows each time.
I want to create a string concatenation and then print out the entire result.
This is what I came up with:
string = "";
counter = 0;
signs = "#";
while (counter < 10){
string = string + signs + "\n";
signs = signs + "#";
counter = counter + 1;
}
alert(string);
So, I am just wondering, is there a better way to create arrays without knowing how to create array variable?
Your first pound-sign (tip of pyramid) should be spaced half the length of your base of your pyramid. So, if your base is 10 # signs long, then the top of your pyramid should be spaced out to 4 spaces then print the # sign.
Second, to make a true pyramid, you'll need to print top to bottom so your second row is progressively getting larger. Think in odd numbers:
// Example
Tip: 1 char
2nd row: 3 chars
3rd row: 5 chars
4th row: 7 chars
5th row: 9 chars
6th row: 11 chars
etc
Your newline character is wrong. It should be a \n. If printing to HTML, then use <BR>.
Alternatively, you can use console.log to print your characters.
The newline character is "\n" not "/n". (The "escape" character in general is backslash not forward slash.)
Also, you have a typo that you said sings = ... instead of signs = ...
EDIT: OK, so you've updated your question to correct both of those problems. Regarding your new question:
So, I am just wondering, is there a better way to create arrays
without knowing how to create array variable?
It sounds like you don't really understand what an array variable is: an array is a data structure that allows you to store data items that are selected by indices. Why do you think you need an array for this "pyramid" functionality?
As an aside, your code could be improved using += and ++:
a = a + b; can be abbreviated as a += b;
a = a + 1; can be abbreviated as a++;
This should work
var stringBuilder = "";
counter = 0;
signs = "#";
while (counter < 10){
stringBuilder = stringBuilder + signs + "\n";
signs = signs + "#";
counter = counter + 1;
}
alert(stringBuilder);
Newline is backslash and "n"
You need only one newline character that is within the loop
The following code should work:
string = "";
counter = 0;
signs = "#";
while (counter < 10){
string = string + signs + "\n";
signs = signs + "#";
counter = counter + 1;
}
alert(string);
The major differences are as follows:
You can't include the newline character in the string you are building, otherwise newlines from previous iterations will still be included in subsequent iterations.
The newline character is \n and not /n.
string can start off as being empty, since you will be appending a "#" each time.
This would be another way to do it:
<script>
string = ""; height = 10;
for(i = 1; i <= height; i++){
string += Array(i).join('#') + '<br>';
}
document.write(string);
</script>
Output:
#
##
###
####
#####
######
#######
########
#########
Now with some more modification:
<script>
string = ""; height = 10;
for(i = 1; i <= height; i++){
string += Array(height-i+1).join(' ') + Array(2*i).join('#') + '<br>';
}
document.write(string);
</script>
<style>body{font-family:monospace;}</style>
You get this:
#
###
#####
#######
#########
###########
#############
###############
#################
###################
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);