/*************************************************************************
jquery.tokenInput.js
Token input control.

Copyright (c) 2008  Jeff Rapp - http://tenthousandlinesofcode.com
Licensed under the MIT License (MIT-License.txt)

*************************************************************************/

$.ti = {};
var TokenInput = {
	_init: function() {

		var self = this;
		var obj = this.element;
		var myTokens = new Array();
		var o = this.options;
		tokenInput = null;

		if (obj[0].tagName == "TEXTAREA") {
			var taItems = obj.val().split('\n');
			for (i = 0; i < taItems.length; i++) {
				if (o.tokens == null)
					o.tokens = new Array();
				o.tokens.push($.trim(taItems[i]));
			}
			var id = obj.attr("id");
			var c = obj.attr("class");
			var newObj = $("<div></div>");
			obj.replaceWith(newObj);
			obj = newObj;
			obj.attr("id", id).attr("class", c);
			this.element = obj;
		}

		obj.empty();

		if (o.minHeight == 0)
			o.minHeight = obj.height();

		if (o.tokens != null) {
			if (o.tokens.length > 0) {
				//default loads here
				for (t in o.tokens) {
					var tkn = o.tokens[t];
					this.addToken(tkn);
				}
			}
		}

		obj.click(
			function() {
				if (tokenInput == null) {

					tokenInput = jQuery('<div class="token_input"></div>');
					var inputWrapper = jQuery("<div><div>");
					var inputInput = jQuery('<input size="1" />');
					inputWrapper.append(inputInput);
					tokenInput.append(inputWrapper);

					obj.append(tokenInput);

					inputInput.focus();

					var bottom = inputInput.offset().top + inputInput.height();
					var tokenContainerBottom = obj.offset().top + obj.height();

					if (bottom > tokenContainerBottom) {
						obj.height(obj.height() + inputInput.height());
					}

					inputInput.blur(
						function() {
							obj.blur();
							tokenInput.hide();
							self.resize();
							tokenInput.remove();
							tokenInput = null;
						}
					);


					inputInput.keypress(
						function(e) {
							if (e.which == 13) {

								if (self.addToken(inputInput.val()) != false) {
									obj.blur();
									tokenInput.hide();
									self.resize();
									tokenInput.remove();
									tokenInput = null;

									obj.click();
								}
							}

//                      Commented out to allow special characters to be typed into the pnlKeywords
//							if (!((e.which >= 48 && e.which <= 57) || (e.which >= 65 && e.which <= 90) || (e.which >= 97 && e.which <= 122) || e.which == 32 || e.which == 8))
//								return false;
						}
					);


				}
			}
		);

		obj.blur(
			function() {
				self.resize();
			}
		);


	},
	resize: function() {
		var obj = this.element;
		var o = this.options;

		if (obj.find(".token:last").length > 0) {
			var bottom = obj.find(".token:last").offset().top + obj.find(".token:last").height();
			var tokenContainerBottom = obj.offset().top + obj.height();
			var newHeight = bottom - obj.offset().top;
			if (bottom > tokenContainerBottom) {
				obj.height(obj.height() + obj.find(".token:last").height());
			}
			if (bottom < tokenContainerBottom && newHeight > o.minHeight) {
				obj.height(newHeight);
			}
		}
	},
	deserialize: function(str) {
		var self = this;
		var groups = str.split("&");
		for (i = 0; i < groups.length; i++) {
			var key = groups[i].split("=");
			self.addToken(unescape(key[1]));
		}
	},
	serialize: function() {
		var obj = this.element;
		var o = this.options;
		var tokens = obj.find("." + o.tokenClass);
		var ret = "";
		var pre = "";
		for (i = 0; i < tokens.length; i++) {
			var token = $(tokens[i]);
			ret += pre + escape(token.attr("id")) + "=" + escape(token.attr("title"));
			pre = "&"
		}
		return ret;
	},
	toArray: function() {
		var obj = this.element;
		var o = this.options;
		var tokens = obj.find("." + o.tokenClass);
		var ret = new Array();
		for (i = 0; i < tokens.length; i++) {
			var token = $(tokens[i]);
			ret[token.attr("id")] = token.attr("title");
		}

		return ret;
	},
	addToken: function(tokenString) {

		var obj = this.element;
		var o = this.options;

		if (tokenString == "" | tokenString == null)
			return false;

		if (o.match != null) {
			//var re = new RegExp(o.match);
			var ismatch = o.match.exec($.trim(tokenString));
			if (ismatch == null) {
				alert(o.matchErrorMessage);
				return false;
			}
		}

		var token = jQuery('<a href="javascript:void(0);"></a>')
		token.addClass(o.tokenClass).attr("id", obj.attr("id") + "_" + o.tokenID).attr("title", tokenString);

		var tokenWrapper = jQuery('<span></span>');

		var tw2 = jQuery('<span></span>');
		var tw3 = jQuery('<span></span>');
		var tw4 = jQuery('<span></span>').append('<nobr class="token_display">' + tokenString + "</nobr>");

		tw3.append(tw4);
		tw2.append(tw3);
		tokenWrapper.append(tw2);
		token.append(tokenWrapper);

		// Token Events
		token.hover(
			function() {
				jQuery(this).addClass(o.tokenHoverClass);
			},
			function() {
				jQuery(this).removeClass(o.tokenHoverClass);
			}
		);

		token.click(
			function() {
				jQuery(this).fadeOut('fast', function() { jQuery(this).remove(); });

				obj.blur();
				if (o.tokenRemovedCallback != null) {
					o.tokenRemovedCallback.call(this, tokenString, obj);
				}
				return false;
			}
		);

		obj.append(token);
		o.tokenID++;
		var self = this;
		self.resize();

		if (o.tokenAddedCallback != null) {
			o.tokenAddedCallback.call(this, tokenString, obj);
		}
	}
};

$.widget('ti.tokeninput', TokenInput); 
$.extend($.ti.tokeninput, {
	getter: "serialize toArray",
	defaults: {
		tokens: null,
		tokenClass: "token",
		tokenHoverClass: "tokenHover",
		tokenID: 0,
		match: null,
		matchErrorMessage: "Token does not match required format.",
		minHeight: 0,
		tokenAddedCallback: null,
		tokenRemovedCallback: null
	}
});

