Friday, January 2, 2015

Wrapping it Up

Wrapping Paper. Really cheap right now.
I know, you are probably sick of wrapping after all those Christmas presents just a week ago. So today I'm talking about line-wrapping.

Today's comic lets you write a short message in the last cell, made out of those wooden letter blocks that little kids play with. Of course, space is limited in the cell and there's only room for about 10 letter blocks per row. To make a multi-word message fit, I had to use a line-wrapping algorithm to split up the text into lines that were no longer than 10 characters each.

There is a fairly good write-up of the process on Wikipedia. I needed a JavaScript implementation so the wrapping could happen in the browser after the user types in the message.

It was actually quite simple. Here is my function:

function lineWrap(text, len) {

    var lineWidth = len || 10; // if line length not specified, default is 10
    var spaceLeft = lineWidth;
    var words = text.split(/\s/);
 
    for (var w in words) {
        var word = words[w];
        if ((word.length + 1) > spaceLeft) {
            words[w] = "\n" + word;
            spaceLeft = lineWidth - word.length;
        } else {
            spaceLeft = spaceLeft - (word.length + 1);
        }
    }

    return words.join(" ").trim();

}

My version defaults the maximum line length to 10 (as you can see on line 3) but you could change that to any default you want. You can also specify another value as the second parameter to the function each time you call it.

To wrap the lines, the given text is first split into an array of words. I split using the regular expression for white-space on line 5. Then, go through the list of words and check if the length of the word plus 1 space will exceed the space available on the line. If it will, put a newline character on the front of the current word and set the space available to be the maximum line length minus the length of the current word. Otherwise, subtract the length of the current word plus 1 space from the current space available and move on to the next word.

After all the words have been checked, I use the join() function on line 17 to put the array of words back together with a space in between each word.

If you call the function like this:

lineWrap("this is some text that should wrap");

the resulting text should look like this:

this is
some text
that
should
wrap

But if you call the function with a longer line length,

lineWrap("this is some text that should wrap", 20);

the resulting text will look like this:

this is some text
that should wrap

Looks good, right? Now get wrapping! Lines, not presents.

Amphibian.com comic for 2 January 2015