I am attempting to create a tool that takes an input text and splits it into chunks of text at a certain # of characters. However, I need to make sure it does not split the
A short and simple way to split a string into chunks up to a certain length using a regexp:
const chunks = str.match(/.{1,154}(\s|$)/g);
some examples:
const str = 'the quick brown fox jumps over the lazy dog';
console.log(str.match(/.{1,10}(\s|$)/g))
console.log(str.match(/.{1,15}(\s|$)/g))
This works because quantifiers (in this case {1,154}
) are by default greedy and will attempt to match as many characters as they can. putting the (\s|$)
behind the .{1,154}
forces the match to terminate on a whitespace character or the end of the string. So .{1,154}(\s|$)
will match up to 154 characters followed by a whitespace character. The /g
modifier then makes it continue to match through the entire string.
To put this in the context of your function:
function splitText() {
"use strict";
var str = document.getElementById("user_input").value;
var chunks = str.match(/.{1,154}(\s|$)/g);
chunks.forEach(function (i,x) {
$("#display").append("<textarea readonly>" + chunks[x] + "</textarea><br/>");
});
}
Note (as has been pointed out in the comments) that this code will fail if one of the words in the string is longer than the length of the chunks.
This solution goes on the logic of having a maximum chunk size and then reducing that size if need be to fit your word. Uses a while loop and a little bit of C style logic.
function splitText() {
"use strict";
var str = document.getElementById("user_input").value;
// Maximum allowed chunk size
let MAX_CHUNK_SIZE = 155;
let chunks = new Array();
let current_chunk_position = 0;
while(current_chunk_position < str.length){
let current_substring = str.substr(current_chunk_position, MAX_CHUNK_SIZE);
let last_index = current_substring.lastIndexOf(" ") > 0 ? current_substring.lastIndexOf(" ") : MAX_CHUNK_SIZE;
let chunk = str.substr(current_chunk_position, last_index);
chunks.push(chunk);
current_chunk_position += last_index;
}
var newq = 0;
for (var x = 0, q = 0; x < nChunks; ++x, q = newq) {
$("#display").append("<textarea readonly>" + chunks[x] + "</textarea><br/>");
}
}
A more simple approach would be to split the entered text into an array of the individual words and then loop through the array and re-build the string, keeping a count of whether adding the next word in the array will put you over your max size.
Also, note that you should keep all of your form
elements inside a single form
.
Lastly, you should not use inline HTML event attributes (onclick
, etc.). That was a technique we used 20+ years ago before we had standards and best-practices and, unfortunately the use of the technique is so prolific, it just will not die the abrupt death it deserves. There are many reasons not to code this way and instead use the modern approach of doing all event handling with .addEventListener()
in a separate JavaScript.
// Don't set variables to properties of DOM elements, set them to the element
// itself so that if you ever want a different property value, you don't have to
// re-scan the DOM for the same element again.
var str = document.getElementById("user_input");
var output = document.getElementById("display");
document.getElementById("go").addEventListener("click",function(){
"use strict";
const size = 155; // Constant is more appropriate here
var words = str.value.split(/\s+/g); // Create array of all words in field
var finalString = "";
// Loop through array
for(var i = 0; i < words.length; i++){
if((finalString + " " + words[i]).length <= size){
finalString += " " + words[i];
} else {
break; // Max size exceeded - quit loop!
}
}
// Update field with correct value
output.textContent = finalString;
console.log(finalString.length);
});
textarea {
width:500px;
height:100px;
}
<h1>Text Splitter</h1>
<form>
<label>Enter a Message
<textarea name="message" id="user_input">This is a test of the emergency broadcast system. If this had been an actual emergency, you would have been informed as to what instructions you should follow in order to remain safe at all times.</textarea></label>
<input type="button" id="go" value="Submit!"><br>
</form>
<label>Your split message: </label>
<p><span id='display'></span></p>
you could use a simple function like this:
function split(string) {
for(i=154; i>=0; i--) {
if(string.charAt(i) == " ") {
var newString1 = string.slice(0, i);
var newString2 = string.slice(i);
}
}
}
Instead of assigning to separate strings you can always put them into an array if you'd like as well.