//#require core.js

extend(String.prototype, {
	/**
	 * change first letter to uppercase
	 */
	ucFirst: function() {
		return this.substring(0,1).toUpperCase() + this.substring(1);
	},

	/**
	 * change first letter to lowercase
	 */
	lcFirst: function() {
		return this.substring(0,1).toLowerCase() + this.substring(1);
	},

	/**
	 * convert a string to CamelCase, using specific chars as the splitting
	 * characters (by default only alphanumeric characters are kept, while
	 * all other are used as delimiters)
	 */
	CamelCase: function(chars) {
		if(!exists(chars)) chars = /[^a-zA-Z0-9]/;
		var parts = this.split(chars);
		var result = '';
		for(i = 0; i < parts.length; i++)
			result += parts[i].substring(0,1).toUpperCase() + parts[i].substring(1);
		return result;
	},

	/**
	 * same as CamelCase, only the first letter is kept lowercase
	 */
	camelCase: function(chars) {
		return this.CamelCase(chars).lcFirst();
	},

	/**
	 * returns true if string contains a given substring
	 * a shortcut form of "indexOf" (and does not return the index)
	 */
	has: function(substr) {
		return this.indexOf(substr) >= 0;
	},

	/**
	 * replace all %X tokens (where X is any character) with substitute
	 * values.
	 *
	 * @param tokens a hash of "token: substitute" pairs
	 * @param eschar the escape character. '%' is used if none given
	 */
	ptokens: function(tokens, eschar) {
		if(!eschar) eschar = '%';
		var reg = new RegExp("(" + eschar + ")(.)", "g")
		return this.replace(reg, function() {
			var token = arguments[2];
			return exists(tokens[token]) ?
				tokens[token] :
				token;
		});
	}
});

 