Click here to Skip to main content
Click here to Skip to main content
Articles » Web Development » ASP.NET » General » Downloads
 
Add your own
alternative version

ASP.NET Advanced Generic Handler ASHX

, 9 Jun 2013
Take your Generic Handlers to the next level...
AdvancedHandler1.1.zip
CodeProject
CodeProject.GenericHandler
bin
CodeProject.GenericHandler.dll
CodeProject.GenericHandler.pdb
CodeProject.GenericHandler.csproj.user
Data
Demo
Handlers
Attributes
obj
Debug
CodeProject.GenericHandler.dll
CodeProject.GenericHandler.pdb
DesignTimeResolveAssemblyReferencesInput.cache
TempPE
Properties
CodeProject.suo
AdvancedHandler2.0-noexe.zip
CodeProject.GenericHandler.pdb
CodeProject.GenericHandler.csproj.user
Exceptions
CodeProject.GenericHandler.pdb
DesignTimeResolveAssemblyReferencesInput.cache
CodeProject.HandlerFormAction
bin
CodeProject.GenericHandler.pdb
CodeProject.HandlerFormAction.pdb
CodeProject.HandlerFormAction.csproj.user
obj
Debug
CodeProject.HandlerFormAction.pdb
DesignTimeResolveAssemblyReferencesInput.cache
ResolveAssemblyReference.cache
TempPE
Properties
CodeProject.suo
AdvancedHandler2.0.zip
CodeProject.GenericHandler.dll
CodeProject.GenericHandler.pdb
CodeProject.GenericHandler.csproj.user
CodeProject.GenericHandler.dll
CodeProject.GenericHandler.pdb
DesignTimeResolveAssemblyReferencesInput.cache
CodeProject.GenericHandler.dll
CodeProject.GenericHandler.pdb
CodeProject.HandlerFormAction.dll
CodeProject.HandlerFormAction.pdb
CodeProject.HandlerFormAction.csproj.user
CodeProject.HandlerFormAction.dll
CodeProject.HandlerFormAction.pdb
DesignTimeResolveAssemblyReferencesInput.cache
ResolveAssemblyReference.cache
CodeProject.suo
ASPnetAdvancedHandler2.5-noexe.zip
ASPnetAdvancedHandler
.git
hooks
applypatch-msg.sample
commit-msg.sample
post-commit.sample
post-receive.sample
post-update.sample
pre-applypatch.sample
pre-commit.sample
prepare-commit-msg.sample
pre-rebase.sample
update.sample
refs
tags
2.0
2.5
App.Utilities.suo
App.Utilities
App.Utilities.csproj.user
obj
Debug
Properties
Web
Handlers
Attributes
Exceptions
CodeProject.GenericHandler.MVCWebTest
bin
CodeProject.GenericHandler.MVCWebTest.csproj.user
Content
themes
base
images
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
Controllers
Global.asax
obj
Debug
Properties
Scripts
Views
Shared
Tests
CodeProject.GenericHandler
CodeProject.GenericHandler.csproj.user
Demo
obj
Debug
Properties
packages
EntityFramework.4.1.10331.0
EntityFramework.4.1.10331.0.nupkg
EntityFramework.4.1.10331.0.nuspec
lib
jQuery.1.5.1
Content
Scripts
jQuery.1.5.1.nupkg
jQuery.1.5.1.nuspec
jQuery.UI.Combined.1.8.11
Content
Content
themes
base
images
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
Scripts
jQuery.UI.Combined.1.8.11.nupkg
jQuery.UI.Combined.1.8.11.nuspec
jQuery.Validation.1.8.0
Content
Scripts
jQuery.Validation.1.8.0.nupkg
jQuery.Validation.1.8.0.nuspec
jQuery.vsdoc.1.5.1
Content
Scripts
jQuery.vsdoc.1.5.1.nupkg
jQuery.vsdoc.1.5.1.nuspec
Modernizr.1.7
Content
Scripts
Modernizr.1.7.nupkg
Modernizr.1.7.nuspec
README.md
ASPnetAdvancedHandler2.5.zip
COMMIT_EDITMSG
config
description
FETCH_HEAD
HEAD
applypatch-msg.sample
commit-msg.sample
post-commit.sample
post-receive.sample
post-update.sample
pre-applypatch.sample
pre-commit.sample
prepare-commit-msg.sample
pre-rebase.sample
update.sample
index
info
exclude
logs
HEAD
refs
heads
help
master
remotes
origin
HEAD
master
objects
01
1416b6f70854c5d16626879a48fe9b22d47b30
f47db1d4f09a3872ff3be09f5f0622d45849e7
03
5acb25ad0f4a50d9ea2b02d951f1fab4d7bb26
05
00866ca41975ee02ac67f321915b6d7c7592f4
09
7bd6643851ee831e0fee226e5f5bf34cbcd2c1
0a
cbe736aaea9f122e9456e684229d24e5752541
0b
739b7114f3345182401c9d09d1cb68c8df3169
0d
5b7354655a74af11c1f728455094d91984cf2e
7fcd967cd491e007d291fe0b30cb495de28238
0f
59c8d49b27fcf8b6d8d97c861c8bb207c03096
10
74a2d5ce7e8ddbc57ef1d580cf9e37a8a5550f
b743be47381bb2b6bdf7c421fc5dd177d58c91
14
5d37c58b0bb6d4deb3882b8804c04f888613b2
17
870e92ad04f51e703381a5c9e256f4a85ecc76
19
e7e0b8a7e7ed624458dd37a112cf436e61197b
1a
e27c8ec3dedf1738e6a58ca0a3d11644d6a7c5
1b
04e300db71b9a4d6dd9410a48c464ea8576212
25
70ec8e17ada98bd7b4e3e647f6be23d7b4e44b
27
84f5f87f68a4a0fb682069fd5ae99e98517d3e
2b
2c103e803e9a17dd123f8ce1d23b3572e98837
36e03291a8c462ec8f85acece4a68cddd7a64f
2c
6dd51a70558a6e84d2141e962e14c49b36085b
2e
e52ee2cb25d3473fe9b972106b27b10d417e6c
2f
aeb5de86adfceb3fa507798bee0e25d3f9dc48
30
774ac11f6ab146f6af452bce9ed76d700890e0
31
1dd32e5d0e5d2909487b13afc77dfe95abb659
34
5b20d8fd6e2205d89a788dab8ecda701e7a9e2
6ba4818dbd6eb015411fb93b033f4d21c5bdfe
df917791f169ee7996f919749cad9944fd0659
35
42991c1571636300771a6af8f1328a2b83d2fa
37
fa76f7bc788a00cf5f77f1c911c0523d59b501
39
afc44b83659a8d594d34fc5dabab7ac231645b
bafb277d5d8583104517ea6a1b9cea45174dc8
3a
d93711aabe80c9c52984e13f6577851c50e5ba
3b
b6785f51b8a4b528bf1b5c74870dd8d8884de7
bfb932dbf24acdbbd37a281a21695d1668e918
3c
e6c64d6b11e3b4f76f2422745996cb467e7479
41
22d79bfe2468b833a1ccc8453b766301fe453f
42
4caff9362bab159ec93f87893bef8314572107
ccba269b6e91bef12ad0fa18be651b5ef0ee68
44
2b7a838a9c4c0714c70079d9ecf0760bcd5c48
43fdc1a156babad4336f004eaf5ca5dfa0f9ab
45
490f93ef67c4167e0b508956d04dae7fd39933
e8928e5284adacea3f9ec07b9b50667d2ac65f
49
69685e0dfc9ed485a9590e0109c8d37480135d
4a
67cbf8e423cc8de6ea9780b322141f710dd562
4b
4fcc1e55c78e948f65672da0af023c25f0baab
a1ad970cd74b7c8b3091e2fabb2a4123775a06
f77631b9c9567ce5b6ca4c89454fc6e6d3e71c
4e
bd51f81894fe8b42c99ae91d9944ad76886753
4f
a4a539269ef205293bca6a267ad6081ef64c39
50
11b0258fada46d2986ace842b32a9201849555
88c99395a50909ead27824c8eee7cf56c19a85
51
b5f3418648892efbff0aadf354d23ba926e43c
52
e6626a072ad18c35926f81b94995a0c5eeee31
55
fb8b0d9906db57538f9e19f06763c1b153eae3
56
ff8bd77e891c0fdd9c2c8596426d2d27d6697e
57
3649574d6521231d307a259f1982f24fa5e591
58
0f1590c5af45536ca57c6693a762301d3030a6
59
48d8cc4932a48bc126343cf1d5ea2ac5f0b3c0
5a
46b47cb16631068aee9e0bd61269fc4e95e5cd
5b
5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4
a708c39172a69e069136bd1309c4322c61f571
5d
494d4582a2be2e680338bbf89a9d242e642e35
5f
14c2d58d32602117d74d2ee7a0645cc031c7fd
65
2834d79428c09cf3e6fea86539ae67c1d29f97
8252a805bbadbb5e11f5af33aea86b583365f5
66
5743481b75730f7f4ab8e96d27cc2bd98340ba
5c8ba19ce32797dd718f4e9d1b97c83941820d
67
b88882ce205a92b95737ac167fe378235b1665
69
e173a6b64d5ad196c8099fd7660a76a87252dc
6a
4f543b1d5bd34ccee2e13cc8aaf156409f0c4a
c9cf6f5ca0a28a843a489835ce738a0df45075
cb5710b14855ddd07d78d0b66ba987e1a06118
6b
42f4c57d5d9e9ea435c71d241c9accdf88a1f5
e355a49e1e8eca3deff52888910327189a51cd
6c
49d12d74ca26c578167e1e8af51339af215e84
6d
92c0d58610c15d14d63996764c44a9417baf73
6e
8718e03fa801231ad9109acf2eea00dcf273d7
71
26923cc02a5c64416f89464987870a18879258
75
b3ff7646a5290e55306d645abfff1d5cba1d45
76
18dc415f870a405ce5234d70307a2cef366e03
78
a2afa94d7ecab22c5821686ec5e1455055be48
79
065dcaa34d02a872215419c48f8d1a2dd1e41b
285779228262f9c021d1ee5a455c6f7f4c1113
30a558099bc8d92b4264eb67a0f040460f4a4f
7b
c212a8c761865ad4cccc014481d7b02cd69ea5
7c
9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30
7e
20394ab1fa50c4077f0c7f864576e0ece16a56
2de926267705be66fe914488033383a8544bf2
c70d11bfb2f77374dfd00ef61ba0c3647b5a0c
7f
fb1a8e7de817c96531ca66e8718b961dbbb770
80
db974a1176ed450d920dd6690827f628c34562
83
b7f5b78802707b6f5c0d76c9dc454b62d18e03
84
93f415da50d6a0e16e5eabb2b88acc03e5b854
86
0aea6e5e2d9441e49fe82ac2c372da5aed37cb
c2baa655eac8539db34f8d9adb69ec1226201c
87
2c7f05fa019f341b09a552a6b9d35917bb6df0
89
ff61bcba0fbfbe359c0d3734942d260b702a4b
8a
bf9e36181d4a7c1d8c50d3b5c8663d8025be10
8b
26fdda786b9a33de6e417937f0613ff5b2fff4
8c
e43de83c6a4d723604e67f60cd2447c94e3100
8f
56f29ea15515370d52a560396067bb28b52005
90
ba3de77a56187029e41295ce3887e890d2c0ab
c8f6105ee4d0fb9490fea84b6d2fce33e111e4
92
0a856e8f1c9aac7a8434ea28b013c652edf42b
94
0fa83ceed3674b77527fe985018ddaffa72b6f
83492f119193104f485d41c15a8bed5f22276f
95
3621e3b04373d30ece80550e150120847cfe41
cdfd3313e5ca576ee3388d4c7493bb50468bed
96
a0b7b3bad61f02f8d471d55aceaa712793d9e0
98
6e9feeb14939b4cc130de6fdc52e616fe97952
c1366e79114389ea72d1f127f7bb995b92779c
9e
3276b6b58dc2aed76c1c00af14a8b63c0a4904
a1
98752ce65815ca48128cdd9babadb8518af722
a2
c17f114d40c9eb6fa6401de13779b0e2700019
a4
def2a3db5c0371886e432308f8db0b8eba4d24
a5
f7942ef2b6b06e3c1aac2110fe7e5a1d88bf51
aa
5cd8a546fab787e1e557bceb747b4a747e1ee0
727ed85f6fa4d0eaa9913ad0f686f653467724
c4e204d265b4f40b962c2ed9674ac1f5f72444
ab
378bbd07785e6249a7d58c769086adbe4e6bb9
ac
8825193e844dacace58a0ba3f97b43c360dc00
8b229af950c29356abf64a6c4aa894575445f0
ad
3d6346e00f246102f72f2e026ed0491988b394
ae
ef7e7dad0b531e04893b2c9e253010a195a0e8
af
6c985b8dc49e60c7521c58918e2a05d79ef32e
b0
7c2ab2da0c761e462a0c776520fc8c4dbd3753
b1
ca52bc59da75e0f6d8df95820dcc64be664f75
b2
6a7dd8a245ce80626dbe0c18c813dca0bda1c1
70620b43a120e2c39379a0de8d164b6c02a4b9
b3
5f65b0b7c721d88437006bae19324f6ba223c3
9b7aab2bd2ce49c37e865318f40d954da7c834
b4
563c6780e7cb67eb046bc732a6e2d71426bbb2
ba
01c6171146ee34cbd841305d3c3feac3b1d878
bb
95ca5c097b4c5e8fdd9e55cd46a61ef88c2440
bd
c3535f745bc86966fb24c67d252c3ea68e8e03
d049d0bcc4a0df8b5db665d7e81422ae9f9e01
bf
037be18396ee3cafb85dc22acaf2ab22c4f683
c1
be6a12cf5079c94e3a47e17c04754702adaa1d
c2
dbb88e0e597afe867f4e36522f48cfadcd7e12
c3
3d52f730efa3aef7d0eb3a9883c6f7eaccadd5
856ce9be4b9b2da3214bb6688acb1ebfca984d
c27a28004c90979936ed242ed4530efe835793
c5
a6165e7b601c0b969c263f203dc47418378ea8
c6
9e8e6d5d5658c40f1cd793fd99c98342790270
c4b0d9ee342e5bd1570a2afab23d1e2d2e2dee
db4cf33459fc53e16a09abd22dce763bad6658
c7
6de824b47d2717c0eb90ebead24aa618a799ac
c9
2f480dfd398b1bc357feead283cef393335bbb
ca
9a76e1db434deb0c55995cde2b073843b4be47
cd
97a44903aaf380d727b997e4fa77b867f5db2a
ce
d48a4882c19462fca2aca60e87f8ea28ee064c
cf
1be490a11f287a3c2d746c31404f340ec65210
d0
28676714f231ff0f13ee76a75b41aed8415133
d1
a86daefd47d53df0ddcf537d806b9bb2f02641
d6
11b4de71c944decde29fc5edab9b6c1431dfe2
8d9ecd2f516970b3591da0aae00c5cdecdce2e
d7
a6abb6b497a05ed2de7210f5a3ce66c02126f2
dc
9b895e3d858ff905201bba43133d6024b34e73
e0
4ddfa9ddcde598a0b432f5db53a456e313d611
d8fd5c150972474311028115b23d5d908c3c29
e3
e2a12e269593c4cf5b0581c411e8be39344675
e4
49f8d7b796277f1cb1cb4833a8a65a1e9bf574
8b02042f3a97e938d405d6510a405ddd2cdd0b
e5
73d25c0a1d1155bca1a711a41ae4a1ecbdafb4
e6
34a021abe2b24ba7b94f399f2dd2fc07fddd73
39d1cad2240191bf6372a440b31e8e7e5b291f
ea
5e4d6e745c2cd4b2fecde302c9b46d22089e8b
a75a85302dba133b56027169ed3e80c84d9653
eb
68ba7e7e298b8c2d1c78054f6b8c0952beea8d
ed
ab4e97bbacf09933580eae62cfc359f3f8efc0
ee
039dc096a38a3753f92519546eee94bcfbeffa
c584bc589cf1ab1fe50781c1780f89c90aa31b
ef
da124b1fc041d169e0bb26232fccf1a9803b6b
f0
987888dab5fdadd6fd4ad93b2a43ed6b15c343
f1
e3501bda53b0f0904ff21493fcb82717802c4e
f3
74fc8cdea53d41aa9185897aa618fbcf20d60b
f4
fb1871b005573211a76239efa30843485f185e
f5
2ee39b9595d9aa943a1f45ddfb163b30e1e2eb
f9
445891330914933f9a110bd725c36d1ebdc536
fb
2488a2de506a92372d453008c66ac1f47b35fe
f9a6780834932dce35b2c2a584ab5038c15606
fd
6123fdfaf9b0f6b06c1984ce172746396184ed
ff
aaede9457f2bb1b67be259ca84fe55bc94a856
info
pack
ORIG_HEAD
packed-refs
heads
help
master
remotes
origin
HEAD
master
2.0
2.5
TAGMESSAGE
App.Utilities.suo
App.Utilities.csproj.user
bin
Debug
App.Utilities.dll
App.Utilities.pdb
Release
App.Utilities.dll
App.Utilities.pdb
DesignTimeResolveAssemblyReferencesInput.cache
TempPE
CodeProject.GenericHandler.MVCWebTest.dll
CodeProject.GenericHandler.MVCWebTest.pdb
EntityFramework.dll
CodeProject.GenericHandler.MVCWebTest.csproj.user
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
Global.asax
Models
CodeProject.GenericHandler.MVCWebTest.csprojResolveAssemblyReference.cache
CodeProject.GenericHandler.MVCWebTest.dll
CodeProject.GenericHandler.MVCWebTest.pdb
DesignTimeResolveAssemblyReferences.cache
DesignTimeResolveAssemblyReferencesInput.cache
TempPE
bin
App.Utilities.dll
App.Utilities.pdb
CodeProject.GenericHandler.dll
CodeProject.GenericHandler.pdb
CodeProject.GenericHandler.csproj.user
CodeProject.GenericHandler.csprojResolveAssemblyReference.cache
CodeProject.GenericHandler.dll
CodeProject.GenericHandler.pdb
DesignTimeResolveAssemblyReferencesInput.cache
ResolveAssemblyReference.cache
TempPE
EntityFramework.4.1.10331.0.nupkg
EntityFramework.4.1.10331.0.nuspec
EntityFramework.dll
jQuery.1.5.1.nupkg
jQuery.1.5.1.nuspec
ui-bg_flat_0_aaaaaa_40x100.png
ui-bg_flat_75_ffffff_40x100.png
ui-bg_glass_55_fbf9ee_1x400.png
ui-bg_glass_65_ffffff_1x400.png
ui-bg_glass_75_dadada_1x400.png
ui-bg_glass_75_e6e6e6_1x400.png
ui-bg_glass_95_fef1ec_1x400.png
ui-bg_highlight-soft_75_cccccc_1x100.png
ui-icons_222222_256x240.png
ui-icons_2e83ff_256x240.png
ui-icons_454545_256x240.png
ui-icons_888888_256x240.png
ui-icons_cd0a0a_256x240.png
jQuery.UI.Combined.1.8.11.nupkg
jQuery.UI.Combined.1.8.11.nuspec
jQuery.Validation.1.8.0.nupkg
jQuery.Validation.1.8.0.nuspec
jQuery.vsdoc.1.5.1.nupkg
jQuery.vsdoc.1.5.1.nuspec
Modernizr.1.7.nupkg
Modernizr.1.7.nuspec
README.md
SampleCode.zip
CodeProject.GenericHandler
bin
CodeProject.GenericHandler.dll
CodeProject.GenericHandler.pdb
CodeProject.GenericHandler.csproj.user
Data
Handlers
Attributes
obj
Debug
CodeProject.GenericHandler.dll
CodeProject.GenericHandler.pdb
DesignTimeResolveAssemblyReferencesInput.cache
TempPE
Properties
/*
* This file has been commented to support Visual Studio Intellisense.
* You should not use this file at runtime inside the browser--it is only
* intended to be used only for design-time IntelliSense.  Please use the
* standard jQuery library for all production use.
*
* Comment version: 1.8
*/

/*
* Note: While Microsoft is not the author of this file, Microsoft is
* offering you a license subject to the terms of the Microsoft Software
* License Terms for Microsoft ASP.NET Model View Controller 3.
* Microsoft reserves all other rights. The notices below are provided
* for informational purposes only and are not the license terms under
* which Microsoft distributed this file.
*
* jQuery validation plugin 1.8.0
*
* http://bassistance.de/jquery-plugins/jquery-plugin-validation/
* http://docs.jquery.com/Plugins/Validation
*
* Copyright (c) 2006 - 2011 Jörn Zaefferer
*
*/

(function($) {

$.extend($.fn, {
	// http://docs.jquery.com/Plugins/Validation/validate
	validate: function( options ) {
		/// <summary>
		/// Validates the selected form. This method sets up event handlers for submit, focus,
		/// keyup, blur and click to trigger validation of the entire form or individual
		/// elements. Each one can be disabled, see the onxxx options (onsubmit, onfocusout,
		/// onkeyup, onclick). focusInvalid focuses elements when submitting a invalid form.
		/// </summary>
		/// <param name="options" type="Options">
		/// A set of key/value pairs that configure the validate. All options are optional.
		/// </param>
		/// <returns type="Validator" />

		// if nothing is selected, return nothing; can't chain anyway
		if (!this.length) {
			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
			return;
		}

		// check if a validator for this form was already created
		var validator = $.data(this[0], 'validator');
		if ( validator ) {
			return validator;
		}
		
		validator = new $.validator( options, this[0] );
		$.data(this[0], 'validator', validator); 
		
		if ( validator.settings.onsubmit ) {
		
			// allow suppresing validation by adding a cancel class to the submit button
			this.find("input, button").filter(".cancel").click(function() {
				validator.cancelSubmit = true;
			});
			
			// when a submitHandler is used, capture the submitting button
			if (validator.settings.submitHandler) {
				this.find("input, button").filter(":submit").click(function() {
					validator.submitButton = this;
				});
			}
		
			// validate the form on submit
			this.submit( function( event ) {
				if ( validator.settings.debug )
					// prevent form submit to be able to see console output
					event.preventDefault();
					
				function handle() {
					if ( validator.settings.submitHandler ) {
						if (validator.submitButton) {
							// insert a hidden input as a replacement for the missing submit button
							var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
						}
						validator.settings.submitHandler.call( validator, validator.currentForm );
						if (validator.submitButton) {
							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
							hidden.remove();
						}
						return false;
					}
					return true;
				}
					
				// prevent submit for invalid forms or custom submit handlers
				if ( validator.cancelSubmit ) {
					validator.cancelSubmit = false;
					return handle();
				}
				if ( validator.form() ) {
					if ( validator.pendingRequest ) {
						validator.formSubmitted = true;
						return false;
					}
					return handle();
				} else {
					validator.focusInvalid();
					return false;
				}
			});
		}
		
		return validator;
	},
	// http://docs.jquery.com/Plugins/Validation/valid
	valid: function() {
		/// <summary>
		/// Checks if the selected form is valid or if all selected elements are valid.
		/// validate() needs to be called on the form before checking it using this method.
		/// </summary>
		/// <returns type="Boolean" />

        if ( $(this[0]).is('form')) {
            return this.validate().form();
        } else {
            var valid = true;
            var validator = $(this[0].form).validate();
            this.each(function() {
				valid &= validator.element(this);
            });
            return valid;
        }
    },
	// attributes: space seperated list of attributes to retrieve and remove
	removeAttrs: function(attributes) {
		/// <summary>
		/// Remove the specified attributes from the first matched element and return them.
		/// </summary>
		/// <param name="attributes" type="String">
		/// A space-seperated list of attribute names to remove.
		/// </param>
		/// <returns type="" />

		var result = {},
			$element = this;
		$.each(attributes.split(/\s/), function(index, value) {
			result[value] = $element.attr(value);
			$element.removeAttr(value);
		});
		return result;
	},
	// http://docs.jquery.com/Plugins/Validation/rules
	rules: function(command, argument) {
		/// <summary>
		/// Return the validations rules for the first selected element.
		/// </summary>
		/// <param name="command" type="String">
		/// Can be either "add" or "remove".
		/// </param>
		/// <param name="argument" type="">
		/// A list of rules to add or remove.
		/// </param>
		/// <returns type="" />

		var element = this[0];
		
		if (command) {
			var settings = $.data(element.form, 'validator').settings;
			var staticRules = settings.rules;
			var existingRules = $.validator.staticRules(element);
			switch(command) {
			case "add":
				$.extend(existingRules, $.validator.normalizeRule(argument));
				staticRules[element.name] = existingRules;
				if (argument.messages)
					settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
				break;
			case "remove":
				if (!argument) {
					delete staticRules[element.name];
					return existingRules;
				}
				var filtered = {};
				$.each(argument.split(/\s/), function(index, method) {
					filtered[method] = existingRules[method];
					delete existingRules[method];
				});
				return filtered;
			}
		}
		
		var data = $.validator.normalizeRules(
		$.extend(
			{},
			$.validator.metadataRules(element),
			$.validator.classRules(element),
			$.validator.attributeRules(element),
			$.validator.staticRules(element)
		), element);
		
		// make sure required is at front
		if (data.required) {
			var param = data.required;
			delete data.required;
			data = $.extend({required: param}, data);
		}
		
		return data;
	}
});

// Custom selectors
$.extend($.expr[":"], {
	// http://docs.jquery.com/Plugins/Validation/blank
	blank: function(a) {return !$.trim("" + a.value);},
	// http://docs.jquery.com/Plugins/Validation/filled
	filled: function(a) {return !!$.trim("" + a.value);},
	// http://docs.jquery.com/Plugins/Validation/unchecked
	unchecked: function(a) {return !a.checked;}
});

// constructor for validator
$.validator = function( options, form ) {
	this.settings = $.extend( true, {}, $.validator.defaults, options );
	this.currentForm = form;
	this.init();
};

$.validator.format = function(source, params) {
	/// <summary>
	/// Replaces {n} placeholders with arguments.
	/// One or more arguments can be passed, in addition to the string template itself, to insert
	/// into the string.
	/// </summary>
	/// <param name="source" type="String">
	/// The string to format.
	/// </param>
	/// <param name="params" type="String">
	/// The first argument to insert, or an array of Strings to insert
	/// </param>
	/// <returns type="String" />

	if ( arguments.length == 1 ) 
		return function() {
			var args = $.makeArray(arguments);
			args.unshift(source);
			return $.validator.format.apply( this, args );
		};
	if ( arguments.length > 2 && params.constructor != Array  ) {
		params = $.makeArray(arguments).slice(1);
	}
	if ( params.constructor != Array ) {
		params = [ params ];
	}
	$.each(params, function(i, n) {
		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
	});
	return source;
};

$.extend($.validator, {
	
	defaults: {
		messages: {},
		groups: {},
		rules: {},
		errorClass: "error",
		validClass: "valid",
		errorElement: "label",
		focusInvalid: true,
		errorContainer: $( [] ),
		errorLabelContainer: $( [] ),
		onsubmit: true,
		ignore: [],
		ignoreTitle: false,
		onfocusin: function(element) {
			this.lastActive = element;
				
			// hide error label and remove error class on focus if enabled
			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
				this.addWrapper(this.errorsFor(element)).hide();
			}
		},
		onfocusout: function(element) {
			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
				this.element(element);
			}
		},
		onkeyup: function(element) {
			if ( element.name in this.submitted || element == this.lastElement ) {
				this.element(element);
			}
		},
		onclick: function(element) {
			// click on selects, radiobuttons and checkboxes
			if ( element.name in this.submitted )
				this.element(element);
			// or option elements, check parent select in that case
			else if (element.parentNode.name in this.submitted)
				this.element(element.parentNode);
		},
		highlight: function( element, errorClass, validClass ) {
			$(element).addClass(errorClass).removeClass(validClass);
		},
		unhighlight: function( element, errorClass, validClass ) {
			$(element).removeClass(errorClass).addClass(validClass);
		}
	},

	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
	setDefaults: function(settings) {
		/// <summary>
		/// Modify default settings for validation.
		/// Accepts everything that Plugins/Validation/validate accepts.
		/// </summary>
		/// <param name="settings" type="Options">
		/// Options to set as default.
		/// </param>
		/// <returns type="undefined" />

		$.extend( $.validator.defaults, settings );
	},

	messages: {
		required: "This field is required.",
		remote: "Please fix this field.",
		email: "Please enter a valid email address.",
		url: "Please enter a valid URL.",
		date: "Please enter a valid date.",
		dateISO: "Please enter a valid date (ISO).",
		number: "Please enter a valid number.",
		digits: "Please enter only digits.",
		creditcard: "Please enter a valid credit card number.",
		equalTo: "Please enter the same value again.",
		accept: "Please enter a value with a valid extension.",
		maxlength: $.validator.format("Please enter no more than {0} characters."),
		minlength: $.validator.format("Please enter at least {0} characters."),
		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
		range: $.validator.format("Please enter a value between {0} and {1}."),
		max: $.validator.format("Please enter a value less than or equal to {0}."),
		min: $.validator.format("Please enter a value greater than or equal to {0}.")
	},
	
	autoCreateRanges: false,
	
	prototype: {
		
		init: function() {
			this.labelContainer = $(this.settings.errorLabelContainer);
			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
			this.submitted = {};
			this.valueCache = {};
			this.pendingRequest = 0;
			this.pending = {};
			this.invalid = {};
			this.reset();
			
			var groups = (this.groups = {});
			$.each(this.settings.groups, function(key, value) {
				$.each(value.split(/\s/), function(index, name) {
					groups[name] = key;
				});
			});
			var rules = this.settings.rules;
			$.each(rules, function(key, value) {
				rules[key] = $.validator.normalizeRule(value);
			});
			
			function delegate(event) {
				var validator = $.data(this[0].form, "validator"),
					eventType = "on" + event.type.replace(/^validate/, "");
				validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
			}
			$(this.currentForm)
				.validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
				.validateDelegate(":radio, :checkbox, select, option", "click", delegate);

			if (this.settings.invalidHandler)
				$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
		},

		// http://docs.jquery.com/Plugins/Validation/Validator/form
		form: function() {
			/// <summary>
			/// Validates the form, returns true if it is valid, false otherwise.
			/// This behaves as a normal submit event, but returns the result.
			/// </summary>
			/// <returns type="Boolean" />

			this.checkForm();
			$.extend(this.submitted, this.errorMap);
			this.invalid = $.extend({}, this.errorMap);
			if (!this.valid())
				$(this.currentForm).triggerHandler("invalid-form", [this]);
			this.showErrors();
			return this.valid();
		},
		
		checkForm: function() {
			this.prepareForm();
			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
				this.check( elements[i] );
			}
			return this.valid(); 
		},
		
		// http://docs.jquery.com/Plugins/Validation/Validator/element
		element: function( element ) {
			/// <summary>
			/// Validates a single element, returns true if it is valid, false otherwise.
			/// This behaves as validation on blur or keyup, but returns the result.
			/// </summary>
			/// <param name="element" type="Selector">
			/// An element to validate, must be inside the validated form.
			/// </param>
			/// <returns type="Boolean" />

			element = this.clean( element );
			this.lastElement = element;
			this.prepareElement( element );
			this.currentElements = $(element);
			var result = this.check( element );
			if ( result ) {
				delete this.invalid[element.name];
			} else {
				this.invalid[element.name] = true;
			}
			if ( !this.numberOfInvalids() ) {
				// Hide error containers on last error
				this.toHide = this.toHide.add( this.containers );
			}
			this.showErrors();
			return result;
		},

		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
		showErrors: function(errors) {
			/// <summary>
			/// Show the specified messages.
			/// Keys have to refer to the names of elements, values are displayed for those elements, using the configured error placement.
			/// </summary>
			/// <param name="errors" type="Object">
			/// One or more key/value pairs of input names and messages.
			/// </param>
			/// <returns type="undefined" />

			if(errors) {
				// add items to error list and map
				$.extend( this.errorMap, errors );
				this.errorList = [];
				for ( var name in errors ) {
					this.errorList.push({
						message: errors[name],
						element: this.findByName(name)[0]
					});
				}
				// remove items from success list
				this.successList = $.grep( this.successList, function(element) {
					return !(element.name in errors);
				});
			}
			this.settings.showErrors
				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
				: this.defaultShowErrors();
		},
		
		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
		resetForm: function() {
			/// <summary>
			/// Resets the controlled form.
			/// Resets input fields to their original value (requires form plugin), removes classes
			/// indicating invalid elements and hides error messages.
			/// </summary>
			/// <returns type="undefined" />

			if ( $.fn.resetForm )
				$( this.currentForm ).resetForm();
			this.submitted = {};
			this.prepareForm();
			this.hideErrors();
			this.elements().removeClass( this.settings.errorClass );
		},
		
		numberOfInvalids: function() {
			/// <summary>
			/// Returns the number of invalid fields.
			/// This depends on the internal validator state. It covers all fields only after
			/// validating the complete form (on submit or via $("form").valid()). After validating
			/// a single element, only that element is counted. Most useful in combination with the
			/// invalidHandler-option.
			/// </summary>
			/// <returns type="Number" />

			return this.objectLength(this.invalid);
		},
		
		objectLength: function( obj ) {
			var count = 0;
			for ( var i in obj )
				count++;
			return count;
		},
		
		hideErrors: function() {
			this.addWrapper( this.toHide ).hide();
		},
		
		valid: function() {
			return this.size() == 0;
		},
		
		size: function() {
			return this.errorList.length;
		},
		
		focusInvalid: function() {
			if( this.settings.focusInvalid ) {
				try {
					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
					.filter(":visible")
					.focus()
					// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
					.trigger("focusin");
				} catch(e) {
					// ignore IE throwing errors when focusing hidden elements
				}
			}
		},
		
		findLastActive: function() {
			var lastActive = this.lastActive;
			return lastActive && $.grep(this.errorList, function(n) {
				return n.element.name == lastActive.name;
			}).length == 1 && lastActive;
		},
		
		elements: function() {
			var validator = this,
				rulesCache = {};
			
			// select all valid inputs inside the form (no submit or reset buttons)
			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
			return $([]).add(this.currentForm.elements)
			.filter(":input")
			.not(":submit, :reset, :image, [disabled]")
			.not( this.settings.ignore )
			.filter(function() {
				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
			
				// select only the first element for each name, and only those with rules specified
				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
					return false;
				
				rulesCache[this.name] = true;
				return true;
			});
		},
		
		clean: function( selector ) {
			return $( selector )[0];
		},
		
		errors: function() {
			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
		},
		
		reset: function() {
			this.successList = [];
			this.errorList = [];
			this.errorMap = {};
			this.toShow = $([]);
			this.toHide = $([]);
			this.currentElements = $([]);
		},
		
		prepareForm: function() {
			this.reset();
			this.toHide = this.errors().add( this.containers );
		},
		
		prepareElement: function( element ) {
			this.reset();
			this.toHide = this.errorsFor(element);
		},
	
		check: function( element ) {
			element = this.clean( element );
			
			// if radio/checkbox, validate first element in group instead
			if (this.checkable(element)) {
			    element = this.findByName(element.name).not(this.settings.ignore)[0];
			}
			
			var rules = $(element).rules();
			var dependencyMismatch = false;
			for (var method in rules) {
				var rule = { method: method, parameters: rules[method] };
				try {
					var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
					
					// if a method indicates that the field is optional and therefore valid,
					// don't mark it as valid when there are no other rules
					if ( result == "dependency-mismatch" ) {
						dependencyMismatch = true;
						continue;
					}
					dependencyMismatch = false;
					
					if ( result == "pending" ) {
						this.toHide = this.toHide.not( this.errorsFor(element) );
						return;
					}
					
					if( !result ) {
						this.formatAndAdd( element, rule );
						return false;
					}
				} catch(e) {
					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
						 + ", check the '" + rule.method + "' method", e);
					throw e;
				}
			}
			if (dependencyMismatch)
				return;
			if ( this.objectLength(rules) )
				this.successList.push(element);
			return true;
		},
		
		// return the custom message for the given element and validation method
		// specified in the element's "messages" metadata
		customMetaMessage: function(element, method) {
			if (!$.metadata)
				return;
			
			var meta = this.settings.meta
				? $(element).metadata()[this.settings.meta]
				: $(element).metadata();
			
			return meta && meta.messages && meta.messages[method];
		},
		
		// return the custom message for the given element name and validation method
		customMessage: function( name, method ) {
			var m = this.settings.messages[name];
			return m && (m.constructor == String
				? m
				: m[method]);
		},
		
		// return the first defined argument, allowing empty strings
		findDefined: function() {
			for(var i = 0; i < arguments.length; i++) {
				if (arguments[i] !== undefined)
					return arguments[i];
			}
			return undefined;
		},
		
		defaultMessage: function( element, method) {
			return this.findDefined(
				this.customMessage( element.name, method ),
				this.customMetaMessage( element, method ),
				// title is never undefined, so handle empty string as undefined
				!this.settings.ignoreTitle && element.title || undefined,
				$.validator.messages[method],
				"<strong>Warning: No message defined for " + element.name + "</strong>"
			);
		},
		
		formatAndAdd: function( element, rule ) {
			var message = this.defaultMessage( element, rule.method ),
				theregex = /\$?\{(\d+)\}/g;
			if ( typeof message == "function" ) {
				message = message.call(this, rule.parameters, element);
			} else if (theregex.test(message)) {
				message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
			}			
			this.errorList.push({
				message: message,
				element: element
			});
			
			this.errorMap[element.name] = message;
			this.submitted[element.name] = message;
		},
		
		addWrapper: function(toToggle) {
			if ( this.settings.wrapper )
				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
			return toToggle;
		},
		
		defaultShowErrors: function() {
			for ( var i = 0; this.errorList[i]; i++ ) {
				var error = this.errorList[i];
				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
				this.showLabel( error.element, error.message );
			}
			if( this.errorList.length ) {
				this.toShow = this.toShow.add( this.containers );
			}
			if (this.settings.success) {
				for ( var i = 0; this.successList[i]; i++ ) {
					this.showLabel( this.successList[i] );
				}
			}
			if (this.settings.unhighlight) {
				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
				}
			}
			this.toHide = this.toHide.not( this.toShow );
			this.hideErrors();
			this.addWrapper( this.toShow ).show();
		},
		
		validElements: function() {
			return this.currentElements.not(this.invalidElements());
		},
		
		invalidElements: function() {
			return $(this.errorList).map(function() {
				return this.element;
			});
		},
		
		showLabel: function(element, message) {
			var label = this.errorsFor( element );
			if ( label.length ) {
				// refresh error/success class
				label.removeClass().addClass( this.settings.errorClass );
			
				// check if we have a generated label, replace the message then
				label.attr("generated") && label.html(message);
			} else {
				// create label
				label = $("<" + this.settings.errorElement + "/>")
					.attr({"for":  this.idOrName(element), generated: true})
					.addClass(this.settings.errorClass)
					.html(message || "");
				if ( this.settings.wrapper ) {
					// make sure the element is visible, even in IE
					// actually showing the wrapped element is handled elsewhere
					label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
				}
				if ( !this.labelContainer.append(label).length )
					this.settings.errorPlacement
						? this.settings.errorPlacement(label, $(element) )
						: label.insertAfter(element);
			}
			if ( !message && this.settings.success ) {
				label.text("");
				typeof this.settings.success == "string"
					? label.addClass( this.settings.success )
					: this.settings.success( label );
			}
			this.toShow = this.toShow.add(label);
		},
		
		errorsFor: function(element) {
			var name = this.idOrName(element);
    		return this.errors().filter(function() {
				return $(this).attr('for') == name;
			});
		},
		
		idOrName: function(element) {
			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
		},

		checkable: function( element ) {
			return /radio|checkbox/i.test(element.type);
		},
		
		findByName: function( name ) {
			// select by name and filter by form for performance over form.find("[name=...]")
			var form = this.currentForm;
			return $(document.getElementsByName(name)).map(function(index, element) {
				return element.form == form && element.name == name && element  || null;
			});
		},
		
		getLength: function(value, element) {
			switch( element.nodeName.toLowerCase() ) {
			case 'select':
				return $("option:selected", element).length;
			case 'input':
				if( this.checkable( element) )
					return this.findByName(element.name).filter(':checked').length;
			}
			return value.length;
		},
	
		depend: function(param, element) {
			return this.dependTypes[typeof param]
				? this.dependTypes[typeof param](param, element)
				: true;
		},
	
		dependTypes: {
			"boolean": function(param, element) {
				return param;
			},
			"string": function(param, element) {
				return !!$(param, element.form).length;
			},
			"function": function(param, element) {
				return param(element);
			}
		},
		
		optional: function(element) {
			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
		},
		
		startRequest: function(element) {
			if (!this.pending[element.name]) {
				this.pendingRequest++;
				this.pending[element.name] = true;
			}
		},
		
		stopRequest: function(element, valid) {
			this.pendingRequest--;
			// sometimes synchronization fails, make sure pendingRequest is never < 0
			if (this.pendingRequest < 0)
				this.pendingRequest = 0;
			delete this.pending[element.name];
			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
				$(this.currentForm).submit();
				this.formSubmitted = false;
			} else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
				$(this.currentForm).triggerHandler("invalid-form", [this]);
				this.formSubmitted = false;
			}
		},
		
		previousValue: function(element) {
			return $.data(element, "previousValue") || $.data(element, "previousValue", {
				old: null,
				valid: true,
				message: this.defaultMessage( element, "remote" )
			});
		}
		
	},
	
	classRuleSettings: {
		required: {required: true},
		email: {email: true},
		url: {url: true},
		date: {date: true},
		dateISO: {dateISO: true},
		dateDE: {dateDE: true},
		number: {number: true},
		numberDE: {numberDE: true},
		digits: {digits: true},
		creditcard: {creditcard: true}
	},
	
	addClassRules: function(className, rules) {
		/// <summary>
		/// Add a compound class method - useful to refactor common combinations of rules into a single
		/// class.
		/// </summary>
		/// <param name="name" type="String">
		/// The name of the class rule to add
		/// </param>
		/// <param name="rules" type="Options">
		/// The compound rules
		/// </param>
		/// <returns type="undefined" />

		className.constructor == String ?
			this.classRuleSettings[className] = rules :
			$.extend(this.classRuleSettings, className);
	},
	
	classRules: function(element) {
		var rules = {};
		var classes = $(element).attr('class');
		classes && $.each(classes.split(' '), function() {
			if (this in $.validator.classRuleSettings) {
				$.extend(rules, $.validator.classRuleSettings[this]);
			}
		});
		return rules;
	},
	
	attributeRules: function(element) {
		var rules = {};
		var $element = $(element);

		for (var method in $.validator.methods) {
			var value = $element.attr(method);
			if (value) {
				rules[method] = value;
			}
		}
		
		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
			delete rules.maxlength;
		}
		
		return rules;
	},
	
	metadataRules: function(element) {
		if (!$.metadata) return {};
		
		var meta = $.data(element.form, 'validator').settings.meta;
		return meta ?
			$(element).metadata()[meta] :
			$(element).metadata();
	},
	
	staticRules: function(element) {
		var rules = {};
		var validator = $.data(element.form, 'validator');
		if (validator.settings.rules) {
			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
		}
		return rules;
	},
	
	normalizeRules: function(rules, element) {
		// handle dependency check
		$.each(rules, function(prop, val) {
			// ignore rule when param is explicitly false, eg. required:false
			if (val === false) {
				delete rules[prop];
				return;
			}
			if (val.param || val.depends) {
				var keepRule = true;
				switch (typeof val.depends) {
					case "string":
						keepRule = !!$(val.depends, element.form).length;
						break;
					case "function":
						keepRule = val.depends.call(element, element);
						break;
				}
				if (keepRule) {
					rules[prop] = val.param !== undefined ? val.param : true;
				} else {
					delete rules[prop];
				}
			}
		});
		
		// evaluate parameters
		$.each(rules, function(rule, parameter) {
			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
		});
		
		// clean number parameters
		$.each(['minlength', 'maxlength', 'min', 'max'], function() {
			if (rules[this]) {
				rules[this] = Number(rules[this]);
			}
		});
		$.each(['rangelength', 'range'], function() {
			if (rules[this]) {
				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
			}
		});
		
		if ($.validator.autoCreateRanges) {
			// auto-create ranges
			if (rules.min && rules.max) {
				rules.range = [rules.min, rules.max];
				delete rules.min;
				delete rules.max;
			}
			if (rules.minlength && rules.maxlength) {
				rules.rangelength = [rules.minlength, rules.maxlength];
				delete rules.minlength;
				delete rules.maxlength;
			}
		}
		
		// To support custom messages in metadata ignore rule methods titled "messages"
		if (rules.messages) {
			delete rules.messages;
		}
		
		return rules;
	},
	
	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
	normalizeRule: function(data) {
		if( typeof data == "string" ) {
			var transformed = {};
			$.each(data.split(/\s/), function() {
				transformed[this] = true;
			});
			data = transformed;
		}
		return data;
	},
	
	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
	addMethod: function(name, method, message) {
		/// <summary>
		/// Add a custom validation method. It must consist of a name (must be a legal javascript 
		/// identifier), a javascript based function and a default string message.
		/// </summary>
		/// <param name="name" type="String">
		/// The name of the method, used to identify and referencing it, must be a valid javascript
		/// identifier
		/// </param>
		/// <param name="method" type="Function">
		/// The actual method implementation, returning true if an element is valid
		/// </param>
		/// <param name="message" type="String" optional="true">
		/// (Optional) The default message to display for this method. Can be a function created by 
		/// jQuery.validator.format(value). When undefined, an already existing message is used 
		/// (handy for localization), otherwise the field-specific messages have to be defined.
		/// </param>
		/// <returns type="undefined" />

		$.validator.methods[name] = method;
		$.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
		if (method.length < 3) {
			$.validator.addClassRules(name, $.validator.normalizeRule(name));
		}
	},

	methods: {

		// http://docs.jquery.com/Plugins/Validation/Methods/required
		required: function(value, element, param) {
			// check if dependency is met
			if ( !this.depend(param, element) )
				return "dependency-mismatch";
			switch( element.nodeName.toLowerCase() ) {
			case 'select':
				// could be an array for select-multiple or a string, both are fine this way
				var val = $(element).val();
				return val && val.length > 0;
			case 'input':
				if ( this.checkable(element) )
					return this.getLength(value, element) > 0;
			default:
				return $.trim(value).length > 0;
			}
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/remote
		remote: function(value, element, param) {
			if ( this.optional(element) )
				return "dependency-mismatch";
			
			var previous = this.previousValue(element);
			if (!this.settings.messages[element.name] )
				this.settings.messages[element.name] = {};
			previous.originalMessage = this.settings.messages[element.name].remote;
			this.settings.messages[element.name].remote = previous.message;
			
			param = typeof param == "string" && {url:param} || param; 
			
			if ( this.pending[element.name] ) {
				return "pending";
			}
			if ( previous.old === value ) {
				return previous.valid;
			}

			previous.old = value;
			var validator = this;
			this.startRequest(element);
			var data = {};
			data[element.name] = value;
			$.ajax($.extend(true, {
				url: param,
				mode: "abort",
				port: "validate" + element.name,
				dataType: "json",
				data: data,
				success: function(response) {
					validator.settings.messages[element.name].remote = previous.originalMessage;
					var valid = response === true;
					if ( valid ) {
						var submitted = validator.formSubmitted;
						validator.prepareElement(element);
						validator.formSubmitted = submitted;
						validator.successList.push(element);
						validator.showErrors();
					} else {
						var errors = {};
						var message = response || validator.defaultMessage(element, "remote");
						errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
						validator.showErrors(errors);
					}
					previous.valid = valid;
					validator.stopRequest(element, valid);
				}
			}, param));
			return "pending";
		},

		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
		minlength: function(value, element, param) {
			return this.optional(element) || this.getLength($.trim(value), element) >= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
		maxlength: function(value, element, param) {
			return this.optional(element) || this.getLength($.trim(value), element) <= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
		rangelength: function(value, element, param) {
			var length = this.getLength($.trim(value), element);
			return this.optional(element) || ( length >= param[0] && length <= param[1] );
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/min
		min: function( value, element, param ) {
			return this.optional(element) || value >= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/max
		max: function( value, element, param ) {
			return this.optional(element) || value <= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/range
		range: function( value, element, param ) {
			return this.optional(element) || ( value >= param[0] && value <= param[1] );
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/email
		email: function(value, element) {
			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/url
		url: function(value, element) {
			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
		},
        
		// http://docs.jquery.com/Plugins/Validation/Methods/date
		date: function(value, element) {
			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
		dateISO: function(value, element) {
			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/number
		number: function(value, element) {
			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/digits
		digits: function(value, element) {
			return this.optional(element) || /^\d+$/.test(value);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
		// based on http://en.wikipedia.org/wiki/Luhn
		creditcard: function(value, element) {
			if ( this.optional(element) )
				return "dependency-mismatch";
			// accept only digits and dashes
			if (/[^0-9-]+/.test(value))
				return false;
			var nCheck = 0,
				nDigit = 0,
				bEven = false;

			value = value.replace(/\D/g, "");

			for (var n = value.length - 1; n >= 0; n--) {
				var cDigit = value.charAt(n);
				var nDigit = parseInt(cDigit, 10);
				if (bEven) {
					if ((nDigit *= 2) > 9)
						nDigit -= 9;
				}
				nCheck += nDigit;
				bEven = !bEven;
			}

			return (nCheck % 10) == 0;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/accept
		accept: function(value, element, param) {
			param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
		equalTo: function(value, element, param) {
			// bind to the blur event of the target in order to revalidate whenever the target field is updated
			// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
			var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
				$(element).valid();
			});
			return value == target.val();
		}
		
	}
	
});

// deprecated, use $.validator.format instead
$.format = $.validator.format;

})(jQuery);

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
;(function($) {
	var pendingRequests = {};
		// Use a prefilter if available (1.5+)
	if ( $.ajaxPrefilter ) {
		$.ajaxPrefilter(function(settings, _, xhr) {
		    var port = settings.port;
		    if (settings.mode == "abort") {
			    if ( pendingRequests[port] ) {
				    pendingRequests[port].abort();
			    }				pendingRequests[port] = xhr;
		    }
	    });
	} else {
		// Proxy ajax
		var ajax = $.ajax;
		$.ajax = function(settings) {
			var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
				port = ( "port" in settings ? settings : $.ajaxSettings ).port;
			if (mode == "abort") {
				if ( pendingRequests[port] ) {
					pendingRequests[port].abort();
				}

			    return (pendingRequests[port] = ajax.apply(this, arguments));
		    }
		    return ajax.apply(this, arguments);
	    };
    }
})(jQuery);

// provides cross-browser focusin and focusout events
// IE has native support, in other browsers, use event caputuring (neither bubbles)

// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 
;(function($) {
	// only implement if not provided by jQuery core (since 1.4)
	// TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
	if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
		$.each({
			focus: 'focusin',
			blur: 'focusout'	
		}, function( original, fix ){
			$.event.special[fix] = {
				setup:function() {
					this.addEventListener( original, handler, true );
				},
				teardown:function() {
					this.removeEventListener( original, handler, true );
				},
				handler: function(e) {
					arguments[0] = $.event.fix(e);
					arguments[0].type = fix;
					return $.event.handle.apply(this, arguments);
				}
			};
			function handler(e) {
				e = $.event.fix(e);
				e.type = fix;
				return $.event.handle.call(this, e);
			}
		});
	};
	$.extend($.fn, {
		validateDelegate: function(delegate, type, handler) {
			return this.bind(type, function(event) {
				var target = $(event.target);
				if (target.is(delegate)) {
					return handler.apply(target, arguments);
				}
			});
		}
	});
})(jQuery);

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

AlexCode
Architect
Switzerland Switzerland
Senior IT Consultant working in Switzerland as Senior Software Engineer.
 
Find more at on my blog.

| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 10 Jun 2013
Article Copyright 2012 by AlexCode
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid