/*
String.prototype.titleCase 1.0

An implementation of John Gruber's TitleCase.pl in JavaScript.
(http://daringfireball.net/projects/titlecase/TitleCase.pl)

TitleCase.pl Documentation:

	#   This filter changes all words to Title Caps, and attempts to be clever
	#   about *un*capitalizing small words like a/an/the in the input.
	#
	#   The list of "small words" which are not capped comes from
	#   the New York Times Manual of Style, plus 'vs' and 'v'. 
	#
	#   John Gruber
	#   http://daringfireball.net/
	#   10 May 2008
	#
	#   License: http://www.opensource.org/licenses/mit-license.php
	#


Usage:
  js> "Sub-Phrase With a Small Word in Quotes: 'a Trick, Perhaps?'".toTitleCase()
  "Sub-Phrase With a Small Word in Quotes: 'A Trick, Perhaps?'"



Uses Steven Levithan's Cross-Browser Split (note: this replaces your
hosts's native split method).

By Jon Hohle <http://hohle.net>
21.May.2008
MIT Licence <http://www.opensource.org/licenses/mit-license.php>

*/


/*
	Cross-Browser Split 0.2.1
	By Steven Levithan <http://stevenlevithan.com>
	MIT license
*/

var nativeSplit = nativeSplit || String.prototype.split;

String.prototype.split = function (s /* separator */, limit) {
	// If separator is not a regex, use the native split method
	if (!(s instanceof RegExp))
		return nativeSplit.apply(this, arguments);

	/* Behavior for limit: If it's...
	 - Undefined: No limit
	 - NaN or zero: Return an empty array
	 - A positive number: Use limit after dropping any decimal
	 - A negative number: No limit
	 - Other: Type-convert, then use the above rules */
	if (limit === undefined || +limit < 0) {
		limit = false;
	} else {
		limit = Math.floor(+limit);
		if (!limit)
			return [];
	}

	var flags = (s.global ? "g" : "") + (s.ignoreCase ? "i" : "") +
	    (s.multiline ? "m" : ""),
	    s2 = new RegExp("^" + s.source + "$", flags),
	    output = [],
	    lastLastIndex = 0,
	    i = 0,
	    match;

	if (!s.global)
		s = new RegExp(s.source, "g" + flags);

	while ((!limit || i++ <= limit) && (match = s.exec(this))) {
		var zeroLengthMatch = !match[0].length;

		// Fix IE's infinite-loop-resistant but incorrect lastIndex
		if (zeroLengthMatch && s.lastIndex > match.index)
			s.lastIndex = match.index; // The same as s.lastIndex--

		if (s.lastIndex > lastLastIndex) {
			// Fix browsers whose exec methods don't consistently
			// return undefined for non-participating capturing groups
			if (match.length > 1) {
				match[0].replace(s2, function () {
					for (var j = 1; j < arguments.length - 2; j++) {
						if (arguments[j] === undefined)
							match[j] = undefined;
					}
				});
			}

			output = output.concat(
			    this.slice(lastLastIndex, match.index),
			    (match.index === this.length ? [] : match.slice(1)));
			lastLastIndex = s.lastIndex;
		}

		if (zeroLengthMatch)
			s.lastIndex++;
	}

	return (lastLastIndex === this.length) ?
		(s.test("") ? output : output.concat("")) :
		(limit      ? output : output.concat(this.slice(lastLastIndex)));
};



// give a hoot, don't pollute
var __TitleCase = {
	__smallWords: ['a', 'an', 'and', 'as', 'at', 'but',
		'by', 'en', 'for', 'if', 'in', 'of', 'on', 'or',
		'to', 'v[.]?', 'via', 'vs[.]?'],

	init: function() {
		this.__smallRE = this.__smallWords.join('|');
		this.__lowerCaseWordsRE = new RegExp(
			'\\b(' + this.__smallRE + ')\\b', 'gi');
		this.__firstWordRE = new RegExp(
			'^([^a-zA-Z0-9 \\r\\n\\t]*)(' + this.__smallRE + ')\\b', 'gi');
		this.__lastWordRE = new RegExp(
			'\\b(' + this.__smallRE + ')([^a-zA-Z0-9 \\r\\n\\t]*)$', 'gi');
	},

	toTitleCase: function(string) {
		var line = '';

		var split = string.split(/([:.;?!][ ]|(?:[ ]|^)["“])/);

		for (var i = 0; i < split.length; ++i) {
			var s = split[i];

			// convert all to lowercase first
			s = s.toLowerCase()

			s = s.replace(
				/\b([a-zA-Z][a-z.'’]*)\b/g,
				this.__titleCaseDottedWordReplacer);

			// lowercase the list of small words
			s = s.replace(this.__lowerCaseWordsRE, this.__lowerReplacer);

			// if the first word in the title is a small word then capitalize it
			s = s.replace(this.__firstWordRE, this.__firstToUpperCase);

			// if the last word in the title is a small word, then capitalize it
			s = s.replace(this.__lastWordRE, this.__firstToUpperCase);

			line += s;
		}

		// special cases
		line = line.replace(/ V(s?)\. /g, ' v$1. ');
		line = line.replace(/(['’])S\b/g, '$1s');
		line = line.replace(/\b(AT&T|Q&A)\b/ig, this.__upperReplacer);

		return line;
	},

	/*	Original Dotted Word Replace That would ignore any words containing a dot
	__titleCaseDottedWordReplacer: function (w) {
		return (w.match(/[a-zA-Z][.][a-zA-Z]/)) ? w : __TitleCase.__firstToUpperCase(w);
	},
	*/
	
	__titleCaseDottedWordReplacer: function (w) {
		return __TitleCase.__firstToUpperCase(w);
	},

	__lowerReplacer: function (w) { return w.toLowerCase() },

	__upperReplacer: function (w) { return w.toUpperCase() },

	__firstToUpperCase: function (w) {
		var split = w.split(/(^[^a-zA-Z0-9]*[a-zA-Z0-9])(.*)$/);
		split[1] = split[1].toUpperCase();
		return split.join('');
	},

	test: function() {
		var testStrings = [
			"Q&A With Steve Jobs: 'That's What Happens In Technology'",
			"What Is AT&T's Problem?",
			"Apple Deal With AT&T Falls Through",
			"this v that",
			"this vs that",
			"this v. that",
			"this vs. that",
			"The SEC's Apple Probe: What You Need to Know",
			"'by the Way, small word at the start but within quotes.'",
			"Small word at end is nothing to be afraid of",
			"Starting Sub-Phrase With a Small Word: a Trick, Perhaps?",
			"Sub-Phrase With a Small Word in Quotes: 'a Trick, Perhaps?'",
			'Sub-Phrase With a Small Word in Quotes: "a Trick, Perhaps?"',
			'"Nothing to Be Afraid of?"',
			'"Nothing to Be Afraid Of?"',
			'a thing'];


		var validStrings = [
			"Q&A With Steve Jobs: 'That's What Happens in Technology'",
			"What Is AT&T's Problem?",
			"Apple Deal With AT&T Falls Through",
			"This v That",
			"This vs That",
			"This v. That",
			"This vs. That",
			"The SEC's Apple Probe: What You Need to Know",
			"'By the Way, Small Word at the Start but Within Quotes.'",
			"Small Word at End Is Nothing to Be Afraid Of",
			"Starting Sub-Phrase With a Small Word: A Trick, Perhaps?",
			"Sub-Phrase With a Small Word in Quotes: 'A Trick, Perhaps?'",
			'Sub-Phrase With a Small Word in Quotes: "A Trick, Perhaps?"',
			'"Nothing to Be Afraid Of?"',
			'"Nothing to Be Afraid Of?"',
			'A Thing'];

		for (var i = 0; i < testStrings.length ; ++i)
		{
			var s = testStrings[i].toTitleCase();
			if (s != validStrings[i])
			{
				alert(s + '\ndoes not match\n' + validStrings[i]);
				return false;
				break;
			}
		}    
		return true;
	}
};

__TitleCase.init();

function toTitleCase(string) { return __TitleCase.toTitleCase(string); }

String.prototype.toTitleCase = function() { return toTitleCase(this); }
