Tuesday, May 19, 2009

Sometimes I Could Just explode()

Every once in a while, a fella in a hurry to get somewhere drives a little faster than his brain can handle, and said fella ends up veering off the road and into a ditch somewhere. That's sort of what happened to me this morning.

I have a function that pulls debugging information and spits it out to a div element, and I wanted that div to have a limited scrollback buffer defined by lines rather than characters. Since a line break is used to end each log entry, I figured a simple .split("<br>") would do the handiwork of creating an array of log items that I could then reverse sort, trim, and spit back out into the div (so my newest items appeared at the top).

Oh, nay nay.

Unbeknownst to me, there's something funny about that self-closing line break, however, that split() didn't like. In fact, it just so happens that HTML tags in general require a bit of attention. I eventually discovered that this was all I needed:

.split(/<\s*br\s*\/?\s*>/gi)

This expression works on variations of <br>, including my <br />, and is not case sensitive, so it works equally well in Firefox as it does IE, which tends to force HTML tags to uppercase in the DOM. (This is important since I'm setting the innerHTML attribute of the div.)

However, I wasn't aware of any of this stuff when I ran into my little problem. So I struck out to create a mimic of PHP's explode() function, except as a prototype extension to string objects. This is the result:


// Javascript prototype that mimics PHP's explode function
String.prototype.explode = function(delimiter, limit) {
// Make 'limit' an optional parameter with a default of 0 (unlimited)
if (typeof limit == 'undefined') limit = 0;

// Create an empty array, the temp buffer, and a copy of the source string
var elements = [];
var temp_el = '';
var temp_str = new String(this);

// Loop through the local copy, removing each slice and pushing it to the array
// Note that we check here to see if we've reached our array element limit
while ((temp_str.indexOf(delimiter) > 0) && ((limit == 0) || (elements.length < limit))) {
temp_el = temp_str.substr(0, temp_str.indexOf(delimiter));
temp_str = temp_str.substr(temp_str.indexOf(delimiter) + delimiter.length, temp_str.length - temp_str.indexOf(delimiter) + 1);
elements.push(temp_el);
}

// If we have any remaining characters, and we haven't yet reached our
// element limit, push the remaining string to another element in the array
if ((temp_str.length > 0) && (elements.length < limit)) elements.push(temp_str);

// Return the array
return elements;
}


Interestingly enough, however, this failed to handle my HTML tags, just as split() failed, presumably for the same reasons. So my time perfecting this little gem ended up being all for naught, since I had to research why this function wouldn't handle the HTML tags either. What a colossal waste of time.

The function itself works, and quite well, from what I can tell based on my limited testing, so if you want it, you're more than welcome to it.

Be warned, however, that split() really is the only way to go. I'm only sharing it for its intrinsic humorous and edutainment value.

No comments: