To Title Case by David Gouch

I wrote some Javascript to convert text to title case in response to John Gruber's public call. My script handles some edge cases Gruber's doesn't. See the test suite.

Just add .toTitleCase() to the string you want converted.

Tested and works in Firefox, Safari, Opera, and IE6.

Download the script

Try It Out

 

Version History

Version 1.1.1: Cleaned up a bit after running through JSLint.

Version 1.1: I simplified the regexes and made the script more robust. I dropped the special AT&T and Q&A search as they’re not needed.

An Explanation of the Code

NOTE: This was written for Version 1.0 – the latest version is slightly different.

What's basically happening is I break the title into segments and filter through them doing special conversions for special segments. If a segment makes it to the bottom I do a generic capitalize.

String.prototype.toTitleCase = function(){

That adds a .toTitleCase method to strings.

return this.replace(/([A-Za-z0-9&`'‘’"“”.:@\/()\{\\}[\]<>_]+-? *)/g, 
function(match, p1, index, title){

That breaks the title down into segments and passes each of them to an anonymous function. It's mostly just an inclusive regex search. I include trailing hyphens in the segment. The space is optional so we don't miss the last word of the title.

match = match.replace(/(at&t|q&a)/i, function(match){
	return match.toUpperCase();});

Here I check for the two special cases AT&T and Q&A if I find them I capitalize them and continue.

if (index > 0 && title.charAt(index - 2) != ":" && 
match.search(
/^(a(nd?|s|t)?|b(ut|y)|en|for|i[fn]|o[fnr]|t(he|o)|vs?\.?|via)[ \/-]/i) > -1)
    return match.toLowerCase();

Here I am checking for small words so I can lowercase them. But a small word starting a title should be capitalized. The index parameter of the replace method tells me how far into the title I am. I make sure it's past the first character.

I use the index parameter again to look two characters before my segment. If it's a : I know to capitalize the small word.

Finally I check for small words. I used a concise regular expression, but you could replace it with /^(and|as|at|but|by|en|for|if|in|of|on|or|the|to|via|vs?\.?|)[ \/-]/i if you want it to be clearer.

(Again, includes trailing hyphen.)

If it passes all the tests we convert it to lowercase and return the segment.

if (match.charAt(0).search(/['"_]/) > -1)
    return match.charAt(0) + match.charAt(1).toUpperCase() + match.substr(2);

That searchs for segments that begin with quote marks or underscores and capitalizes the segment one character past the marks. The underscores check is for people writing using Textile or Markdown: _my emphasized text_ needs to be appropriately capitalized.

if (match.substr(1).search(/[A-Z]+|[A-Za-z]+[._][A-Za-z]+/) > -1)
    return match;

That piece is searching for two things: words in camelCase and urls. I search the segment after the first character and if I find a capital letter I assume it's camelCase and probably the way it should be. If that isn't the case I also search for periods or underscores in which case it's probably a url so I should leave it alone and I return the segment unchanged.

    return match.charAt(0).toUpperCase() + match.substr(1);

If the segment made it past all my filters then it gets an old-fashioned capitalization and I send it back proud.

Other Things I’ve Made

Select Improvement – a script to create custom selects.