Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adding Rejuicer files

  • Loading branch information...
commit 77ad58bae1f632a3e07a8ab95683be530ead4c4f 1 parent 5deab73
@skroonenburg authored
Showing with 26,617 additions and 0 deletions.
  1. +34 −0 .gitignore
  2. +20 −0 Demos/Mvc/MvcDemo/MvcDemo.sln
  3. +356 −0 Demos/Mvc/MvcDemo/MvcDemo/Content/Site.css
  4. BIN  Demos/Mvc/MvcDemo/MvcDemo/Content/azure splash.png
  5. BIN  Demos/Mvc/MvcDemo/MvcDemo/Content/transformedUrlImage.png
  6. +153 −0 Demos/Mvc/MvcDemo/MvcDemo/Controllers/AccountController.cs
  7. +24 −0 Demos/Mvc/MvcDemo/MvcDemo/Controllers/HomeController.cs
  8. +1 −0  Demos/Mvc/MvcDemo/MvcDemo/Global.asax
  9. +50 −0 Demos/Mvc/MvcDemo/MvcDemo/Global.asax.cs
  10. +283 −0 Demos/Mvc/MvcDemo/MvcDemo/Models/AccountModels.cs
  11. +148 −0 Demos/Mvc/MvcDemo/MvcDemo/MvcDemo.csproj
  12. +35 −0 Demos/Mvc/MvcDemo/MvcDemo/Properties/AssemblyInfo.cs
  13. +6,111 −0 Demos/Mvc/MvcDemo/MvcDemo/Scripts/jquery-1.4.1.js
  14. +1,155 −0 Demos/Mvc/MvcDemo/MvcDemo/Scripts/jquery.validate.js
  15. +52 −0 Demos/Mvc/MvcDemo/MvcDemo/Views/Account/ChangePassword.aspx
  16. +12 −0 Demos/Mvc/MvcDemo/MvcDemo/Views/Account/ChangePasswordSuccess.aspx
  17. +46 −0 Demos/Mvc/MvcDemo/MvcDemo/Views/Account/LogOn.aspx
  18. +60 −0 Demos/Mvc/MvcDemo/MvcDemo/Views/Account/Register.aspx
  19. +12 −0 Demos/Mvc/MvcDemo/MvcDemo/Views/Home/About.aspx
  20. +28 −0 Demos/Mvc/MvcDemo/MvcDemo/Views/Home/Index.aspx
  21. +11 −0 Demos/Mvc/MvcDemo/MvcDemo/Views/Shared/Error.aspx
  22. +14 −0 Demos/Mvc/MvcDemo/MvcDemo/Views/Shared/LogOnUserControl.ascx
  23. +41 −0 Demos/Mvc/MvcDemo/MvcDemo/Views/Shared/Site.Master
  24. +35 −0 Demos/Mvc/MvcDemo/MvcDemo/Views/Web.config
  25. +30 −0 Demos/Mvc/MvcDemo/MvcDemo/Web.Debug.config
  26. +31 −0 Demos/Mvc/MvcDemo/MvcDemo/Web.Release.config
  27. +84 −0 Demos/Mvc/MvcDemo/MvcDemo/Web.config
  28. +64 −0 Demos/Mvc/MvcDemo/MvcDemo/Web.config.orig
  29. +20 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo.sln
  30. +13 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/About.aspx
  31. +17 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/About.aspx.cs
  32. +17 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/About.aspx.designer.cs
  33. +60 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/ChangePassword.aspx
  34. +17 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/ChangePassword.aspx.cs
  35. +26 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/ChangePassword.aspx.designer.cs
  36. +13 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/ChangePasswordSuccess.aspx
  37. +17 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/ChangePasswordSuccess.aspx.cs
  38. +17 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/ChangePasswordSuccess.aspx.designer.cs
  39. +49 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/Login.aspx
  40. +17 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/Login.aspx.cs
  41. +35 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/Login.aspx.designer.cs
  42. +75 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/Register.aspx
  43. +32 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/Register.aspx.cs
  44. +35 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/Register.aspx.designer.cs
  45. +18 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Account/Web.config
  46. +17 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Default.aspx
  47. +17 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Default.aspx.cs
  48. +17 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Default.aspx.designer.cs
  49. +1 −0  Demos/WebForms/WebFormsDemo/WebFormsDemo/Global.asax
  50. +63 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Global.asax.cs
  51. +35 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Properties/AssemblyInfo.cs
  52. +8,061 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Scripts/jquery-1.4.1-vsdoc.js
  53. +6,111 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Scripts/jquery-1.4.1.js
  54. +167 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Scripts/jquery-1.4.1.min.js
  55. +54 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Site.Master
  56. +17 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Site.Master.cs
  57. +51 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Site.Master.designer.cs
  58. +294 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Styles/Site.css
  59. +30 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Web.Debug.config
  60. +31 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Web.Release.config
  61. +64 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/Web.config
  62. +176 −0 Demos/WebForms/WebFormsDemo/WebFormsDemo/WebFormsDemo.csproj
  63. BIN  Lib/EcmaScript.NET.modified.dll
  64. BIN  Lib/Rejuicer.dll
  65. BIN  Lib/Yahoo.Yui.Compressor.dll
  66. +22 −0 Nuspec/Rejuicer.nuspec
  67. +19 −0 Nuspec/web.config.transform
  68. BIN  Source/Rejuicer/Lib/nunit.framework.dll
  69. +7 −0 Source/Rejuicer/Rejuicer-test/App.config
  70. +92 −0 Source/Rejuicer/Rejuicer-test/DefaultCssTransformerTest.cs
  71. +113 −0 Source/Rejuicer/Rejuicer-test/FluentConfigurerTests.cs
  72. +36 −0 Source/Rejuicer/Rejuicer-test/Properties/AssemblyInfo.cs
  73. +69 −0 Source/Rejuicer/Rejuicer-test/Rejuicer-test.csproj
  74. +125 −0 Source/Rejuicer/Rejuicer-test/RejuicerEngineTests.cs
  75. +4 −0 Source/Rejuicer/Rejuicer.gpState
  76. +32 −0 Source/Rejuicer/Rejuicer.sln
  77. +39 −0 Source/Rejuicer/Rejuicer/Configuration/Configuration.cs
  78. +27 −0 Source/Rejuicer/Rejuicer/Engine/CacheProvider.cs
  79. +44 −0 Source/Rejuicer/Rejuicer/Engine/DefaultCssTransformer.cs
  80. +85 −0 Source/Rejuicer/Rejuicer/Engine/FileResolver.cs
  81. +22 −0 Source/Rejuicer/Rejuicer/Engine/FileTransformationPipeline.cs
  82. +51 −0 Source/Rejuicer/Rejuicer/Engine/FileTransformerRegistry.cs
  83. +14 −0 Source/Rejuicer/Rejuicer/Engine/ICacheProvider.cs
  84. +13 −0 Source/Rejuicer/Rejuicer/Engine/IFileTransformer.cs
  85. +28 −0 Source/Rejuicer/Rejuicer/Engine/OutputContent.cs
  86. +256 −0 Source/Rejuicer/Rejuicer/Engine/RejuicerEngine.cs
  87. +34 −0 Source/Rejuicer/Rejuicer/Engine/RejuicerHandler.cs
  88. +68 −0 Source/Rejuicer/Rejuicer/Engine/RejuicerModule.cs
  89. +64 −0 Source/Rejuicer/Rejuicer/Fluent/CompactorConfigurer.cs
  90. +32 −0 Source/Rejuicer/Rejuicer/Fluent/DirectoryFileMatchConfigurer.cs
  91. +17 −0 Source/Rejuicer/Rejuicer/Fluent/ICompactorConfigurer.cs
  92. +13 −0 Source/Rejuicer/Rejuicer/Fluent/ICompactorContextSelector.cs
  93. +13 −0 Source/Rejuicer/Rejuicer/Fluent/ICompactorModeSelector.cs
  94. +13 −0 Source/Rejuicer/Rejuicer/Fluent/IDirectoryFileMatchConfigurer.cs
  95. +33 −0 Source/Rejuicer/Rejuicer/Fluent/OnRequest.cs
  96. +20 −0 Source/Rejuicer/Rejuicer/HtmlHelpers/IncludesCacheModel.cs
  97. +130 −0 Source/Rejuicer/Rejuicer/HtmlHelpers/Rejuicer.cs
  98. +8 −0 Source/Rejuicer/Rejuicer/Model/Context.cs
  99. +13 −0 Source/Rejuicer/Rejuicer/Model/FileMatchModel.cs
  100. +8 −0 Source/Rejuicer/Rejuicer/Model/Mode.cs
  101. +74 −0 Source/Rejuicer/Rejuicer/Model/RejuicedFileModel.cs
  102. +8 −0 Source/Rejuicer/Rejuicer/Model/ResourceType.cs
  103. +16 −0 Source/Rejuicer/Rejuicer/PathUtilities/IVirtualPathResolver.cs
  104. +1 −0  Source/Rejuicer/Rejuicer/PathUtilities/PathHelpers.cs
  105. +47 −0 Source/Rejuicer/Rejuicer/PathUtilities/VirtualPathResolver.cs
  106. +38 −0 Source/Rejuicer/Rejuicer/Properties/AssemblyInfo.cs
  107. +104 −0 Source/Rejuicer/Rejuicer/Rejuicer.csproj
  108. +4 −0 Source/Rejuicer/Rejuicer/packages.config
  109. +7 −0 Source/Rejuicer/RejuicerConfiguration-test/App.config
  110. +33 −0 Source/Rejuicer/RejuicerConfiguration-test/ConfigurationTest.cs
  111. +36 −0 Source/Rejuicer/RejuicerConfiguration-test/Properties/AssemblyInfo.cs
  112. +70 −0 Source/Rejuicer/RejuicerConfiguration-test/RejuicerConfiguration-test.csproj
  113. BIN  Source/Rejuicer/packages/YUICompressor.NET.1.5.0.0/YUICompressor.NET.1.5.0.0.nupkg
  114. BIN  Source/Rejuicer/packages/YUICompressor.NET.1.5.0.0/lib/NET20/EcmaScript.NET.modified.dll
  115. BIN  Source/Rejuicer/packages/YUICompressor.NET.1.5.0.0/lib/NET20/Iesi.Collections.dll
  116. BIN  Source/Rejuicer/packages/YUICompressor.NET.1.5.0.0/lib/NET20/Yahoo.Yui.Compressor.NET20.dll
  117. BIN  Source/Rejuicer/packages/YUICompressor.NET.1.5.0.0/lib/NET35/EcmaScript.NET.modified.dll
  118. BIN  Source/Rejuicer/packages/YUICompressor.NET.1.5.0.0/lib/NET35/Yahoo.Yui.Compressor.dll
  119. +4 −0 Source/Rejuicer/packages/repositories.config
  120. +12 −0 Source/Rejuicer/test/Rejuicer-test.VisualState.xml
  121. +7 −0 Source/Rejuicer/test/Rejuicer-test.nunit
  122. +12 −0 Source/Rejuicer/test/RejuicerConfiguration-test.VisualState.xml
  123. +6 −0 Source/Rejuicer/test/RejuicerConfiguration-test.nunit
View
34 .gitignore
@@ -0,0 +1,34 @@
+# Ignore file for Visual Studio 2008
+
+# use glob syntax
+syntax: glob
+
+# Ignore Visual Studio 2008 files
+*.obj
+*.exe
+*.pdb
+*.user
+*.aps
+*.pch
+*.vspscc
+*_i.c
+*_p.c
+*.ncb
+*.suo
+*.tlb
+*.tlh
+*.bak
+*.cache
+*.ilk
+*.log
+*.lib
+*.sbr
+*.scc
+[Bb]in
+[Dd]ebug*/
+obj/
+[Rr]elease*/
+_ReSharper*/
+[Tt]est[Rr]esult*
+[Bb]uild[Ll]og.*
+*.[Pp]ublish.xml
View
20 Demos/Mvc/MvcDemo/MvcDemo.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MvcDemo", "MvcDemo\MvcDemo.csproj", "{DF2A074E-7F68-4F71-80B5-DD47A3D556A9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DF2A074E-7F68-4F71-80B5-DD47A3D556A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF2A074E-7F68-4F71-80B5-DD47A3D556A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DF2A074E-7F68-4F71-80B5-DD47A3D556A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DF2A074E-7F68-4F71-80B5-DD47A3D556A9}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
View
356 Demos/Mvc/MvcDemo/MvcDemo/Content/Site.css
@@ -0,0 +1,356 @@
+/*----------------------------------------------------------
+The base color for this template is #5c87b2. If you'd like
+to use a different color start by replacing all instances of
+#5c87b2 with your new color.
+----------------------------------------------------------*/
+body
+{
+ background-color: #5c87b2;
+ font-size: .75em;
+ font-family: Verdana, Helvetica, Sans-Serif;
+ margin: 0;
+ padding: 0;
+ color: #696969;
+}
+
+a:link
+{
+ color: #034af3;
+ text-decoration: underline;
+}
+a:visited
+{
+ color: #505abc;
+}
+a:hover
+{
+ color: #1d60ff;
+ text-decoration: none;
+}
+a:active
+{
+ color: #12eb87;
+}
+
+p, ul
+{
+ margin-bottom: 20px;
+ line-height: 1.6em;
+}
+
+/* HEADINGS
+----------------------------------------------------------*/
+h1, h2, h3, h4, h5, h6
+{
+ font-size: 1.5em;
+ color: #000;
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+h1
+{
+ font-size: 2em;
+ padding-bottom: 0;
+ margin-bottom: 0;
+}
+h2
+{
+ padding: 0 0 10px 0;
+}
+h3
+{
+ font-size: 1.2em;
+}
+h4
+{
+ font-size: 1.1em;
+}
+h5, h6
+{
+ font-size: 1em;
+}
+
+/* this rule styles <h2> tags that are the
+first child of the left and right table columns */
+.rightColumn > h1, .rightColumn > h2, .leftColumn > h1, .leftColumn > h2
+{
+ margin-top: 0;
+}
+
+/* PRIMARY LAYOUT ELEMENTS
+----------------------------------------------------------*/
+
+/* you can specify a greater or lesser percentage for the
+page width. Or, you can specify an exact pixel width. */
+.page
+{
+ width: 90%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+#header
+{
+ position: relative;
+ margin-bottom: 0px;
+ color: #000;
+ padding: 0;
+}
+
+#header h1
+{
+ font-weight: bold;
+ padding: 5px 0;
+ margin: 0;
+ color: #fff;
+ border: none;
+ line-height: 2em;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 32px !important;
+}
+
+#main
+{
+ padding: 30px 30px 15px 30px;
+ background-color: #fff;
+ margin-bottom: 30px;
+ _height: 1px; /* only IE6 applies CSS properties starting with an underscore */
+}
+
+#footer
+{
+ color: #999;
+ padding: 10px 0;
+ text-align: center;
+ line-height: normal;
+ margin: 0;
+ font-size: .9em;
+}
+
+/* TAB MENU
+----------------------------------------------------------*/
+ul#menu
+{
+ border-bottom: 1px #5C87B2 solid;
+ padding: 0 0 2px;
+ position: relative;
+ margin: 0;
+ text-align: right;
+}
+
+ul#menu li
+{
+ display: inline;
+ list-style: none;
+}
+
+ul#menu li#greeting
+{
+ padding: 10px 20px;
+ font-weight: bold;
+ text-decoration: none;
+ line-height: 2.8em;
+ color: #fff;
+}
+
+ul#menu li a
+{
+ padding: 10px 20px;
+ font-weight: bold;
+ text-decoration: none;
+ line-height: 2.8em;
+ background-color: #e8eef4;
+ color: #034af3;
+}
+
+ul#menu li a:hover
+{
+ background-color: #fff;
+ text-decoration: none;
+}
+
+ul#menu li a:active
+{
+ background-color: #a6e2a6;
+ text-decoration: none;
+}
+
+ul#menu li.selected a
+{
+ background-color: #fff;
+ color: #000;
+}
+
+/* FORM LAYOUT ELEMENTS
+----------------------------------------------------------*/
+
+fieldset
+{
+ margin: 1em 0;
+ padding: 1em;
+ border: 1px solid #CCC;
+}
+
+fieldset p
+{
+ margin: 2px 12px 10px 10px;
+}
+
+legend
+{
+ font-size: 1.1em;
+ font-weight: 600;
+ padding: 2px 4px 8px 4px;
+}
+
+input[type="text"]
+{
+ width: 200px;
+ border: 1px solid #CCC;
+}
+
+input[type="password"]
+{
+ width: 200px;
+ border: 1px solid #CCC;
+}
+
+/* TABLE
+----------------------------------------------------------*/
+
+table
+{
+ border: solid 1px #e8eef4;
+ border-collapse: collapse;
+}
+
+table td
+{
+ padding: 5px;
+ border: solid 1px #e8eef4;
+}
+
+table th
+{
+ padding: 6px 5px;
+ text-align: left;
+ background-color: #e8eef4;
+ border: solid 1px #e8eef4;
+}
+
+/* MISC
+----------------------------------------------------------*/
+.clear
+{
+ clear: both;
+}
+
+.error
+{
+ color:Red;
+}
+
+#menucontainer
+{
+ margin-top:40px;
+}
+
+div#title
+{
+ display:block;
+ float:left;
+ text-align:left;
+}
+
+#logindisplay
+{
+ font-size:1.1em;
+ display:block;
+ text-align:right;
+ margin:10px;
+ color:White;
+}
+
+#logindisplay a:link
+{
+ color: white;
+ text-decoration: underline;
+}
+
+#logindisplay a:visited
+{
+ color: white;
+ text-decoration: underline;
+}
+
+#logindisplay a:hover
+{
+ color: white;
+ text-decoration: none;
+}
+
+/* Styles for validation helpers
+-----------------------------------------------------------*/
+.field-validation-error
+{
+ color: #ff0000;
+}
+
+.field-validation-valid
+{
+ display: none;
+}
+
+.input-validation-error
+{
+ border: 1px solid #ff0000;
+ background-color: #ffeeee;
+}
+
+.validation-summary-errors
+{
+ font-weight: bold;
+ color: #ff0000;
+}
+
+.validation-summary-valid
+{
+ display: none;
+}
+
+/* Styles for editor and display helpers
+----------------------------------------------------------*/
+.display-label,
+.editor-label,
+.display-field,
+.editor-field
+{
+ margin: 0.5em 0;
+}
+
+.text-box
+{
+ width: 30em;
+}
+
+.text-box.multi-line
+{
+ height: 6.5em;
+}
+
+.tri-state
+{
+ width: 6em;
+}
+
+.testImageCssTransform
+{
+ background-image: url(~/Content/transformedUrlImage.png);
+ width: 400px;
+ height: 72px;
+}
+
+code
+{
+ font-size: 200%;
+}
View
BIN  Demos/Mvc/MvcDemo/MvcDemo/Content/azure splash.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  Demos/Mvc/MvcDemo/MvcDemo/Content/transformedUrlImage.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
153 Demos/Mvc/MvcDemo/MvcDemo/Controllers/AccountController.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Security.Principal;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Routing;
+using System.Web.Security;
+using MvcDemo.Models;
+
+namespace MvcDemo.Controllers
+{
+
+ [HandleError]
+ public class AccountController : Controller
+ {
+
+ public IFormsAuthenticationService FormsService { get; set; }
+ public IMembershipService MembershipService { get; set; }
+
+ protected override void Initialize(RequestContext requestContext)
+ {
+ if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
+ if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
+
+ base.Initialize(requestContext);
+ }
+
+ // **************************************
+ // URL: /Account/LogOn
+ // **************************************
+
+ public ActionResult LogOn()
+ {
+ return View();
+ }
+
+ [HttpPost]
+ public ActionResult LogOn(LogOnModel model, string returnUrl)
+ {
+ if (ModelState.IsValid)
+ {
+ if (MembershipService.ValidateUser(model.UserName, model.Password))
+ {
+ FormsService.SignIn(model.UserName, model.RememberMe);
+ if (!String.IsNullOrEmpty(returnUrl))
+ {
+ return Redirect(returnUrl);
+ }
+ else
+ {
+ return RedirectToAction("Index", "Home");
+ }
+ }
+ else
+ {
+ ModelState.AddModelError("", "The user name or password provided is incorrect.");
+ }
+ }
+
+ // If we got this far, something failed, redisplay form
+ return View(model);
+ }
+
+ // **************************************
+ // URL: /Account/LogOff
+ // **************************************
+
+ public ActionResult LogOff()
+ {
+ FormsService.SignOut();
+
+ return RedirectToAction("Index", "Home");
+ }
+
+ // **************************************
+ // URL: /Account/Register
+ // **************************************
+
+ public ActionResult Register()
+ {
+ ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
+ return View();
+ }
+
+ [HttpPost]
+ public ActionResult Register(RegisterModel model)
+ {
+ if (ModelState.IsValid)
+ {
+ // Attempt to register the user
+ MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);
+
+ if (createStatus == MembershipCreateStatus.Success)
+ {
+ FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
+ return RedirectToAction("Index", "Home");
+ }
+ else
+ {
+ ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
+ }
+ }
+
+ // If we got this far, something failed, redisplay form
+ ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
+ return View(model);
+ }
+
+ // **************************************
+ // URL: /Account/ChangePassword
+ // **************************************
+
+ [Authorize]
+ public ActionResult ChangePassword()
+ {
+ ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
+ return View();
+ }
+
+ [Authorize]
+ [HttpPost]
+ public ActionResult ChangePassword(ChangePasswordModel model)
+ {
+ if (ModelState.IsValid)
+ {
+ if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
+ {
+ return RedirectToAction("ChangePasswordSuccess");
+ }
+ else
+ {
+ ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
+ }
+ }
+
+ // If we got this far, something failed, redisplay form
+ ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
+ return View(model);
+ }
+
+ // **************************************
+ // URL: /Account/ChangePasswordSuccess
+ // **************************************
+
+ public ActionResult ChangePasswordSuccess()
+ {
+ return View();
+ }
+
+ }
+}
View
24 Demos/Mvc/MvcDemo/MvcDemo/Controllers/HomeController.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+
+namespace MvcDemo.Controllers
+{
+ [HandleError]
+ public class HomeController : Controller
+ {
+ public ActionResult Index()
+ {
+ ViewData["Message"] = "Welcome to ASP.NET MVC!";
+
+ return View();
+ }
+
+ public ActionResult About()
+ {
+ return View();
+ }
+ }
+}
View
1  Demos/Mvc/MvcDemo/MvcDemo/Global.asax
@@ -0,0 +1 @@
+<%@ Application Codebehind="Global.asax.cs" Inherits="MvcDemo.MvcApplication" Language="C#" %>
View
50 Demos/Mvc/MvcDemo/MvcDemo/Global.asax.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Routing;
+using Rejuicer;
+
+namespace MvcDemo
+{
+ // Note: For instructions on enabling IIS6 or IIS7 classic mode,
+ // visit http://go.microsoft.com/?LinkId=9394801
+
+ public class MvcApplication : System.Web.HttpApplication
+ {
+ public static void RegisterRoutes(RouteCollection routes)
+ {
+ routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
+ routes.IgnoreRoute("{resource}.css/{*pathInfo}");
+ routes.MapRoute(
+ "Default", // Route name
+ "{controller}/{action}/{id}", // URL with parameters
+ new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
+ );
+
+ }
+
+ public static void ConfigureRejuicer()
+ {
+ OnRequest.ForJs("~/Combined-{0}.js")
+ .Compact
+ .FilesIn("~/Scripts/")
+ .Matching("*.js")
+ .Configure();
+
+ OnRequest.ForCss("~/Combined.css")
+ .Compact
+ .File("~/Content/Site.css")
+ .Configure();
+ }
+
+ protected void Application_Start()
+ {
+ AreaRegistration.RegisterAllAreas();
+
+ RegisterRoutes(RouteTable.Routes);
+ ConfigureRejuicer();
+ }
+ }
+}
View
283 Demos/Mvc/MvcDemo/MvcDemo/Models/AccountModels.cs
@@ -0,0 +1,283 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.Globalization;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Security;
+
+namespace MvcDemo.Models
+{
+
+ #region Models
+ [PropertiesMustMatch("NewPassword", "ConfirmPassword", ErrorMessage = "The new password and confirmation password do not match.")]
+ public class ChangePasswordModel
+ {
+ [Required]
+ [DataType(DataType.Password)]
+ [DisplayName("Current password")]
+ public string OldPassword { get; set; }
+
+ [Required]
+ [ValidatePasswordLength]
+ [DataType(DataType.Password)]
+ [DisplayName("New password")]
+ public string NewPassword { get; set; }
+
+ [Required]
+ [DataType(DataType.Password)]
+ [DisplayName("Confirm new password")]
+ public string ConfirmPassword { get; set; }
+ }
+
+ public class LogOnModel
+ {
+ [Required]
+ [DisplayName("User name")]
+ public string UserName { get; set; }
+
+ [Required]
+ [DataType(DataType.Password)]
+ [DisplayName("Password")]
+ public string Password { get; set; }
+
+ [DisplayName("Remember me?")]
+ public bool RememberMe { get; set; }
+ }
+
+ [PropertiesMustMatch("Password", "ConfirmPassword", ErrorMessage = "The password and confirmation password do not match.")]
+ public class RegisterModel
+ {
+ [Required]
+ [DisplayName("User name")]
+ public string UserName { get; set; }
+
+ [Required]
+ [DataType(DataType.EmailAddress)]
+ [DisplayName("Email address")]
+ public string Email { get; set; }
+
+ [Required]
+ [ValidatePasswordLength]
+ [DataType(DataType.Password)]
+ [DisplayName("Password")]
+ public string Password { get; set; }
+
+ [Required]
+ [DataType(DataType.Password)]
+ [DisplayName("Confirm password")]
+ public string ConfirmPassword { get; set; }
+ }
+ #endregion
+
+ #region Services
+ // The FormsAuthentication type is sealed and contains static members, so it is difficult to
+ // unit test code that calls its members. The interface and helper class below demonstrate
+ // how to create an abstract wrapper around such a type in order to make the AccountController
+ // code unit testable.
+
+ public interface IMembershipService
+ {
+ int MinPasswordLength { get; }
+
+ bool ValidateUser(string userName, string password);
+ MembershipCreateStatus CreateUser(string userName, string password, string email);
+ bool ChangePassword(string userName, string oldPassword, string newPassword);
+ }
+
+ public class AccountMembershipService : IMembershipService
+ {
+ private readonly MembershipProvider _provider;
+
+ public AccountMembershipService()
+ : this(null)
+ {
+ }
+
+ public AccountMembershipService(MembershipProvider provider)
+ {
+ _provider = provider ?? Membership.Provider;
+ }
+
+ public int MinPasswordLength
+ {
+ get
+ {
+ return _provider.MinRequiredPasswordLength;
+ }
+ }
+
+ public bool ValidateUser(string userName, string password)
+ {
+ if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
+ if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");
+
+ return _provider.ValidateUser(userName, password);
+ }
+
+ public MembershipCreateStatus CreateUser(string userName, string password, string email)
+ {
+ if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
+ if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");
+ if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email");
+
+ MembershipCreateStatus status;
+ _provider.CreateUser(userName, password, email, null, null, true, null, out status);
+ return status;
+ }
+
+ public bool ChangePassword(string userName, string oldPassword, string newPassword)
+ {
+ if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
+ if (String.IsNullOrEmpty(oldPassword)) throw new ArgumentException("Value cannot be null or empty.", "oldPassword");
+ if (String.IsNullOrEmpty(newPassword)) throw new ArgumentException("Value cannot be null or empty.", "newPassword");
+
+ // The underlying ChangePassword() will throw an exception rather
+ // than return false in certain failure scenarios.
+ try
+ {
+ MembershipUser currentUser = _provider.GetUser(userName, true /* userIsOnline */);
+ return currentUser.ChangePassword(oldPassword, newPassword);
+ }
+ catch (ArgumentException)
+ {
+ return false;
+ }
+ catch (MembershipPasswordException)
+ {
+ return false;
+ }
+ }
+ }
+
+ public interface IFormsAuthenticationService
+ {
+ void SignIn(string userName, bool createPersistentCookie);
+ void SignOut();
+ }
+
+ public class FormsAuthenticationService : IFormsAuthenticationService
+ {
+ public void SignIn(string userName, bool createPersistentCookie)
+ {
+ if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
+
+ FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
+ }
+
+ public void SignOut()
+ {
+ FormsAuthentication.SignOut();
+ }
+ }
+ #endregion
+
+ #region Validation
+ public static class AccountValidation
+ {
+ public static string ErrorCodeToString(MembershipCreateStatus createStatus)
+ {
+ // See http://go.microsoft.com/fwlink/?LinkID=177550 for
+ // a full list of status codes.
+ switch (createStatus)
+ {
+ case MembershipCreateStatus.DuplicateUserName:
+ return "Username already exists. Please enter a different user name.";
+
+ case MembershipCreateStatus.DuplicateEmail:
+ return "A username for that e-mail address already exists. Please enter a different e-mail address.";
+
+ case MembershipCreateStatus.InvalidPassword:
+ return "The password provided is invalid. Please enter a valid password value.";
+
+ case MembershipCreateStatus.InvalidEmail:
+ return "The e-mail address provided is invalid. Please check the value and try again.";
+
+ case MembershipCreateStatus.InvalidAnswer:
+ return "The password retrieval answer provided is invalid. Please check the value and try again.";
+
+ case MembershipCreateStatus.InvalidQuestion:
+ return "The password retrieval question provided is invalid. Please check the value and try again.";
+
+ case MembershipCreateStatus.InvalidUserName:
+ return "The user name provided is invalid. Please check the value and try again.";
+
+ case MembershipCreateStatus.ProviderError:
+ return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
+
+ case MembershipCreateStatus.UserRejected:
+ return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
+
+ default:
+ return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+ public sealed class PropertiesMustMatchAttribute : ValidationAttribute
+ {
+ private const string _defaultErrorMessage = "'{0}' and '{1}' do not match.";
+ private readonly object _typeId = new object();
+
+ public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty)
+ : base(_defaultErrorMessage)
+ {
+ OriginalProperty = originalProperty;
+ ConfirmProperty = confirmProperty;
+ }
+
+ public string ConfirmProperty { get; private set; }
+ public string OriginalProperty { get; private set; }
+
+ public override object TypeId
+ {
+ get
+ {
+ return _typeId;
+ }
+ }
+
+ public override string FormatErrorMessage(string name)
+ {
+ return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
+ OriginalProperty, ConfirmProperty);
+ }
+
+ public override bool IsValid(object value)
+ {
+ PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
+ object originalValue = properties.Find(OriginalProperty, true /* ignoreCase */).GetValue(value);
+ object confirmValue = properties.Find(ConfirmProperty, true /* ignoreCase */).GetValue(value);
+ return Object.Equals(originalValue, confirmValue);
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
+ public sealed class ValidatePasswordLengthAttribute : ValidationAttribute
+ {
+ private const string _defaultErrorMessage = "'{0}' must be at least {1} characters long.";
+ private readonly int _minCharacters = Membership.Provider.MinRequiredPasswordLength;
+
+ public ValidatePasswordLengthAttribute()
+ : base(_defaultErrorMessage)
+ {
+ }
+
+ public override string FormatErrorMessage(string name)
+ {
+ return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
+ name, _minCharacters);
+ }
+
+ public override bool IsValid(object value)
+ {
+ string valueAsString = value as string;
+ return (valueAsString != null && valueAsString.Length >= _minCharacters);
+ }
+ }
+ #endregion
+
+}
View
148 Demos/Mvc/MvcDemo/MvcDemo/MvcDemo.csproj
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>
+ </ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{DF2A074E-7F68-4F71-80B5-DD47A3D556A9}</ProjectGuid>
+ <ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>MvcDemo</RootNamespace>
+ <AssemblyName>MvcDemo</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <MvcBuildViews>false</MvcBuildViews>
+ <UseIISExpress>false</UseIISExpress>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="EcmaScript.NET.modified, Version=0.1.1.0, Culture=neutral, PublicKeyToken=7d53ba4f537753a5, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\..\Lib\EcmaScript.NET.modified.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="Rejuicer, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\..\Lib\Rejuicer.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Web.DynamicData" />
+ <Reference Include="System.Web.Entity" />
+ <Reference Include="System.Web.ApplicationServices" />
+ <Reference Include="System.ComponentModel.DataAnnotations">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Web" />
+ <Reference Include="System.Web.Extensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Web.Abstractions" />
+ <Reference Include="System.Web.Routing" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Configuration" />
+ <Reference Include="System.Web.Services" />
+ <Reference Include="System.EnterpriseServices" />
+ <Reference Include="Yahoo.Yui.Compressor, Version=1.5.0.0, Culture=neutral, PublicKeyToken=f8b4b81ec75097e2, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\..\Lib\Yahoo.Yui.Compressor.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Controllers\AccountController.cs" />
+ <Compile Include="Controllers\HomeController.cs" />
+ <Compile Include="Global.asax.cs">
+ <DependentUpon>Global.asax</DependentUpon>
+ </Compile>
+ <Compile Include="Models\AccountModels.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Content\azure splash.png" />
+ <Content Include="Global.asax" />
+ <Content Include="Web.config">
+ <SubType>Designer</SubType>
+ </Content>
+ <Content Include="Web.Debug.config">
+ <DependentUpon>Web.config</DependentUpon>
+ </Content>
+ <Content Include="Web.Release.config">
+ <DependentUpon>Web.config</DependentUpon>
+ </Content>
+ <Content Include="Content\Site.css" />
+ <Content Include="Scripts\jquery-1.4.1.js" />
+ <Content Include="Scripts\jquery.validate.js" />
+ <Content Include="Views\Account\ChangePassword.aspx" />
+ <Content Include="Views\Account\ChangePasswordSuccess.aspx" />
+ <Content Include="Views\Account\LogOn.aspx" />
+ <Content Include="Views\Account\Register.aspx" />
+ <Content Include="Views\Home\About.aspx" />
+ <Content Include="Views\Home\Index.aspx" />
+ <Content Include="Views\Shared\Error.aspx" />
+ <Content Include="Views\Shared\LogOnUserControl.ascx" />
+ <Content Include="Views\Shared\Site.Master" />
+ <Content Include="Views\Web.config">
+ <SubType>Designer</SubType>
+ </Content>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="App_Data\" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target> -->
+ <Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
+ <AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)" />
+ </Target>
+ <ProjectExtensions>
+ <VisualStudio>
+ <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
+ <WebProjectProperties>
+ <UseIIS>False</UseIIS>
+ <AutoAssignPort>True</AutoAssignPort>
+ <DevelopmentServerPort>5212</DevelopmentServerPort>
+ <DevelopmentServerVPath>/</DevelopmentServerVPath>
+ <IISUrl>
+ </IISUrl>
+ <NTLMAuthentication>False</NTLMAuthentication>
+ <UseCustomServer>False</UseCustomServer>
+ <CustomServerUrl>
+ </CustomServerUrl>
+ <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
+ </WebProjectProperties>
+ </FlavorProperties>
+ </VisualStudio>
+ </ProjectExtensions>
+</Project>
View
35 Demos/Mvc/MvcDemo/MvcDemo/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MvcDemo")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("MvcDemo")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6b89f54b-4e36-4bb3-9db6-ea1c314d6c0c")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
View
6,111 Demos/Mvc/MvcDemo/MvcDemo/Scripts/jquery-1.4.1.js
6,111 additions, 0 deletions not shown
View
1,155 Demos/Mvc/MvcDemo/MvcDemo/Scripts/jquery.validate.js
@@ -0,0 +1,1155 @@
+/*
+ * jQuery validation plug-in 1.6
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+ * http://docs.jquery.com/Plugins/Validation
+ *
+ * Copyright (c) 2006 - 2008 Jörn Zaefferer
+ *
+ * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+(function($) {
+
+$.extend($.fn, {
+ // http://docs.jquery.com/Plugins/Validation/validate
+ validate: function( options ) {
+
+ // 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() {
+ 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) {
+ 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) {
+ 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( {}, $.validator.defaults, options );
+ this.currentForm = form;
+ this.init();
+};
+
+$.validator.format = function(source, params) {
+ 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.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) {
+ $.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");
+ validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0] );
+ }
+ $(this.currentForm)
+ .delegate("focusin focusout keyup", ":text, :password, :file, select, textarea", delegate)
+ .delegate("click", ":radio, :checkbox, select, option", delegate);
+
+ if (this.settings.invalidHandler)
+ $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/form
+ form: function() {
+ 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 ) {
+ 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) {
+ 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() {
+ if ( $.fn.resetForm )
+ $( this.currentForm ).resetForm();
+ this.submitted = {};
+ this.prepareForm();
+ this.hideErrors();
+ this.elements().removeClass( this.settings.errorClass );
+ },
+
+ numberOfInvalids: function() {
+ 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();
+ } 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 )[0];
+ }
+
+ var rules = $(element).rules();
+ var dependencyMismatch = false;
+ for( 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) {
+ 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 (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) {
+ $.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 ( previous.old !== value ) {
+ 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 = (previous.message = response || validator.defaultMessage( element, "remote" ));
+ errors[element.name] = $.isFunction(message) ? message(value) : message;
+ validator.showErrors(errors);
+ }
+ previous.valid = valid;
+ validator.stopRequest(element, valid);
+ }
+ }, param));
+ return "pending";
+ } else if( this.pending[element.name] ) {
+ return "pending";
+ }
+ return previous.valid;
+ },
+
+ // 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;
+ }