(function() {
	$.extend($.validity.messages, {
		require: "#{field} muss angegeben werden.",

		// Format validators:
		match: "#{field} hat ein ungültiges Format.",
		integer: "#{field} muss eine positive, ganze Zahl sein.",
		date: "#{field} muss ein gültiges Datum sein.",
		email: "#{field} muss eine gültige E-Mail-Adresse sein.",
		url: "#{field} muss eine gültige URL sein.",
		number: "#{field} muss eine gültige Zahl sein.",
		zip: "#{field} muss eine gültige Postleitzahl sein.",
		phone: "#{field} muss eine gültige Telefonnummer sein.",
		guid: "#{field} muss eine gültige GUID sein (z.B. {3F2504E0-4F89-11D3-9A0C-0305E82C3301}).",
		time24: "#{field} muss eine gültige Zeit sein (hh:mm).",
		time12: "#{field} muss eine gültige Zeit sein (hh:mm AM/PM).",

		// Value range messages:
		lessThan: "#{field} muss kleiner als #{max} sein.",
		lessThanOrEqualTo: "#{field} muss kleiner oder gleich #{max} sein.",
		greaterThan: "#{field} muss grösser als #{min} sein.",
		greaterThanOrEqualTo: "#{field} muss grösser oder gleich #{min} sein.",
		range: "#{field} muss zwischen #{min} und #{max} liegen.",

		// Value length messages:
		tooLong: "#{field} kann nicht mehr als #{max} Zeichen beinhalten.",
		tooShort: "#{field} kann nicht weniger als #{min} Zeichen beinhalten.",

		// Aggregate validator messages:
		equal: "Werte passen nicht überein.",
		distinct: "Ein Wert ist doppelt vorhanden.",
		sum: "Die Werte müssen in der Summe #{sum} ergeben.",
		sumMax: "Die Summe darf maximal #{max} betragen.",
		sumMin: "Die Summe muss mindestens #{min} betragen.",

		nonHtml: "#{field} darf keine HTML-Zeichen enthalten.",

		generic: "Ungültig."
	});
	
	$.extend($.validity.patterns, {
		// Based off of http://en.wikipedia.org/wiki/Calendar_date
		date:/^([012]\d|30|31)\.([01]\d)\.(\d\d|(19|20)\d\d)$/, 
		
		// Swiss postal codes
		zip: /^[1-9][0-9]{3}$/,
		
		// Russian phone number pattern from http://regexlib.com/REDetails.aspx?regexp_id=1463
		phone: /((8|\+7)-?)?\(?\d{3,5}\)?-?\d{1}-?\d{1}-?\d{1}-?\d{1}-?\d{1}((-?\d{1})?-?\d{1})?/
	});
	
	$.validity.outputs.shop = {
		// The start function will be called when validation starts.
		// This allows you to prepare the page for validation, for instance
		// you might remove any validation messages that are already on the page.
		start: function(){ 
			$('.shop-invalid-label').hide();
			$('.shop-invalid').removeClass('shop-invalid');
		},
		
		// The end function is called when validation has concluded.
		// This allows you to flush any buffers or do anything you need to
		// after all of the validators have been called.
		// results will be the results object.
		// results.valid is a boolean representing whether the form is valid.
		// results.errors is an integer of how many errors there are.
		end: function(results) { 
			if (!results.valid && $.validity.settings.scrollTo) location.hash = $('.shop-invalid:eq(0)').attr('id');
		},
		
		// The raise function is called to raise an error for a specific input.
		// The first argument is a jQuery object of the input to raise the error message for.
		// The second argument is the string of the error message.
		raise: function($obj, msg){
			$obj.addClass('shop-invalid');
			var label = $('label[for="' + $obj.attr('id') + '"].shop-invalid-label');
			if (!label.length) {
				var label = $(document.createElement('label'));
				var repl = $('#shop-replace-invalid-label-' + $obj.attr('id'));
				if (repl.length) {
					if (repl.attr('width')) {
						width = repl.attr('width');
					} else {
						width = 0;
					}
					repl.replaceWith(label);
					label.addClass('shop-invalid-label');
					label.attr('for', $obj.attr('id'));
					label.text(msg);
					if (width) {
						label.width(parseInt(width) - 
									parseInt(label.css('padding-left')) - 
									parseInt(label.css('padding-right')) - 
									parseInt(label.css('border-left-width')) - 
									parseInt(label.css('border-right-width')));
					} else {
						label.width($obj.outerWidth() - 
									parseInt(label.css('padding-left')) - 
									parseInt(label.css('padding-right')) - 
									parseInt(label.css('border-left-width')) - 
									parseInt(label.css('border-right-width')));
					}
				} else {
					$obj.after(label);
					label.addClass('shop-invalid-label');
					label.attr('for', $obj.attr('id'));
					label.text(msg);
					label.width($obj.outerWidth() - 
								parseInt(label.css('padding-left')) - 
								parseInt(label.css('padding-right')) - 
								parseInt(label.css('border-left-width')) - 
								parseInt(label.css('border-right-width')));
				}
			} else {
				label.css('display', '');
			}
		},
		
		// The raiseAggregate function is similar to the raise function, except that
		// the $obj argument will be a jQuery object of several inputs, 
		// all of which are invalid aggregately.
		raiseAggregate: function($obj, msg){ 
			$obj.addClass('shop-invalid');
			$obj = $obj.last();
			var label = $(document.createElement('label'));
			$obj.after(label);
			label.addClass('shop-invalid-label');
			label.text(msg);
			label.attr('for', $obj.attr('id'));
			label.width($obj.outerWidth() - 
						parseInt(label.css('padding-left')) - 
						parseInt(label.css('padding-right')) - 
						parseInt(label.css('border-left-width')) - 
						parseInt(label.css('border-right-width')));
		}
	};
	
	$.validity.setup({
		outputMode: 'shop',
		scrollTo: true
	});
})();
