// Javascript Plus - JS Language extensions to native types
// Ali Chamas 12/12/07 - For use in City Of Sydney Online Applications

String.prototype.digitAt = function (index) {
	var str = new String(this);
	if (index < str.length)
		str = this.charAt(index);
	else
		str = "####";
	return parseInt(str);
}

String.prototype.toInt = function () {
	return parseInt(this);
}

String.prototype.subtract = function (subtractAmountFromRight) {
	var str = new String(this);
	if (str.length >= subtractAmountFromRight)
		str = str.substring(0, str.length - subtractAmountFromRight);
	return str;
}

String.prototype.padLeft = function (length, str) {
	var padded = new String(this);
	while (padded.length < length)
		padded = str + padded;
	return padded;
}

String.prototype.left = function () {
	var str = new String(this);
	if (str.length > 0)
		str = str.charAt(0);
	return str;
}

String.prototype.right = function () {
	var str = new String(this);
	if (str.length > 0)
		str = str.charAt(str.length - 1);
	return str;
}

String.prototype.trim = function () {
	var str = new String(this);
	if (str.length > 0) {
		str = str.replace(/^ +/, "");
		str = str.replace(/ +$/, "");
		return str;
	}
	return str;
}

String.prototype.ubound = function () {
	return Math.max(0, this.length - 1);
}

String.prototype.commaFormat = function () {
	var str = this;
	var delimiter = ",";
	var a = str.split('.', 2);
	var d = a[1];
	var i = a[0].toInt();
	if (isNaN(i))
		return '';
	var minus = '';
	if (i < 0)
		minus = '-';
	i = Math.abs(i);
	var n = new String(i);
	var a = [];
	while(n.length > 3) {
		var nn = n.substr(n.length-3);
		a.unshift(nn);
		n = n.substr(0,n.length-3);
	}
	if (n.length > 0)
		a.unshift(n);
	n = a.join(delimiter);
	if (d == null)
		str = n;
	else
		str = n + '.' + d;
	str = minus + str;
	return str;
}

// convert a single hex character to decimal
String.prototype.hexCharToDec = function () {
	var input = this.toUpperCase();
	var value = -1;
	if (input == "A") value = 10;
	if (input == "B") value = 11;
	if (input == "C") value = 12;
	if (input == "D") value = 13;
	if (input == "E") value = 14;
	if (input == "F") value = 15;
	if (value == -1) value = eval(input);
	return value;
}

// convert a single decimal character to a hex char
String.prototype.charToHex = function () {
	var digit = this.toInt();
	if (digit > 15) digit = (digit % 15) - 1;
	if (digit < 10)  return digit.toString();
	if (digit == 10) return "A";
	if (digit == 11) return "B";
	if (digit == 12) return "C";
	if (digit == 13) return "D";
	if (digit == 14) return "E";
	if (digit == 15) return "F";
}

// convert a 6 digit hex string (may include # char) to an associate array with red green and blue components
String.prototype.hexToDec = function () {
	var str = this.replace("#", "");
	if (str.length != 6) return null;
	var a = str.charAt(0).hexCharToDec();
	var b = str.charAt(1).hexCharToDec();
	var c = str.charAt(2).hexCharToDec();
	var d = str.charAt(3).hexCharToDec();
	var e = str.charAt(4).hexCharToDec();
	var f = str.charAt(5).hexCharToDec();
	var x = (a * 16) + b;
	var y = (c * 16) + d;
	var z = (e * 16) + f;
	var color = {"r":x, "g":y, "b":z};
	return color;
}

// convert seperate red green and blue components to a hex string
Object.prototype.rgbToHex = function () {
	var a = new String(Math.floor(this.r / 16)).charToHex();
	var b = new String(this.r % 16).charToHex();
	var c = new String(Math.floor(this.g / 16)).charToHex();
	var d = new String(this.g % 16).charToHex();
	var e = new String(Math.floor(this.b / 16)).charToHex();
	var f = new String(this.b % 16).charToHex();
	var z = "#" + a + b + c + d + e + f;
	return z;
}

// ------ Array ---------------

Object.prototype.toString = function () {
	var str = "{";
	for (var key in this) {
		str += key + ":";
		if (typeof(this[key]) == "string") str += "'";
		str += this[key];
		if (typeof(this[key]) == "string") str += "'";
		str += ", ";
	}
	str = str.subtract(2);
	return str + "}";
}

Array.prototype.ubound = function () {
	return this.length - 1;
}

Array.prototype.last = function () {
	try {
		return this[this.ubound()];
	}
	catch (ex) {
		return null;
	}
}

Array.prototype.first = function () {
	try {
		return this[0];
	}
	catch (ex) {
		return null;
	}
}

// ---------------------- Array as dictionary -----------------------------
function KeyValuePair() {}
KeyValuePair.prototype.key = null;
KeyValuePair.prototype.value = null;
KeyValuePair.prototype.toString = function () {
	return this.key + "=" + this.value;
}

Array.prototype.add = function (key, value) {
	var pair = new KeyValuePair();
	pair.key = key;
	pair.value = value;
	this.push(pair);
}

Array.prototype.at = function (key) {
	if (this.length == 0)
		return null;
	for (var i=0; i<this.length; i++ ) {
		if (this[i].key) {
			if (this[i].key == key) 
				return this[i].value;
		}
	}
	return null;
}

Array.prototype.contains = function (key) {
	return this.at(key) != null;
}

Array.prototype.remove = function (key) {
	if (this.length == 0)
		return false;
	for (var i=0; i<this.length; i++ ) {
		if (this[i].key) {
			if (this[i].key == key) 
				this.splice(i, 1);
				return true;
		}
	}
	return false;
}

Array.prototype.keys = function () {
	if (this.length == 0)
		return false;
	var keysArray = new Array();
	for (var i=0; i<this.length; i++ ) {
		if (this[i].key) {
			keysArray.push(this[i].key);
		}
	}
	return keysArray;
}

Array.prototype.values = function () {
	if (this.length == 0)
		return false;
	var valuesArray = new Array();
	for (var i=0; i<this.length; i++ ) {
		if (this[i].value) {
			valuesArray.push(this[i].value);
		}
	}
	return valuesArray;
}

Array.prototype.enumerate = function (func) {
	if ((func== null) | (this.length == 0))
		return;
	for (var i=0; i<this.length; i++ ) {
		func(this[i]);
	}
}