
(function ($) {
	
	$.hasFocus = null;
	$.lastFocused = null;
	$.lastLastFocused = null;
	
	$.fn.hasFocus = function () {
		return ($.hasFocus == $(this).get(0));
	};
	$.fn.lastFocused = function () {
		return ($.lastFocused == $(this).get(0));
	};
	$.hasFocusInit = function (selector) {
		var s = selector || "input, textarea, select, a, button";
		$(s).hasFocusInit();
	};
	$.fn.hasFocusInit = function () {
		return this.each(function () {
			$(this)
				.focus(function () {
					$.hasFocus = this;
					$.lastLastFocused = $.lastFocused;
					$.lastFocused = this;
				})
				.blur(function() {
					$.hasFocus = false;
				});
		});
	};
	
	$(function () {
		var $e = $("input, textarea, select, a, button");
		// only auto load if less than 1500 elements, else jquery blows up on "unload" of all elements
		// select only elements that you need hasFocus for to fix
		if ($e.length <= 1500) $e/*.filter(':lt(1500)')*/.hasFocusInit();
	});
	
	$.fn.enter = function (fn) {
		var func = function (e) {
			var $_this = $(this);
			var default_f = function () {
							$_this.closest('form').submit();
							return false;
						};
			if (typeof fn != 'function') var f = default_f;
			else var f = fn;
			
			var k = e.charCode || e.keyCode || e.which;
			if (k == 13) {
				return f.call(this,e,default_f);
			}
		};
//		$('form').attr('onsubmit', "return false;");
//		var func = function () {return false;};
		this.find("input[type='text'], input[type='password']").andSelf().filter("input[type='text'], input[type='password']").keydown(func)/*.keyup(func).keypress(func)*/;
		return this;
	};
	
	$.focusFirst = function (selectors) {
		if (!selectors) {
			/*var $focus = */$("input:visible, select:visible, textarea:visible").focusFirst();
		} else {
			/*var $focus = */$([]).focusFirst({fallbackFocusSelectors: selectors});
//			alert($(selector).length);
//			var $focus = $(selector).filter("input:visible, select:visible, textarea:visible");
//			if (!$focus.length) $focus = $(selector).find("input:visible, select:visible, textarea:visible");
		}
//		if ($focus.length) return $focus.filter(":first").focus();
//		else return false;
	};
	
	$.fn.focusFirst = function (options) {
		isFocused = false;
		
		var isString = function (str) {
			return (typeof str != 'undefined' && (typeof str == 'string' || (typeof str == 'object' && (str.constructor.toString().match(/string/i) != null))));	
		};
		
		var isjQuery = function (obj) {
			return (obj instanceof jQuery);
		};
		
		var isUndefined = function (obj) {
			return (typeof obj == 'undefined');
		};
		
//		var isArray = function (obj) {
//			return ((obj && typeof obj == 'object' || (typeof obj == 'function'))
//					&& obj.constructor == Array);
//		};
		
		var _processFallback = function (options) {
			
			if (isUndefined(options) || isUndefined(options.fallbackFocusSelectors)) return false;

			if ($.isArray(options.fallbackFocusSelectors)) {	
				$.each(options.fallbackFocusSelectors, function () {
					
					if (this instanceof jQuery) this.focusFirst();
					else {
						if (isjQuery(this)) this.focusFirst();
						else if (isString(this)) $(this.toString()).focusFirst();
						else $(this).focusFirst();
					}
//					alert(isFocused);
					if (isFocused) return false;
				});
			} else {
				if (isjQuery(options.fallbackFocusSelectors)) options.fallbackFocusSelectors.focusFirst();
				else if (isString(options.fallbackFocusSelectors)) $(options.fallbackFocusSelectors.toString()).focusFirst(); 
				else $(options.fallbackFocusSelectors).focusFirst(); 
			}
		}
				
		if (!this.length && options && options.fallbackFocusSelectors) {
			_processFallback(options);
			return this;
		}
		
		return this.each(function () {
			var $focus = $(this).filter("input:visible:first, select:visible:first, textarea:visible:first");
			if (!$focus.length) $focus = $(this).find("input:visible:first, select:visible:first, textarea:visible:first");
			if ($focus.length) {
//				alert($focus.attr('name'));
				$focus.filter(":first").focus();
				isFocused = true;
//				alert(isFocused);
				return false;
			} else if (options) {
				_processFallback(options);
				if (isFocused) return false;
			}
		});
	};
	
	$.focusIEHack = function (selector) {
		$(selector).focusIEHack();
	};
	
	$.fn.focusIEHack = function () {
		if ($.browser.msie) {
			cnt = 0;
			$lastInput = null;
			return this.each(function () {
				var $_this = $(this);
				$(this)
					.focus(function () { setTimeout(function () {
//														if ($lastInput) {
//															$tmpLastInput = $lastInput;
//															$('.sffocus').stop(true, true);
//															if ($lastInput.hasClass('invalid')) var className = 'invalid';
//															else var className = 'sffocus';
//															$lastInput.effect('transfer', {to: $_this, className: className}, 'slow', function () { $_this.addClass('sffocus'); $tmpLastInput.removeClass('sffocus'); });
////															$lastInput.removeClass('sffocus');
//															$lastInput = $_this;
//														} else {
//															setTimeout(function () {$_this.addClass('sffocus'); $lastInput = $_this;}, 0);
//														}
														$_this.addClass('sffocus');
													}, 0); })
														
					.blur (function () { setTimeout(function () { $_this.removeClass('sffocus'); }, 0); });
			});
		} else return this;
	};
	
	$(document).ready(function() {
		$('.focusborder').focusIEHack();
	});
	
	$.fn.pollingChange = function (bind_fn, options) {
		
		if (typeof bind_fn == 'function') this.bind('pollingChange', bind_fn);
		else if (typeof bind_fn == 'object' && typeof options == 'undefined') options = bind_fn;
		
		var o = $.extend({interval: 500, val: function () { return $(this).val(); }}, options);
		if (typeof o.val != 'function') o.val = function () { return $(this).val(); };
		
		var checkChanged = function () {
			var $_this = $(this);
			var curVal;
			var lastVal = $_this.data('pollingChange_lastValue');
			$_this.data('pollingChange_lastValue', curVal = o.val.call($_this));
			if (lastVal != curVal) {
				$_this.trigger('pollingChange');
			}
		};
		
		return this.each(function () {
			
			var $_this = $(this);
			// init last value so we don't trigger the event on page load
			$_this.data('pollingChange_lastValue', o.val.call($_this));
			$_this.data('pollingChange_timer', window.setInterval(function () { checkChanged.call($_this); }, o.interval));
			$_this.bind('change keyup', function () { checkChanged.call($_this); });
		});
	};
	
	$.fn.pollingChangeRemove = function () {
		return this.each(function () {
			var $_this = $(this);
			var theTimer = $_this.data('pollingChange_timer');
			$_this.unbind('pollingChange');
			if (theTimer) clearInterval(theTimer);
			$_this.removeData('pollingChange_lastValue').removeData('pollingChange_timer');
		});
	};
	
})(jQuery);
