$.extend($.validator.prototype, {
	cachedServerValidationCall : function(settings) 
	{
		var removeBlocking = function() {
			// remove multiple request blocking
			$settingsElement.data(checkRequestKeyName, false);
		};
		
		var $settingsElement = $(settings.element);
		var checkRequestKeyName = $settingsElement.attr('id') + settings.suffix + '_checkRequest';
		var cacheKeyName = $settingsElement.attr('id') + settings.suffix + '_cached';
		var formValidator = this;

		formValidator.startRequest(settings.element);
		// prevent multiple simultaneous requests
		if ($settingsElement.data(checkRequestKeyName))
		{
			return true;
		}
		$settingsElement.data(checkRequestKeyName, true);
		
		// if result for given value is cached -> return it
		if ($settingsElement.data(cacheKeyName) && typeof ($settingsElement.data(cacheKeyName))[settings.value] != 'undefined')
		{
			removeBlocking();
			return ($settingsElement.data(cacheKeyName))[settings.value] === true;
		}
		// create cache hash if it doesn't exist
		if (!($settingsElement.data(cacheKeyName)))
		{
			$settingsElement.data(cacheKeyName, {});
		}
		
		$.ajax({
			type: "POST", 
			async: true,
			dataType : "text",
			data : settings.validationData,
			url: settings.url, 
			skipLoadingAnimation : true,
			success : function(result) 
			{
				// store value in cache (if it's not null)
				var valResult = (result.toLowerCase() == "true" ? true : false);
				if (valResult != null && typeof valResult != 'undefined')
				{
					($settingsElement.data(cacheKeyName))[settings.value] = valResult;
					
					if (valResult) {
						formValidator.prepareElement(settings.element);
						formValidator.successList.push(settings.element);
						formValidator.showErrors();
					} else {
						var errors = {};
						errors[settings.element.name] = formValidator.customMessage(settings.element.name, settings.clientValidatorName);
						formValidator.showErrors(errors);
					}
				}
				
				formValidator.stopRequest(settings.element, valResult);
				removeBlocking();
			},
			error : function(data)
			{
				removeBlocking();
				// return as if valid in case of error
				return true;
			}
		});
		
		// until response has come - return special 'pending' result
		return "pending";
	}
});
