Note: A good CSS rule might solve your problem, no JS required. Look into the word-wrap property.
Moving on with the code, here's a few solutions.
First, I recommend isolating your concerns in separate functions. In your snippet, you reach into a few different things, like Item.bounds.width
and Item.value
. You're better off passing these to functions to operate on them and handing the result back to the object. So as I understand the core of your question, you want a function like:
function(str: string,
chunkLength: number,
delimiter: string = "\n",
maxLines: number = 3) { /* code */ }
The function needs to:
- Break str into chunks of given size
- Take only as many chunks as allowed by line size
- Join them all together with a delimiter
You would invoke this function in your above snippet:
Item.value = demoFunction(Item.value,selectedItemLength);
Keep in mind that as you asked it (and as I wrote my solutions), you ignore whitespace. This will break words or tokens apart with no regard for whitespace. This may not be desired. ie,
testFunction("teal mittens", 8) == "teal mit\ntens";
Imperative Solution
This is a stateful for loop, as you mentioned.
var demoImperative = function(str, chunkLength, delimiter = "\n", maxLines = 3) {
var chunks = [];
for (var index = 0; index < str.length && chunks.length < maxLines; index += chunkLength) {
// NOTE: substr != substring. See https://stackoverflow.com/questions/3745515/what-is-the-difference-between-substr-and-substring
chunks.push(str.substr(index, chunkLength));
}
return chunks.join(delimiter);
}
Messy, but it works. The for loop keeps moving through the str by index until out of string or lines. I chose not to build the string on the fly, since this means the loop would have to track the current line number as another variable and joining (without putting an extra \n on the end) is trickier.
RegExp Solution
This makes use of a trick I found on SO to split js strings by length.
var demoRegExp = function(str, chunkLength, delimiter = "\n", maxLines = 3) {
var regExp = new RegExp('.{1,'+chunkLength+'}', 'g');
return str.match(regExp).slice(0,maxLines).join(delimiter);
}
Certainly terse, if a tad unclear. The .match()
does the split, .slice()
takes only the proper number of lines, and .join()
brings the array back to a string.
Ramda Solution
This one uses Ramda.JS, a functional library that makes data transformation in js (what you're doing here) much simpler. I wrote this one for fun.
var demoRamda = function(str, chunkLength, delimiter = "\n", maxLines = 3) {
return R.pipe(
R.splitEvery(chunkLength),
R.take(maxLines),
R.join(delimiter)
)(str);
}
Clear and simple, but this requires the ramda.js library. Unless you're doing this server-side (unlikely) including a huge utility library for this one action is overkill, so I would advise against this one.