(function ($) {
	$.focusFirst = function (selectors) {
		if (!selectors) {
			$("input:visible, select:visible, textarea:visible").focusFirst();
		} else {
			$([]).focusFirst({fallbackFocusSelectors: selectors});
		}
	};
	
	$.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 _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();
					}
					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) {
				$focus.filter(":first").focus();
				isFocused = true;
				return false;
			} else if (options) {
				_processFallback(options);
				if (isFocused) return false;
			}
		});
	};
})(jQuery);